/* * Copyright 2014 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.logic.behavior.tree; import org.terasology.module.sandbox.API; import org.terasology.rendering.nui.properties.OneOf; /** * All children are evaluated in parallel. Policies for success and failure will define when this node finishes and in which state.<br> * <br> * <b>SUCCESS</b>: when success policy is fulfilled (one or all children <b>SUCCESS</b>).<br> * <b>FAILURE</b>, when failure policy is fulfilled (one or all children <b>FAILURE</b>).<br> * <br> * Auto generated javadoc - modify README.markdown instead! */ @API public class ParallelNode extends CompositeNode { public enum Policy { RequireOne, RequireAll } @OneOf.Enum private Policy successPolicy; @OneOf.Enum private Policy failurePolicy; public ParallelNode() { successPolicy = Policy.RequireAll; failurePolicy = Policy.RequireOne; } public ParallelNode(Policy forSuccess, Policy forFailure) { successPolicy = forSuccess; failurePolicy = forFailure; } @Override public ParallelTask createTask() { return new ParallelTask(this); } public static class ParallelTask extends CompositeTask { private int successCount; private int failureCount; public ParallelTask(ParallelNode node) { super(node); } @Override public void onInitialize() { getNode().children().forEach(this::start); successCount = 0; failureCount = 0; } @Override public Status update(float dt) { return Status.RUNNING; } @Override public void handle(Status result) { if (this.getStatus() != Status.RUNNING) { // this happens, when this task is already stopped, because of a previously finished child task // currently its not simple to correctly stop child tasks, so parallel children may continue (and finish) // its work, even if this parallel is already finished return; } if (result == Status.SUCCESS) { successCount++; if (getNode().successPolicy == Policy.RequireOne) { stop(Status.SUCCESS); } } if (result == Status.FAILURE) { failureCount++; if (getNode().failurePolicy == Policy.RequireOne) { stop(Status.FAILURE); } } if (getNode().failurePolicy == Policy.RequireAll && failureCount == getNode().children().size()) { stop(Status.FAILURE); } if (getNode().successPolicy == Policy.RequireAll && successCount == getNode().children().size()) { stop(Status.SUCCESS); } } @Override public ParallelNode getNode() { return (ParallelNode) super.getNode(); } } }