Skip to content
This repository has been archived by the owner on Oct 1, 2022. It is now read-only.

Movable Refactoring #563

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
f10bf7d
Create Entity and delegate all calls to Movable's interfaces to the C…
homoroselaps Feb 6, 2017
c7cb40f
Merge branch 'master' into MovableRefactoring
homoroselaps Feb 6, 2017
c5be586
Filled in the boilerplate code for the Components
homoroselaps Feb 16, 2017
a8547e9
missed file
homoroselaps Feb 16, 2017
400bcbd
remove String indexing, switch to Class IdentityHashMap
homoroselaps Mar 27, 2017
3d2fffa
incorporate IScheduleTimerable into Entity
homoroselaps Mar 28, 2017
7353c95
add SimpleBehaviourTree
homoroselaps Mar 28, 2017
94df9bd
Merge remote-tracking branch 'original/master' into MovableRefactoring
homoroselaps Mar 28, 2017
2ca099a
Implement Pathing Code into SteeringComponent
homoroselaps Mar 28, 2017
df49b0f
unify the Movable interface to support future refactorings
homoroselaps Mar 28, 2017
40799ce
remove author
homoroselaps Mar 28, 2017
8396115
Merge branch 'MovableInterface' into MovableRefactoring
homoroselaps Mar 29, 2017
08c034f
lambda behavior tree, basc geologist
homoroselaps Apr 1, 2017
40423a0
Entity lifecycle, convertTo
homoroselaps Apr 3, 2017
5b6bd8a
introduce OnEnable/OnDisable/OnDestroy in Component life cycle
homoroselaps Apr 4, 2017
65fd543
cleanup
homoroselaps Apr 5, 2017
1a7fffb
first draft for bearer behavior tree and component cleanup
homoroselaps Apr 13, 2017
20a7456
fix geologist behavior tree
homoroselaps Apr 13, 2017
1a4e916
first donkey behavior tree and cleanup
homoroselaps Apr 14, 2017
b1f911c
architecture runs, Donkey AI works, too many fixes
homoroselaps Apr 15, 2017
c7b8018
fix AnimationComponent
homoroselaps Apr 15, 2017
7f308b6
support game serialization
homoroselaps Apr 17, 2017
9c0c2da
Clean up code, fix static code inspection issues
homoroselaps Apr 28, 2017
aff376b
Merge remote-tracking branch 'original/master' into MovableRefactoring
homoroselaps Apr 28, 2017
d7ca002
Merge branch 'master' into MovableRefactoring and regenerate replay s…
homoroselaps Aug 31, 2017
adb8826
fix: more than one material got removed at each call
homoroselaps Oct 28, 2017
474fd44
Improve BehaviorTree nodes and design, improve donkey BT
homoroselaps Dec 4, 2017
623daf4
fix run components multiple times per timerEvent, support Notificatio…
homoroselaps Dec 4, 2017
cf110b7
fix Entity called only once
homoroselaps Dec 5, 2017
3c94118
Merge branch 'master' into MovableRefactoring
homoroselaps Dec 6, 2017
f86b87c
implement idle behavior
homoroselaps Dec 6, 2017
186e419
implement basic reaction to push requests, improve handling of entity…
homoroselaps Dec 7, 2017
2005940
Merge branch 'master' into MovableRefactoring
andreas-eberle May 6, 2018
7de0f8f
Fix some method and field names
andreas-eberle May 10, 2018
4027c57
Further renamings
andreas-eberle May 10, 2018
d140c09
Change notification retrieval to use streams instead of iterator
andreas-eberle May 10, 2018
f2bf74d
Refactor MovableWrapper
andreas-eberle May 10, 2018
918c57a
Add test map with specialists
andreas-eberle May 12, 2018
db980d2
Further refactorings and started work on Geologist
andreas-eberle May 12, 2018
116bc1f
Improve debugging node to print debug information in levels and only …
andreas-eberle May 12, 2018
ac76ec4
Add DynamicGuardSelector and make Geologist mostly working
andreas-eberle May 12, 2018
e76340f
Improve stop working behavior of geologist
andreas-eberle May 12, 2018
076a981
Make Notification implement Serializable
andreas-eberle May 12, 2018
1fd9452
Use notification to start and stop work of geologist
andreas-eberle May 13, 2018
54e5d7f
Improve tree readability by including debug message to parameters of …
andreas-eberle May 13, 2018
b3aa62f
Merge remote-tracking branch 'original/master' into MovableRefactoring
homoroselaps Jul 26, 2019
1b7175b
fix notificationCondition, fix chained animation
homoroselaps Jul 27, 2019
7761f6e
fix bearer steeringComponent idleBehavior
homoroselaps Jul 28, 2019
8ddfef7
implement convertTo other entity
homoroselaps Jul 29, 2019
a54b76c
start implementing BuildingWorker
homoroselaps Aug 3, 2019
ea0d6f8
WIP: BuildingWorkerBehaviorComponent
Jul 6, 2020
0642bbb
BuldingWorker Melter is working
Jul 9, 2020
0a3b0e9
presumably all BuildingWorkers work (tested: StoneCutter, Farmer, Shi…
Jul 16, 2020
7fccf39
basic BrickLayer Behavior implemented. not tested yet
Aug 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import jsettlers.input.tasks.ConvertGuiTask;
import jsettlers.logic.map.grid.movable.MovableGrid;
import jsettlers.logic.movable.Movable;
import jsettlers.logic.movable.MovableDataManager;
import jsettlers.logic.movable.interfaces.ILogicMovable;
import jsettlers.network.client.interfaces.ITaskScheduler;

Expand Down Expand Up @@ -60,7 +61,7 @@ public void clear() {
public void removeDeadPioneers() {
Collection<Integer> idsToRemove = new ArrayList<>(pioneerIds.size());
for (Integer pioneerId : pioneerIds) {
if (Movable.getMovableByID(pioneerId) == null) {
if (MovableDataManager.getMovableByID(pioneerId) == null) {
idsToRemove.add(pioneerId);
}
}
Expand Down Expand Up @@ -90,10 +91,11 @@ public void fill(ITaskScheduler taskScheduler, AiStatistics aiStatistics, byte p
}

public PioneerGroup getPioneersWithNoAction() {
List<Integer> pioneersWithNoAction = stream(pioneerIds).filter(pioneerId -> Movable.getMovableByID(pioneerId).getAction() == EMovableAction.NO_ACTION).collect(Collectors.toList());
List<Integer> pioneersWithNoAction = stream(pioneerIds).filter(pioneerId -> MovableDataManager.getMovableByID(pioneerId).getAction() == EMovableAction.NO_ACTION).collect(Collectors.toList());
return new PioneerGroup(pioneersWithNoAction);
}


public void addAll(List<Integer> pioneerIds) {
this.pioneerIds.addAll(pioneerIds);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import jsettlers.logic.buildings.others.StockBuilding;
import jsettlers.logic.buildings.trading.TradingBuilding;
import jsettlers.logic.movable.Movable;
import jsettlers.logic.movable.MovableDataManager;
import jsettlers.logic.movable.interfaces.ILogicMovable;
import jsettlers.network.client.task.packets.TaskPacket;
import jsettlers.network.synchronic.timer.ITaskExecutor;
Expand Down Expand Up @@ -260,7 +261,7 @@ private void setBuildingPriority(SetBuildingPriorityGuiTask guiTask) {

private void convertMovables(ConvertGuiTask guiTask) {
for (Integer currID : guiTask.getSelection()) {
ILogicMovable movable = Movable.getMovableByID(currID);
ILogicMovable movable = MovableDataManager.getMovableByID(currID);
if (movable != null) {
movable.convertTo(guiTask.getTargetType());
}
Expand All @@ -270,7 +271,7 @@ private void convertMovables(ConvertGuiTask guiTask) {

private void stopOrStartWorking(List<Integer> selectedMovables, boolean stop) {
for (Integer currID : selectedMovables) {
ILogicMovable movable = Movable.getMovableByID(currID);
ILogicMovable movable = MovableDataManager.getMovableByID(currID);
if (movable != null) {
movable.stopOrStartWorking(stop);
}
Expand All @@ -279,7 +280,7 @@ private void stopOrStartWorking(List<Integer> selectedMovables, boolean stop) {

private void killSelectedMovables(List<Integer> selectedMovables) {
for (Integer currID : selectedMovables) {
ILogicMovable curr = Movable.getMovableByID(currID);
ILogicMovable curr = MovableDataManager.getMovableByID(currID);
if (curr != null) {
curr.kill();
}
Expand All @@ -296,7 +297,7 @@ private void killSelectedMovables(List<Integer> selectedMovables) {
*/
private void moveSelectedTo(ShortPoint2D targetPosition, List<Integer> movableIds) {
if (movableIds.size() == 1) {
ILogicMovable currMovable = Movable.getMovableByID(movableIds.get(0));
ILogicMovable currMovable = MovableDataManager.getMovableByID(movableIds.get(0));
if (currMovable != null) {
currMovable.moveTo(targetPosition);
}
Expand All @@ -306,7 +307,7 @@ private void moveSelectedTo(ShortPoint2D targetPosition, List<Integer> movableId
}

private void sendMovablesNew(ShortPoint2D targetPosition, List<Integer> movableIds) {
List<ILogicMovable> movables = stream(movableIds).map(Movable::getMovableByID).filter(Objects::nonNull).collect(Collectors.toList());
List<ILogicMovable> movables = stream(movableIds).map(MovableDataManager::getMovableByID).filter(Objects::nonNull).collect(Collectors.toList());
if (movables.isEmpty()) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import jsettlers.common.position.ShortPoint2D;
import jsettlers.logic.buildings.Building;
import jsettlers.logic.buildings.IBuildingsGrid;
import jsettlers.logic.movable.EntityFactory;
import jsettlers.logic.movable.Movable;
import jsettlers.logic.movable.interfaces.ILogicMovable;
import jsettlers.logic.player.Player;
Expand Down Expand Up @@ -56,7 +57,7 @@ protected int subTimerEvent() {
ILogicMovable movableAtDoor = super.grid.getMovable(super.getDoor());

if (movableAtDoor == null) {
movableAtDoor = new Movable(super.grid.getMovableGrid(), getMovableType(), getDoor(), super.getPlayer());
movableAtDoor = EntityFactory.CreateMovable(super.grid.getMovableGrid(), getMovableType(), getDoor(), super.getPlayer());
produced++;

if (produced < getProduceLimit()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@
import jsettlers.logic.map.loading.list.MapList;
import jsettlers.logic.map.loading.newmap.MapFileHeader;
import jsettlers.logic.map.loading.newmap.MapFileHeader.MapType;
import jsettlers.logic.movable.EntityFactory;
import jsettlers.logic.movable.Movable;
import jsettlers.logic.movable.MovableDataManager;
import jsettlers.logic.movable.interfaces.AbstractMovableGrid;
import jsettlers.logic.movable.interfaces.IAttackable;
import jsettlers.logic.movable.interfaces.ILogicMovable;
Expand Down Expand Up @@ -430,7 +432,7 @@ public final boolean isInBounds(int x, int y) {
}

final ILogicMovable createNewMovableAt(ShortPoint2D pos, EMovableType type, Player player) {
return new Movable(movablePathfinderGrid, type, pos, player);
return EntityFactory.CreateMovable(movablePathfinderGrid, type, pos, player);
}

/**
Expand Down Expand Up @@ -930,7 +932,7 @@ public void hitWithArrowAt(ArrowObject arrow) {
@Override
public void spawnDonkey(ShortPoint2D position, Player player) {
Player realPlayer = partitionsGrid.getPlayer(player.getPlayerId());
ILogicMovable donkey = new Movable(movablePathfinderGrid, EMovableType.DONKEY, position, realPlayer);
ILogicMovable donkey = EntityFactory.CreateMovable(movablePathfinderGrid, EMovableType.DONKEY, position, realPlayer);
donkey.leavePosition();
}

Expand Down Expand Up @@ -1924,7 +1926,7 @@ public final IMapObject getMapObjectsAt(short x, short y) {

@Override
public final ConcurrentLinkedQueue<? extends IViewDistancable> getMovableViewDistancables() {
return Movable.getAllMovables();
return MovableDataManager.allMovables();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
package jsettlers.logic.movable;

import java.util.Iterator;

import jsettlers.common.movable.EMovableAction;
import jsettlers.common.movable.EMovableType;
import jsettlers.logic.constants.MatchConstants;
import jsettlers.logic.movable.components.SteeringComponent;
import jsettlers.logic.movable.simplebehaviortree.Decorator;
import jsettlers.logic.movable.simplebehaviortree.IBooleanConditionFunction;
import jsettlers.logic.movable.simplebehaviortree.INodeStatusActionConsumer;
import jsettlers.logic.movable.simplebehaviortree.INodeStatusActionFunction;
import jsettlers.logic.movable.simplebehaviortree.Node;
import jsettlers.logic.movable.simplebehaviortree.NodeStatus;
import jsettlers.logic.movable.simplebehaviortree.Tick;
import jsettlers.logic.movable.simplebehaviortree.nodes.Action;
import jsettlers.logic.movable.simplebehaviortree.nodes.Condition;
import jsettlers.logic.movable.simplebehaviortree.nodes.Failer;
import jsettlers.logic.movable.simplebehaviortree.nodes.Guard;
import jsettlers.logic.movable.simplebehaviortree.nodes.Inverter;
import jsettlers.logic.movable.simplebehaviortree.nodes.MemSelector;
import jsettlers.logic.movable.simplebehaviortree.nodes.MemSequence;
import jsettlers.logic.movable.simplebehaviortree.nodes.Parallel;
import jsettlers.logic.movable.simplebehaviortree.nodes.Property;
import jsettlers.logic.movable.simplebehaviortree.nodes.Repeat;
import jsettlers.logic.movable.simplebehaviortree.nodes.Selector;
import jsettlers.logic.movable.simplebehaviortree.nodes.Sequence;
import jsettlers.logic.movable.simplebehaviortree.nodes.Succeeder;
import jsettlers.logic.movable.simplebehaviortree.nodes.Wait;

public final class BehaviorTreeHelper {

/* --- Node Factory --- */

public static Action<Context> Action(INodeStatusActionConsumer<Context> action) {
return new Action<Context>(action);
}

public static Action<Context> Action(INodeStatusActionFunction<Context> action) {
return new Action<Context>(action);
}

public static Condition<Context> Condition(IBooleanConditionFunction<Context> condition) {
return new Condition<>(condition);
}

public static Failer<Context> Failer() {
return new Failer<>();
}

public static Guard<Context> Guard(IBooleanConditionFunction<Context> condition, Node<Context> child) {
return new Guard<Context>(condition, child);
}

public static Guard<Context> Guard(IBooleanConditionFunction<Context> condition, boolean shouldBe, Node<Context> child) {
return new Guard<Context>(condition, shouldBe, child);
}

public static Inverter<Context> Inverter(Node<Context> child) {
return new Inverter<>(child);
}

@SafeVarargs
public static MemSelector<Context> MemSelector(Node<Context>... children) {
return new MemSelector<>(children);
}

@SafeVarargs
public static MemSequence<Context> MemSequence(Node<Context>... children) {
return new MemSequence<>(children);
}

@SafeVarargs
public static Parallel<Context> Parallel(Parallel.Policy successPolicy, boolean preemptive, Node<Context>... children) {
return new Parallel<Context>(successPolicy, preemptive, children);
}

public static Repeat<Context> Repeat(Repeat.Policy policy, Node<Context> condition, Node<Context> child) {
return new Repeat<>(policy, condition, child);
}

public static Repeat<Context> Repeat(Node<Context> condition, Node<Context> child) {
return new Repeat<>(condition, child);
}

@SafeVarargs
public static Selector<Context> Selector(Node<Context>... children) {
return new Selector<>(children);
}

@SafeVarargs
public static Sequence<Context> Sequence(Node<Context>... children) {
return new Sequence<>(children);
}

public static Succeeder<Context> Succeeder() {
return new Succeeder<>();
}

public static Wait<Context> Wait(Node<Context> condition) {
return new Wait<>(condition);
}

public static NotificationCondition NotificationCondition(Class<? extends Notification> type) {
return new NotificationCondition(type);
}

public static NotificationCondition NotificationCondition(Class<? extends Notification> type, boolean consume) {
return new NotificationCondition(type, consume);
}

public static Node<Context> WaitForTargetReached_FailIfNotReachable() {
// wait for targetReached, but abort if target not reachable
return Sequence(
Inverter(NotificationCondition(SteeringComponent.TargetNotReachedTrigger.class, true)),
Wait(NotificationCondition(SteeringComponent.TargetReachedTrigger.class, true))
);
}

public static Property<Context, Boolean> SetAttackableWhile(boolean value, Node<Context> child) {
return new Property<>(
(c,v)->{c.entity.attC().IsAttackable(v);},
(c)->{return c.entity.attC().IsAttackable();},
value,
child);
}

public static Property<Context, Boolean> SetIdleBehaviorActiveWhile(boolean value, Node<Context> child) {
return new Property<>(
(c,v)->{c.entity.steerC().IsIdleBehaviorActive(v);},
(c)->c.entity.steerC().IsIdleBehaviorActive(),
value,
child);
}

public static Guard<Context> TriggerGuard(Class<? extends Notification> type, Node<Context> child) {
return new Guard<>(entity -> entity.comp.getNotificationsIt(type).hasNext(), true, child);
}

public static Action<Context> StartAnimation(EMovableAction animation, short duration) {
return new Action<>(c -> {
c.entity.aniC().startAnimation(animation, duration);
});
}

public static void convertTo(Entity entity, EMovableType type) {
Entity blueprint = EntityFactory.CreateEntity(entity.gameC().getMovableGrid(), type, entity.movC().getPos(), entity.movC().getPlayer());
entity.convertTo(blueprint);
}

public static <T> Node<T> Optional(Node<T> child) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a different name. An Optional is a fixed thing in java8, which makes this confusing.

return new Selector<T>(child, new Succeeder<T>());
}

public static Sleep Sleep(int milliseconds) {
return new Sleep(milliseconds);
}

public static class Sleep extends Node<Context> {
private static final long serialVersionUID = 8774557186392581042L;
final int delay;
int endTime;
public Sleep(int milliseconds) {
super();
delay = milliseconds;
}

@Override
public NodeStatus onTick(Tick<Context> tick) {
int remaining = endTime - MatchConstants.clock().getTime();
if (remaining <= 0) return NodeStatus.Success;
tick.Target.entity.setInvocationDelay(remaining);
return NodeStatus.Running;
}

@Override
public void onOpen(Tick<Context> tick) {
endTime = MatchConstants.clock().getTime() + delay;
}
}

public static Node<Context> WaitForNotification(Class<? extends Notification> type, boolean consume) {
return Wait(NotificationCondition(type, consume));
}

public static Debug $(String msg, Node<Context> child) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please name this method debug or something like that. I first thought this is a crazy new syntax...

return new Debug(msg, child);
}

public static Debug $(String msg) {
return new Debug(msg);
}

public static class Debug extends Decorator<Context> {
private static final boolean DEBUG = false;
private static final long serialVersionUID = 9019598003328102086L;
private final String message;
public Debug(String message) {
super(null);
this.message = message;
}

public Debug(String message, Node<Context> child) {
super(child);
this.message = message;
}

@Override
public NodeStatus onTick(Tick<Context> tick) {
if (DEBUG) System.out.println(message);
if (child != null) {
NodeStatus result = child.execute(tick);
String res = result == NodeStatus.Success ? "Success" : result == NodeStatus.Failure ? "Failure" : "Running";
if (DEBUG) System.out.println(message + ": " + res);
return result;
}
return NodeStatus.Success;
}
}

public static class NotificationCondition extends Condition<Context> {
private static final long serialVersionUID = 1780756145252644771L;

public NotificationCondition(Class<? extends Notification> type) {
this(type, false);
}

public NotificationCondition(Class<? extends Notification> type, boolean consume) {
super((context)->{
Iterator<? extends Notification> it = context.comp.getNotificationsIt(type);
if (it.hasNext()) {
if (consume) context.comp.consumeNotification(it.next());
return true;
}
return false;
});
}
}
}
18 changes: 18 additions & 0 deletions jsettlers.logic/src/main/java/jsettlers/logic/movable/Context.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package jsettlers.logic.movable;

import jsettlers.logic.movable.components.Component;

/**
* Created by homoroselaps
*/

public final class Context {
public final Entity entity;
public final Component comp;
public Entity getEntity() { return entity; }
public Component getComponent() { return comp; }
public Context(Entity entity, Component component) {
this.entity = entity;
this.comp = component;
}
}
Loading