diff --git a/go.graphics.android/src/main/java/go/graphics/android/GOSurfaceView.java b/go.graphics.android/src/main/java/go/graphics/android/GOSurfaceView.java index 4a2fc58e22..984c3b0d36 100644 --- a/go.graphics.android/src/main/java/go/graphics/android/GOSurfaceView.java +++ b/go.graphics.android/src/main/java/go/graphics/android/GOSurfaceView.java @@ -282,4 +282,9 @@ public GLDrawContext getDrawContext() { public void setContextDestroyedListener(IContextDestroyedListener contextDestroyedListener) { this.contextDestroyedListener = contextDestroyedListener; } + + @Override + protected int getCurrentModifiers() { + return GOEvent.MODIFIER_ALT | GOEvent.MODIFIER_CTRL | GOEvent.MODIFIER_SHIFT; + } } diff --git a/go.graphics.swing/src/main/java/go/graphics/swing/event/swingInterpreter/GOSwingEventConverter.java b/go.graphics.swing/src/main/java/go/graphics/swing/event/swingInterpreter/GOSwingEventConverter.java index 7c1100970b..531fe6b441 100644 --- a/go.graphics.swing/src/main/java/go/graphics/swing/event/swingInterpreter/GOSwingEventConverter.java +++ b/go.graphics.swing/src/main/java/go/graphics/swing/event/swingInterpreter/GOSwingEventConverter.java @@ -22,6 +22,7 @@ import java.awt.event.ComponentListener; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; +import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; @@ -32,6 +33,7 @@ import java.lang.reflect.Field; import go.graphics.UIPoint; +import go.graphics.event.GOEvent; import go.graphics.event.GOEventHandlerProvider; import go.graphics.event.interpreter.AbstractEventConverter; @@ -54,6 +56,8 @@ public class GOSwingEventConverter extends AbstractEventConverter private int scaleFactor = 1; + private int modifiers; + /** * Creates a new event converter, that converts swing events to go events. * @@ -108,25 +112,30 @@ private void updateScaleFactor(Component component) { @Override public void mouseEntered(MouseEvent e) { + updateModifiers(e); startHover(convertToLocal(e)); } @Override public void mouseMoved(MouseEvent e) { + updateModifiers(e); updateHoverPosition(convertToLocal(e)); } @Override public void mouseExited(MouseEvent e) { + updateModifiers(e); endHover(convertToLocal(e)); } @Override public void mouseClicked(MouseEvent e) { + // ignored - we trace down/up } @Override public void mousePressed(MouseEvent e) { + updateModifiers(e); int mouseButton = e.getButton(); UIPoint local = convertToLocal(e); if (mouseButton == MouseEvent.BUTTON1) { @@ -142,6 +151,7 @@ public void mousePressed(MouseEvent e) { @Override public void mouseDragged(MouseEvent e) { + updateModifiers(e); UIPoint local = convertToLocal(e); updateDrawPosition(local); updatePanPosition(local); @@ -150,6 +160,7 @@ public void mouseDragged(MouseEvent e) { @Override public void mouseReleased(MouseEvent e) { + updateModifiers(e); UIPoint local = convertToLocal(e); if (e.getButton() == MouseEvent.BUTTON1) { endDraw(local); @@ -164,19 +175,9 @@ public void mouseReleased(MouseEvent e) { @Override public void keyPressed(KeyEvent e) { + updateModifiers(e); String text = getKeyName(e); startKeyEvent(text); - /* - * if (ongoingKeyEvent == null) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { ongoingKeyEvent.setHandler(getCancelHandler()); } else if - * (e.getKeyCode() == KeyEvent.VK_UP) { ongoingKeyEvent.setHandler(getPanHandler(0, -KEYPAN)); } else if (e.getKeyCode() == KeyEvent.VK_DOWN) - * { ongoingKeyEvent.setHandler(getPanHandler(0, KEYPAN)); } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { - * ongoingKeyEvent.setHandler(getPanHandler(KEYPAN, 0)); } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { - * ongoingKeyEvent.setHandler(getPanHandler(-KEYPAN, 0)); } - * - * provider.handleEvent(ongoingKeyEvent); - * - * ongoingKeyEvent.started(); } - */ } private String getKeyName(KeyEvent e) { @@ -253,7 +254,7 @@ private String getKeyName(KeyEvent e) { text = "BACK_SPACE"; break; default: - text = "" + e.getKeyChar(); + text = Character.toString(e.getKeyChar()); } } return text; @@ -261,15 +262,32 @@ private String getKeyName(KeyEvent e) { @Override public void keyReleased(KeyEvent e) { + updateModifiers(e); endKeyEvent(getKeyName(e)); } + private void updateModifiers(InputEvent e) { + int swingMod = e.getModifiers(); + this.modifiers = 0; + if ((swingMod & InputEvent.ALT_MASK) != 0) { + this.modifiers |= GOEvent.MODIFIER_ALT; + } + if ((swingMod & InputEvent.CTRL_MASK) != 0) { + this.modifiers |= GOEvent.MODIFIER_CTRL; + } + if ((swingMod & InputEvent.SHIFT_MASK) != 0) { + this.modifiers |= GOEvent.MODIFIER_SHIFT; + } + } + @Override public void keyTyped(KeyEvent e) { + // ignored } @Override public void mouseWheelMoved(MouseWheelEvent e) { + updateModifiers(e); float factor = (float) Math.exp(-e.getUnitsToScroll() / 20.0); startZoom(); endZoomEvent(factor, convertToLocal(e)); @@ -277,6 +295,7 @@ public void mouseWheelMoved(MouseWheelEvent e) { @Override public void componentResized(ComponentEvent e) { + // ignored } @Override @@ -291,6 +310,7 @@ public void componentShown(ComponentEvent componentEvent) { @Override public void componentHidden(ComponentEvent e) { + // ignored } @Override @@ -310,4 +330,9 @@ void privateRegisterComponentListenerToParentWindowOf(Component component, Compo privateRegisterComponentListenerToParentWindowOf(component.getParent(), childComponent); } } + + @Override + protected int getCurrentModifiers() { + return modifiers; + } } diff --git a/go.graphics/src/main/java/go/graphics/area/Area.java b/go.graphics/src/main/java/go/graphics/area/Area.java index dd4464d598..cc250d99c7 100644 --- a/go.graphics/src/main/java/go/graphics/area/Area.java +++ b/go.graphics/src/main/java/go/graphics/area/Area.java @@ -321,6 +321,10 @@ private void changePoint(UIPoint point) { private class SimpleHoverEvent extends AbstractMouseEvent implements GOHoverEvent { + private SimpleHoverEvent() { + super(0); + } + public void finish() { this.setPhase(PHASE_FINISHED); } diff --git a/go.graphics/src/main/java/go/graphics/event/GOEvent.java b/go.graphics/src/main/java/go/graphics/event/GOEvent.java index fd20090af8..49adad0998 100644 --- a/go.graphics/src/main/java/go/graphics/event/GOEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/GOEvent.java @@ -32,6 +32,10 @@ * @author michael */ public interface GOEvent { + int MODIFIER_SHIFT = 1; + int MODIFIER_CTRL = 2; + int MODIFIER_ALT = 4; + /** * Indicates that the event is in the initialization phase. In this pahse, the event handler is searched. */ @@ -75,4 +79,10 @@ public interface GOEvent { * @return The phase the event is in. */ int getPhase(); + + /** + * Gets the modifiers for the event + * @return The modifiers as bit set + */ + int getModifiers(); } diff --git a/go.graphics/src/main/java/go/graphics/event/GOKeyEvent.java b/go.graphics/src/main/java/go/graphics/event/GOKeyEvent.java index 357e229e38..f8f5e3e4a4 100644 --- a/go.graphics/src/main/java/go/graphics/event/GOKeyEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/GOKeyEvent.java @@ -32,6 +32,19 @@ public class GOKeyEvent extends SingleHandlerGoEvent { public GOKeyEvent(String keyCode) { this.keyCode = keyCode; } + + /** + * Creates a new key event for a given key code. + * + * @param keyCode + * The key code. + * @param modifiers + * The modifiers. + */ + public GOKeyEvent(String keyCode, int modifiers) { + super(modifiers); + this.keyCode = keyCode; + } /** * Gets the key code the event has. diff --git a/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoEvent.java b/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoEvent.java index fa10310422..5447bef5ee 100644 --- a/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoEvent.java @@ -24,6 +24,16 @@ public class SingleHandlerGoEvent implements GOEvent { private int phase = PHASE_INITIALIZING; + private final int modifiers; + + public SingleHandlerGoEvent() { + this(0); + } + + public SingleHandlerGoEvent(int modifiers) { + this.modifiers = modifiers; + } + @Override public void setHandler(GOEventHandler handler) { if (getPhase() != PHASE_INITIALIZING) { @@ -67,4 +77,9 @@ protected void setPhase(int phase) { public int getPhase() { return phase; } + + @Override + public int getModifiers() { + return modifiers; + } } diff --git a/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoModalEvent.java b/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoModalEvent.java index 3f463fc2f2..027feb2a62 100644 --- a/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoModalEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/SingleHandlerGoModalEvent.java @@ -22,6 +22,13 @@ * @author michael */ public class SingleHandlerGoModalEvent extends SingleHandlerGoEvent { + public SingleHandlerGoModalEvent() { + } + + public SingleHandlerGoModalEvent(int modifiers) { + super(modifiers); + } + /** * This method notifies the handler, if it supports the {@link GOModalEventHandler}, that the event data has changed. */ diff --git a/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractEventConverter.java b/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractEventConverter.java index 6a13f22dc1..91dba8939b 100644 --- a/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractEventConverter.java +++ b/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractEventConverter.java @@ -64,7 +64,7 @@ protected void tryCancelCurrentEvent() { */ protected void startDraw(UIPoint start) { if (ongoingDrawEvent == null) { - ongoingDrawEvent = new ConvertedDrawEvent(start); + ongoingDrawEvent = new ConvertedDrawEvent(start, getCurrentModifiers()); handleEvent(ongoingDrawEvent); @@ -83,7 +83,8 @@ protected void endDraw(UIPoint position) { if (ongoingDrawEvent != null) { if (tryReplaceEvent(position, ReplacableEvent.DRAW, ongoingDrawEvent.getTime(), - ongoingDrawEvent.getMouseMoved())) { + ongoingDrawEvent.getMouseMoved(), + ongoingDrawEvent.getModifiers())) { abortDraw(); } else { ongoingDrawEvent.released(); @@ -101,7 +102,7 @@ protected void abortDraw() { protected void startPan(UIPoint start) { if (ongoingPanEvent == null) { - ongoingPanEvent = new ConvertedPanEvent(start); + ongoingPanEvent = new ConvertedPanEvent(start, getCurrentModifiers()); handleEvent(ongoingPanEvent); ongoingPanEvent.initialized(); } @@ -116,7 +117,9 @@ protected void updatePanPosition(UIPoint current) { protected void endPan(UIPoint position) { if (ongoingPanEvent != null) { if (tryReplaceEvent(position, ReplacableEvent.PAN, - ongoingPanEvent.getTime(), ongoingPanEvent.getMouseMoved())) { + ongoingPanEvent.getTime(), + ongoingPanEvent.getMouseMoved(), + ongoingPanEvent.getModifiers())) { abortPan(); } else { ongoingPanEvent.released(); @@ -127,7 +130,7 @@ protected void endPan(UIPoint position) { protected void startZoom() { if (ongoingZoomEvent == null) { - ongoingZoomEvent = new ConvertedZoomEvent(); + ongoingZoomEvent = new ConvertedZoomEvent(getCurrentModifiers()); handleEvent(ongoingZoomEvent); ongoingZoomEvent.initialized(); } @@ -156,7 +159,7 @@ protected void abortPan() { protected void startHover(UIPoint start) { if (ongoingHoverEvent == null) { - ongoingHoverEvent = new ConvertedHoverEvent(start); + ongoingHoverEvent = new ConvertedHoverEvent(start, getCurrentModifiers()); handleEvent(ongoingHoverEvent); ongoingHoverEvent.initialized(); } @@ -172,7 +175,8 @@ protected void endHover(UIPoint position) { if (ongoingHoverEvent != null) { if (tryReplaceEvent(position, ReplacableEvent.HOVER, ongoingHoverEvent.getTime(), - ongoingHoverEvent.getMouseMoved())) { + ongoingHoverEvent.getMouseMoved(), + ongoingHoverEvent.getModifiers())) { abortHover(); } else { ongoingHoverEvent.released(); @@ -188,8 +192,8 @@ protected void abortHover() { } } - protected boolean fireCommandEvent(UIPoint point, boolean isSelect) { - ConvertedCommandEvent commandEvent = new ConvertedCommandEvent(point, isSelect); + protected boolean fireCommandEvent(UIPoint point, boolean isSelect, int modifiers) { + ConvertedCommandEvent commandEvent = new ConvertedCommandEvent(point, isSelect, modifiers); handleEvent(commandEvent); @@ -200,7 +204,7 @@ protected boolean fireCommandEvent(UIPoint point, boolean isSelect) { protected synchronized void startKeyEvent(String string) { if (ongoingKeyEvent == null) { - ongoingKeyEvent = new GOKeyEvent(string); + ongoingKeyEvent = new GOKeyEvent(string, getCurrentModifiers()); replaceKeyEvent(ongoingKeyEvent); handleEvent(ongoingKeyEvent); ongoingKeyEvent.started(); @@ -251,7 +255,8 @@ private class ConvertedCommandEvent extends SingleHandlerGoEvent implements private final UIPoint position; private final boolean selecting; - public ConvertedCommandEvent(UIPoint position, boolean selecting) { + public ConvertedCommandEvent(UIPoint position, boolean selecting, int modifiers) { + super(modifiers); this.position = position; this.selecting = selecting; } @@ -279,11 +284,11 @@ protected void addReplaceRule(EventReplacementRule r) { } private boolean tryReplaceEvent(UIPoint p, ReplacableEvent e, double time, - double distance) { + double distance, int modifiers) { for (EventReplacementRule r : replace) { if (r.matches(e, time, distance)) { boolean success = fireCommandEvent(p, - r.replaced == Replacement.COMMAND_SELECT); + r.replaced == Replacement.COMMAND_SELECT, modifiers); if (success) { return true; } @@ -300,6 +305,10 @@ protected boolean panStarted() { return ongoingPanEvent != null; } + protected int getCurrentModifiers() { + return 0; + } + /** * a rule on when to replace short draw, hover or pan events with other stuff. * diff --git a/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractMouseEvent.java b/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractMouseEvent.java index 1c6c31251c..7e11761bde 100644 --- a/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractMouseEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/interpreter/AbstractMouseEvent.java @@ -23,8 +23,8 @@ public class AbstractMouseEvent extends SingleHandlerGoModalEvent { private int mouseMoved = 0; private long startTime = 0; - public AbstractMouseEvent() { - super(); + public AbstractMouseEvent(int modifiers) { + super(modifiers); startTime = System.currentTimeMillis(); } diff --git a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedDrawEvent.java b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedDrawEvent.java index 0cc8f1a710..e2d42cefd2 100644 --- a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedDrawEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedDrawEvent.java @@ -29,8 +29,10 @@ public class ConvertedDrawEvent extends AbstractMouseEvent implements * * @param point * The point where it starts. + * @param modifiers The modifiers */ - public ConvertedDrawEvent(final UIPoint point) { + public ConvertedDrawEvent(final UIPoint point, int modifiers) { + super(modifiers); this.position = point; } diff --git a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedHoverEvent.java b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedHoverEvent.java index ad651d2bc7..c5961d6d42 100644 --- a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedHoverEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedHoverEvent.java @@ -25,7 +25,8 @@ public class ConvertedHoverEvent extends AbstractMouseEvent implements GOHoverEvent { - public ConvertedHoverEvent(UIPoint start) { + public ConvertedHoverEvent(UIPoint start, int modifiers) { + super(modifiers); position = start; } diff --git a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedPanEvent.java b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedPanEvent.java index 88cd688929..e0ee15215a 100644 --- a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedPanEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedPanEvent.java @@ -31,8 +31,10 @@ class ConvertedPanEvent extends AbstractMouseEvent implements GOPanEvent { * * @param point * THe point the user first put his mouse to. + * @param modifiers The modifiers */ - protected ConvertedPanEvent(UIPoint point) { + protected ConvertedPanEvent(UIPoint point, int modifiers) { + super(modifiers); this.position = point; this.original = point; } diff --git a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedZoomEvent.java b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedZoomEvent.java index dcf6ebf590..51c14f3e26 100644 --- a/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedZoomEvent.java +++ b/go.graphics/src/main/java/go/graphics/event/interpreter/ConvertedZoomEvent.java @@ -33,7 +33,8 @@ public class ConvertedZoomEvent extends AbstractMouseEvent implements GOZoomEven /** * Constructor */ - public ConvertedZoomEvent() { + public ConvertedZoomEvent(int modifiers) { + super(modifiers); } @Override diff --git a/go.graphics/src/main/java/go/graphics/event/mouse/GOEventProxy.java b/go.graphics/src/main/java/go/graphics/event/mouse/GOEventProxy.java index 29ebcbd4a4..ca6d07e1cb 100644 --- a/go.graphics/src/main/java/go/graphics/event/mouse/GOEventProxy.java +++ b/go.graphics/src/main/java/go/graphics/event/mouse/GOEventProxy.java @@ -45,4 +45,9 @@ public void setHandler(GOEventHandler handler) { this.baseEvent.setHandler(new EventHandlerProxy(this, handler)); } + @Override + public int getModifiers() { + return this.baseEvent.getModifiers(); + } + } \ No newline at end of file diff --git a/jsettlers.common/src/main/java/jsettlers/common/menu/action/EMoveToMode.java b/jsettlers.common/src/main/java/jsettlers/common/menu/action/EMoveToMode.java new file mode 100644 index 0000000000..9db3e0dc0b --- /dev/null +++ b/jsettlers.common/src/main/java/jsettlers/common/menu/action/EMoveToMode.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2017 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *******************************************************************************/ +package jsettlers.common.menu.action; + +/** + * The mode movables should use for move_to + * @author Michael Zangl + */ +public enum EMoveToMode { + /** + * Normal move + */ + NORMAL(false, false), + /** + * Forced move + */ + FORCED(true, false), + /** + * Work at destination. + * For geologists, thieves and pioneers, this implies that they shoud start their work when they reach the destination + * For soldiers, they should start to patrol between the start and end point + */ + WORK(true, true), + /** + * Add a waypoint to the route the movable should take on the next move action of any other type + */ + ADD_WAYPOINT(false, false); + + private final boolean force; + private final boolean workAtDestination; + + EMoveToMode(boolean doForce, boolean doWorkAtDestination) { + this.force = doForce; + this.workAtDestination = doWorkAtDestination; + } + + public boolean isForced() { + return force; + } + + public boolean doWorkAtDestination() { + return workAtDestination; + } +} diff --git a/jsettlers.graphics/src/main/java/jsettlers/graphics/action/MoveToAction.java b/jsettlers.graphics/src/main/java/jsettlers/graphics/action/MoveToAction.java new file mode 100644 index 0000000000..3d18952647 --- /dev/null +++ b/jsettlers.graphics/src/main/java/jsettlers/graphics/action/MoveToAction.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2017 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *******************************************************************************/ +package jsettlers.graphics.action; + +import go.graphics.event.GOEvent; +import jsettlers.common.menu.action.EActionType; +import jsettlers.common.menu.action.EMoveToMode; +import jsettlers.common.position.ShortPoint2D; + +public class MoveToAction extends PointAction { + + private final EMoveToMode mode; + + public MoveToAction(ShortPoint2D position, EMoveToMode mode) { + super(EActionType.MOVE_TO, position); + this.mode = mode; + } + + public EMoveToMode getMode() { + return mode; + } + + @Override + public String toString() { + return "MoveToAction [mode=" + mode + ", getPosition()=" + getPosition() + "]"; + } + + public static EMoveToMode modeForModifiers(int modifiers) { + if ((modifiers & GOEvent.MODIFIER_ALT) != 0) { + return EMoveToMode.WORK; + } + if ((modifiers & GOEvent.MODIFIER_CTRL) != 0) { + return EMoveToMode.FORCED; + } + if ((modifiers & GOEvent.MODIFIER_SHIFT) != 0) { + return EMoveToMode.ADD_WAYPOINT; + } + return EMoveToMode.NORMAL; + } +} diff --git a/jsettlers.graphics/src/main/java/jsettlers/graphics/map/MapContent.java b/jsettlers.graphics/src/main/java/jsettlers/graphics/map/MapContent.java index 7194f20d8b..8e76237286 100644 --- a/jsettlers.graphics/src/main/java/jsettlers/graphics/map/MapContent.java +++ b/jsettlers.graphics/src/main/java/jsettlers/graphics/map/MapContent.java @@ -60,6 +60,7 @@ import jsettlers.graphics.action.ActionFireable; import jsettlers.graphics.action.ActionHandler; import jsettlers.graphics.action.ActionThreadBlockingListener; +import jsettlers.graphics.action.MoveToAction; import jsettlers.graphics.action.PointAction; import jsettlers.graphics.action.ScreenChangeAction; import jsettlers.graphics.action.SelectAreaAction; @@ -743,7 +744,7 @@ private void changeMousePosition(UIPoint position) { private Action getActionForCommand(GOCommandEvent commandEvent) { UIPoint position = commandEvent.getCommandPosition(); if (controls.containsPoint(position)) { - return controls.getActionFor(position, commandEvent.isSelecting()); + return controls.getActionFor(position, commandEvent); } else { // handle map click return handleCommandOnMap(commandEvent, position); @@ -781,7 +782,6 @@ public void eventDataChanged(GOEvent event) { }; private Action handleCommandOnMap(GOCommandEvent commandEvent, UIPoint position) { - float x = (float) position.getX(); float y = (float) position.getY(); ShortPoint2D onMap = this.context.getPositionOnScreen(x, y); @@ -790,7 +790,7 @@ private Action handleCommandOnMap(GOCommandEvent commandEvent, UIPoint position) if (commandEvent.isSelecting()) { action = handleSelectCommand(onMap); } else { - action = new PointAction(EActionType.MOVE_TO, onMap); + action = new MoveToAction(onMap, MoveToAction.modeForModifiers(commandEvent.getModifiers())); } return action; } @@ -894,7 +894,7 @@ public void action(IAction action) { } break; case MOVE_TO: - moveToMarker = ((PointAction) action).getPosition(); + moveToMarker = ((MoveToAction) action).getPosition(); moveToMarkerTime = System.currentTimeMillis(); break; case SHOW_MESSAGE: diff --git a/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/IControls.java b/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/IControls.java index a6085da724..358ff870e5 100644 --- a/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/IControls.java +++ b/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/IControls.java @@ -16,6 +16,7 @@ import go.graphics.GLDrawContext; import go.graphics.UIPoint; +import go.graphics.event.command.GOCommandEvent; import go.graphics.event.mouse.GODrawEvent; import jsettlers.common.map.shapes.MapRectangle; import jsettlers.common.menu.IMapInterfaceListener; @@ -82,11 +83,11 @@ public interface IControls extends IMapInterfaceListener { * * @param position * The positon. - * @param selecting - * If the event is a select event. + * @param event + * The event * @return The action for the position. */ - Action getActionFor(UIPoint position, boolean selecting); + Action getActionFor(UIPoint position, GOCommandEvent event); /** * Handles a draw event. The event may be fired even if it is outside the interface. diff --git a/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/original/OriginalControls.java b/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/original/OriginalControls.java index 2fbd00fa51..58a0e9aa28 100644 --- a/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/original/OriginalControls.java +++ b/jsettlers.graphics/src/main/java/jsettlers/graphics/map/controls/original/OriginalControls.java @@ -18,9 +18,11 @@ import go.graphics.UIPoint; import go.graphics.event.GOEvent; import go.graphics.event.GOModalEventHandler; +import go.graphics.event.command.GOCommandEvent; import go.graphics.event.mouse.GODrawEvent; import jsettlers.common.map.shapes.MapRectangle; import jsettlers.common.menu.action.EActionType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.menu.action.IAction; import jsettlers.common.player.IInGamePlayer; import jsettlers.common.position.FloatRectangle; @@ -30,6 +32,7 @@ import jsettlers.graphics.action.ActionFireable; import jsettlers.graphics.action.ChangePanelAction; import jsettlers.graphics.action.ExecutableAction; +import jsettlers.graphics.action.MoveToAction; import jsettlers.graphics.action.PointAction; import jsettlers.graphics.map.MapDrawContext; import jsettlers.graphics.map.controls.IControls; @@ -198,12 +201,12 @@ private double getMinimapOffset(double y) { } @Override - public Action getActionFor(UIPoint position, boolean selecting) { + public Action getActionFor(UIPoint position, GOCommandEvent event) { float relativex = (float) position.getX() / this.uiBase.getPosition().getWidth(); float relativey = (float) position.getY() / this.uiBase.getPosition().getHeight(); Action action; if (minimap != null && relativey > layoutProperties.MAIN_PANEL_TOP && getMinimapOffset(position.getY()) < position.getX()) { - action = getForMinimap(relativex, relativey, selecting); + action = getForMinimap(relativex, relativey, event.isSelecting(), MoveToAction.modeForModifiers(event.getModifiers())); startMapPosition = null; // to prevent it from jumping back. } else { action = uiBase.getAction(relativex, relativey); @@ -226,10 +229,11 @@ public Action getActionFor(UIPoint position, boolean selecting) { * The position on the minimap. * @param selecting * true if it was a selection click and the view should move there. + * @param moveToMode The mode to use for move tos * @return the action for that point or null for no action. */ private Action getForMinimap(float relativex, float relativey, - boolean selecting) { + boolean selecting, EMoveToMode moveToMode) { float minimapx = (relativex - layoutProperties.miniMap.MAP_LEFT) / layoutProperties.miniMap.MAP_WIDTH; float minimapy = ((relativey - layoutProperties.MAIN_PANEL_TOP) @@ -240,7 +244,7 @@ private Action getForMinimap(float relativex, float relativey, if (selecting) { return new PointAction(EActionType.PAN_TO, clickPosition); } else { - return new PointAction(EActionType.MOVE_TO, clickPosition); + return new MoveToAction(clickPosition, moveToMode); } } else { return null; @@ -296,7 +300,7 @@ private Action getActionForDraw(GODrawEvent event) { float height = this.uiBase.getPosition().getHeight(); float relativey = (float) position.getY() / height; - return getForMinimap(relativex, relativey, true); + return getForMinimap(relativex, relativey, true, MoveToAction.modeForModifiers(event.getModifiers())); } /** diff --git a/jsettlers.logic/src/main/java/jsettlers/ai/army/ConfigurableGeneral.java b/jsettlers.logic/src/main/java/jsettlers/ai/army/ConfigurableGeneral.java index 689af985c9..adb042fd36 100644 --- a/jsettlers.logic/src/main/java/jsettlers/ai/army/ConfigurableGeneral.java +++ b/jsettlers.logic/src/main/java/jsettlers/ai/army/ConfigurableGeneral.java @@ -22,6 +22,7 @@ import jsettlers.ai.highlevel.AiStatistics; import jsettlers.common.buildings.EBuildingType; import jsettlers.common.material.EMaterialType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EMovableType; import jsettlers.common.movable.ESoldierType; import jsettlers.common.player.IPlayer; @@ -214,7 +215,7 @@ private void sendTroopsTo(List attackerPositions, ShortPoint2D tar } } - taskScheduler.scheduleTask(new MoveToGuiTask(player.playerId, target, attackerIds)); + taskScheduler.scheduleTask(new MoveToGuiTask(player.playerId, target, attackerIds, EMoveToMode.NORMAL)); } private ShortPoint2D getTargetEnemyDoorToAttack(IPlayer enemyToAttack) { diff --git a/jsettlers.logic/src/main/java/jsettlers/ai/highlevel/WhatToDoAi.java b/jsettlers.logic/src/main/java/jsettlers/ai/highlevel/WhatToDoAi.java index 89fe5972b2..ff06a2768f 100644 --- a/jsettlers.logic/src/main/java/jsettlers/ai/highlevel/WhatToDoAi.java +++ b/jsettlers.logic/src/main/java/jsettlers/ai/highlevel/WhatToDoAi.java @@ -73,6 +73,7 @@ import jsettlers.common.buildings.EBuildingType; import jsettlers.common.landscape.EResourceType; import jsettlers.common.material.EMaterialType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EMovableType; import jsettlers.common.movable.IMovable; import jsettlers.common.position.ShortPoint2D; @@ -233,7 +234,7 @@ private Set occupyMilitaryBuildings() { private void sendMovableTo(IMovable movable, ShortPoint2D target) { if (movable != null) { - taskScheduler.scheduleTask(new MoveToGuiTask(playerId, target, Collections.singletonList(movable.getID()))); + taskScheduler.scheduleTask(new MoveToGuiTask(playerId, target, Collections.singletonList(movable.getID()), EMoveToMode.FORCED)); } } @@ -442,7 +443,7 @@ private void releaseAllPioneers() { List pioneerIds = stream(pioneers).map(pioneerPosition -> mainGrid.getMovableGrid().getMovableAt(pioneerPosition.x, pioneerPosition.y).getID()).collect(Collectors.toList()); taskScheduler.scheduleTask(new ConvertGuiTask(playerId, pioneerIds, EMovableType.BEARER)); // pioneers which can not be converted shall walk into player's land to be converted the next tic - taskScheduler.scheduleTask(new MoveToGuiTask(playerId, aiStatistics.getPositionOfPartition(playerId), pioneerIds)); + taskScheduler.scheduleTask(new MoveToGuiTask(playerId, aiStatistics.getPositionOfPartition(playerId), pioneerIds, EMoveToMode.FORCED)); } } @@ -464,7 +465,7 @@ private void setNewTargetForBroadenerPioneers() { PioneerGroup pioneersWithNoAction = broadenerPioneers.getPioneersWithNoAction(); ShortPoint2D broadenTarget = pioneerAi.findBroadenTarget(); if (broadenTarget != null) { - taskScheduler.scheduleTask(new MoveToGuiTask(playerId, broadenTarget, pioneersWithNoAction.getPioneerIds())); + taskScheduler.scheduleTask(new MoveToGuiTask(playerId, broadenTarget, pioneersWithNoAction.getPioneerIds(), EMoveToMode.WORK)); } } } @@ -473,7 +474,7 @@ private void setNewTargetForResourcePioneers() { if (resourcePioneers.isNotEmpty()) { ShortPoint2D resourceTarget = pioneerAi.findResourceTarget(); if (resourceTarget != null) { - taskScheduler.scheduleTask(new MoveToGuiTask(playerId, resourceTarget, resourcePioneers.getPioneerIds())); + taskScheduler.scheduleTask(new MoveToGuiTask(playerId, resourceTarget, resourcePioneers.getPioneerIds(), EMoveToMode.WORK)); } } } diff --git a/jsettlers.logic/src/main/java/jsettlers/input/GuiInterface.java b/jsettlers.logic/src/main/java/jsettlers/input/GuiInterface.java index 8e0b8a74a1..df20287e79 100644 --- a/jsettlers.logic/src/main/java/jsettlers/input/GuiInterface.java +++ b/jsettlers.logic/src/main/java/jsettlers/input/GuiInterface.java @@ -30,6 +30,7 @@ import jsettlers.common.menu.IMapInterfaceListener; import jsettlers.common.menu.UIState; import jsettlers.common.menu.action.EActionType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.menu.action.IAction; import jsettlers.common.movable.EMovableType; import jsettlers.common.movable.ESoldierType; @@ -42,6 +43,7 @@ import jsettlers.graphics.action.BuildAction; import jsettlers.graphics.action.ChangeTradingRequestAction; import jsettlers.graphics.action.ConvertAction; +import jsettlers.graphics.action.MoveToAction; import jsettlers.graphics.action.PointAction; import jsettlers.graphics.action.ScreenChangeAction; import jsettlers.graphics.action.SelectAreaAction; @@ -217,13 +219,13 @@ public void action(IAction action) { break; case MOVE_TO: { - final PointAction moveToAction = (PointAction) action; + final MoveToAction moveToAction = (MoveToAction) action; if (currentSelection.getSelectionType() == ESelectionType.BUILDING && currentSelection.getSize() == 1) { setBuildingWorkArea(moveToAction.getPosition()); } else { - moveTo(moveToAction.getPosition()); + moveTo(moveToAction.getPosition(), moveToAction.getMode()); } break; } @@ -503,9 +505,9 @@ private void stopOrStartWorkingAction(boolean stop) { taskScheduler.scheduleTask(new MovableGuiTask(stop ? EGuiAction.STOP_WORKING : EGuiAction.START_WORKING, playerId, getIDsOfSelected())); } - private void moveTo(ShortPoint2D pos) { + private void moveTo(ShortPoint2D pos, EMoveToMode mode) { final List selectedIds = getIDsOfSelected(); - scheduleTask(new MoveToGuiTask(playerId, pos, selectedIds)); + scheduleTask(new MoveToGuiTask(playerId, pos, selectedIds, mode)); } private List getIDsOfSelected() { diff --git a/jsettlers.logic/src/main/java/jsettlers/input/GuiTaskExecutor.java b/jsettlers.logic/src/main/java/jsettlers/input/GuiTaskExecutor.java index 3bb76ec398..408d255145 100644 --- a/jsettlers.logic/src/main/java/jsettlers/input/GuiTaskExecutor.java +++ b/jsettlers.logic/src/main/java/jsettlers/input/GuiTaskExecutor.java @@ -22,6 +22,7 @@ import jsettlers.common.buildings.IBuilding; import jsettlers.common.map.shapes.HexGridArea; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.position.ShortPoint2D; import jsettlers.common.utils.mutables.MutableInt; import jsettlers.input.tasks.ChangeTowerSoldiersGuiTask; @@ -100,7 +101,7 @@ public void executeTask(TaskPacket iTask) { case MOVE_TO: { MoveToGuiTask task = (MoveToGuiTask) guiTask; - moveSelectedTo(task.getPosition(), task.getSelection()); + moveSelectedTo(task.getPosition(), task.getSelection(), task.getMode()); break; } @@ -293,19 +294,20 @@ private void killSelectedMovables(List selectedMovables) { * position to move to * @param movableIds * A list of the id's of the movables. + * @param mode The move to mode to use */ - private void moveSelectedTo(ShortPoint2D targetPosition, List movableIds) { + private void moveSelectedTo(ShortPoint2D targetPosition, List movableIds, EMoveToMode mode) { if (movableIds.size() == 1) { ILogicMovable currMovable = Movable.getMovableByID(movableIds.get(0)); if (currMovable != null) { - currMovable.moveTo(targetPosition); + currMovable.moveTo(targetPosition, mode); } } else if (!movableIds.isEmpty()) { - sendMovablesNew(targetPosition, movableIds); + sendMovablesNew(targetPosition, movableIds, mode); } } - private void sendMovablesNew(ShortPoint2D targetPosition, List movableIds) { + private void sendMovablesNew(ShortPoint2D targetPosition, List movableIds, EMoveToMode mode) { List movables = stream(movableIds).map(Movable::getMovableByID).filter(Objects::nonNull).collect(Collectors.toList()); if (movables.isEmpty()) { return; @@ -322,7 +324,7 @@ private void sendMovablesNew(ShortPoint2D targetPosition, List movableI Optional movableOptional = removeMovableThatCanMoveTo(movables, x, y); movableOptional.ifPresent(movable -> { - movable.moveTo(new ShortPoint2D(x, y)); + movable.moveTo(new ShortPoint2D(x, y), mode); numberOfSendMovables.value++; }); }); diff --git a/jsettlers.logic/src/main/java/jsettlers/input/tasks/MoveToGuiTask.java b/jsettlers.logic/src/main/java/jsettlers/input/tasks/MoveToGuiTask.java index cadbcc1969..e44d6ea251 100644 --- a/jsettlers.logic/src/main/java/jsettlers/input/tasks/MoveToGuiTask.java +++ b/jsettlers.logic/src/main/java/jsettlers/input/tasks/MoveToGuiTask.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.List; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.position.ShortPoint2D; /** @@ -28,35 +29,44 @@ */ public class MoveToGuiTask extends MovableGuiTask { private ShortPoint2D position; + private EMoveToMode mode; public MoveToGuiTask() { } - public MoveToGuiTask(byte playerId, ShortPoint2D pos, List selection) { + public MoveToGuiTask(byte playerId, ShortPoint2D pos, List selection, EMoveToMode mode) { super(EGuiAction.MOVE_TO, playerId, selection); this.position = pos; + this.mode = mode; } public ShortPoint2D getPosition() { return position; } + + public EMoveToMode getMode() { + return mode; + } @Override protected void serializeTask(DataOutputStream dos) throws IOException { super.serializeTask(dos); SimpleGuiTask.serializePosition(dos, position); + dos.writeByte(mode.ordinal()); } @Override protected void deserializeTask(DataInputStream dis) throws IOException { super.deserializeTask(dis); position = SimpleGuiTask.deserializePosition(dis); + mode = EMoveToMode.values()[dis.readByte()]; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); + result = prime * result + ((mode == null) ? 0 : mode.hashCode()); result = prime * result + ((position == null) ? 0 : position.hashCode()); return result; } @@ -70,6 +80,8 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; MoveToGuiTask other = (MoveToGuiTask) obj; + if (mode != other.mode) + return false; if (position == null) { if (other.position != null) return false; diff --git a/jsettlers.logic/src/main/java/jsettlers/logic/movable/Movable.java b/jsettlers.logic/src/main/java/jsettlers/logic/movable/Movable.java index 450c8cce1e..53d34084c1 100644 --- a/jsettlers.logic/src/main/java/jsettlers/logic/movable/Movable.java +++ b/jsettlers.logic/src/main/java/jsettlers/logic/movable/Movable.java @@ -23,6 +23,7 @@ import jsettlers.common.mapobject.EMapObjectType; import jsettlers.common.material.EMaterialType; import jsettlers.common.material.ESearchType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EDirection; import jsettlers.common.movable.EMovableAction; import jsettlers.common.movable.EMovableType; @@ -72,6 +73,7 @@ public final class Movable implements ILogicMovable { private ShortPoint2D position; private ShortPoint2D requestedTargetPosition = null; + protected EMoveToMode requestedMoveMode; private Path path; private float health; @@ -125,9 +127,12 @@ private final void readObject(ObjectInputStream ois) throws IOException, ClassNo * * @param targetPosition */ - public final void moveTo(ShortPoint2D targetPosition) { + @Override + public final void moveTo(ShortPoint2D targetPosition, EMoveToMode mode) { if (movableType.isPlayerControllable() && strategy.canBeControlledByPlayer() && !alreadyWalkingToPosition(targetPosition)) { this.requestedTargetPosition = targetPosition; + this.requestedMoveMode = mode; + strategy.stopOrStartWorking(!mode.doWorkAtDestination()); } } @@ -135,6 +140,7 @@ private boolean alreadyWalkingToPosition(ShortPoint2D targetPosition) { return this.state == EMovableState.PATHING && this.path.getTargetPos().equals(targetPosition); } + @Override public void leavePosition() { if (state != EMovableState.DOING_NOTHING || !enableNothingToDo) { return; @@ -217,7 +223,7 @@ public int timerEvent() { requestedTargetPosition = null; if (foundPath) { - this.strategy.moveToPathSet(oldPos, oldTargetPos, path.getTargetPos()); + this.strategy.moveToPathSet(oldPos, oldTargetPos, path.getTargetPos(), requestedMoveMode); return animationDuration; // we already follow the path and initiated the walking } else { break; @@ -281,6 +287,7 @@ private void pathingAction() { // if path is finished, or canceled by strategy return from here setState(EMovableState.DOING_NOTHING); movableAction = EMovableAction.NO_ACTION; + strategy.pathDone(path.getTargetPos()); path = null; return; } diff --git a/jsettlers.logic/src/main/java/jsettlers/logic/movable/MovableStrategy.java b/jsettlers.logic/src/main/java/jsettlers/logic/movable/MovableStrategy.java index d1e76f3c34..a8bfe3afe3 100644 --- a/jsettlers.logic/src/main/java/jsettlers/logic/movable/MovableStrategy.java +++ b/jsettlers.logic/src/main/java/jsettlers/logic/movable/MovableStrategy.java @@ -17,6 +17,7 @@ import jsettlers.algorithms.path.Path; import jsettlers.common.material.EMaterialType; import jsettlers.common.material.ESearchType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EDirection; import jsettlers.common.movable.EMovableAction; import jsettlers.common.movable.EMovableType; @@ -237,8 +238,9 @@ protected void strategyKilledEvent(ShortPoint2D pathTarget) { // used in overrid * The target position of the old path or null if no old path was set. * @param targetPos * The new target position. + * @param mode The mode for the target */ - protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos) { + protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos, EMoveToMode mode) { } /** @@ -333,6 +335,9 @@ protected void sleep(short sleepTime) { protected void pathAborted(ShortPoint2D pathTarget) { } + protected void pathDone(ShortPoint2D pathTarget) { + } + /** * This method is called before a material is dropped during a {@link EMovableType}.DROP action. * diff --git a/jsettlers.logic/src/main/java/jsettlers/logic/movable/interfaces/ILogicMovable.java b/jsettlers.logic/src/main/java/jsettlers/logic/movable/interfaces/ILogicMovable.java index 42570260ac..2877a3c9dc 100644 --- a/jsettlers.logic/src/main/java/jsettlers/logic/movable/interfaces/ILogicMovable.java +++ b/jsettlers.logic/src/main/java/jsettlers/logic/movable/interfaces/ILogicMovable.java @@ -5,6 +5,7 @@ import jsettlers.algorithms.fogofwar.IViewDistancable; import jsettlers.algorithms.path.IPathCalculatable; import jsettlers.algorithms.path.Path; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EMovableType; import jsettlers.common.position.ShortPoint2D; import jsettlers.input.IGuiMovable; @@ -33,5 +34,5 @@ public interface ILogicMovable extends void convertTo(EMovableType newMovableType); Player getPlayer(); IBuildingOccupyableMovable setOccupyableBuilding(IOccupyableBuilding building); - void moveTo(ShortPoint2D targetPosition); + void moveTo(ShortPoint2D targetPosition, EMoveToMode mode); } diff --git a/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/soldiers/SoldierStrategy.java b/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/soldiers/SoldierStrategy.java index 49a60e7fdf..ea92003656 100644 --- a/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/soldiers/SoldierStrategy.java +++ b/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/soldiers/SoldierStrategy.java @@ -16,6 +16,7 @@ import jsettlers.algorithms.path.Path; import jsettlers.common.buildings.OccupierPlace; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EDirection; import jsettlers.common.movable.EMovableType; import jsettlers.common.movable.ESoldierClass; @@ -38,6 +39,7 @@ public abstract class SoldierStrategy extends MovableStrategy implements IBuildi */ private enum ESoldierState { AGGRESSIVE, + FORCED_MOVE, SEARCH_FOR_ENEMIES, HITTING, @@ -70,6 +72,7 @@ public SoldierStrategy(Movable movable, EMovableType movableType) { protected void action() { switch (state) { case AGGRESSIVE: + case FORCED_MOVE: break; case HITTING: @@ -108,7 +111,7 @@ protected void action() { if (!isInTower) { // we are in danger because an enemy entered our range where we can't attack => run away EDirection escapeDirection = EDirection.getApproxDirection(toCloseEnemy.getPos(), movable.getPos()); super.goInDirection(escapeDirection, EGoInDirectionMode.GO_IF_ALLOWED_AND_FREE); - movable.moveTo(null); // reset moveToRequest, so the soldier doesn't go there after fleeing. + movable.moveTo(null, EMoveToMode.NORMAL); // reset moveToRequest, so the soldier doesn't go there after fleeing. } // else { // we are in the tower, so wait and check again next time. @@ -312,12 +315,12 @@ protected boolean checkPathStepPreconditions(ShortPoint2D pathTarget, int step) } @Override - protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos) { + protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos, EMoveToMode mode) { if (targetPos != null && this.oldPathTarget != null) { oldPathTarget = null; // reset the path target to be able to get the new one when we hijack the path inSaveGotoMode = false; } - changeStateTo(ESoldierState.SEARCH_FOR_ENEMIES); + changeStateTo(mode.isForced() ? ESoldierState.FORCED_MOVE : ESoldierState.SEARCH_FOR_ENEMIES); } @Override @@ -388,6 +391,9 @@ protected void strategyKilledEvent(ShortPoint2D pathTarget) { @Override protected void pathAborted(ShortPoint2D pathTarget) { switch (state) { + case FORCED_MOVE: + changeStateTo(ESoldierState.AGGRESSIVE); + break; case INIT_GOTO_TOWER: case GOING_TO_TOWER: notifyTowerThatRequestFailed(); @@ -397,6 +403,15 @@ protected void pathAborted(ShortPoint2D pathTarget) { break; } } + + @Override + protected void pathDone(ShortPoint2D pathTarget) { + switch (state) { + case FORCED_MOVE: + changeStateTo(ESoldierState.AGGRESSIVE); + break; + } + } protected float getCombatStrength() { return movable.getPlayer().getCombatStrengthInformation().getCombatStrength(isOnOwnGround()); diff --git a/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/GeologistStrategy.java b/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/GeologistStrategy.java index 0a31281bb8..f09086e2ae 100644 --- a/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/GeologistStrategy.java +++ b/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/GeologistStrategy.java @@ -16,6 +16,7 @@ import jsettlers.common.map.shapes.HexGridArea; import jsettlers.common.material.ESearchType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EMovableAction; import jsettlers.common.position.MutablePoint2D; import jsettlers.common.position.ShortPoint2D; @@ -36,6 +37,7 @@ public final class GeologistStrategy extends MovableStrategy { private EGeologistState state = EGeologistState.JOBLESS; private ShortPoint2D centerPos; + private boolean working; public GeologistStrategy(Movable movable) { super(movable); @@ -45,7 +47,7 @@ public GeologistStrategy(Movable movable) { protected void action() { switch (state) { case JOBLESS: - return; + break; case GOING_TO_POS: { ShortPoint2D pos = movable.getPos(); @@ -53,6 +55,10 @@ protected void action() { if (centerPos == null) { this.centerPos = pos; } + + if (!working) { + break; + } super.getGrid().setMarked(pos, false); // unmark the pos for the following check if (canWorkOnPos(pos)) { @@ -84,6 +90,11 @@ protected void action() { } private void findWorkablePosition() { + if (!working) { + this.state = EGeologistState.JOBLESS; + centerPos = null; + return; + } ShortPoint2D closeWorkablePos = getCloseWorkablePos(); if (closeWorkablePos != null && super.goToPos(closeWorkablePos)) { @@ -141,7 +152,7 @@ protected boolean canBeControlledByPlayer() { } @Override - protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos) { + protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos, EMoveToMode mode) { this.state = EGeologistState.GOING_TO_POS; centerPos = null; @@ -154,6 +165,7 @@ protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos @Override protected void stopOrStartWorking(boolean stop) { + working = !stop; if (stop) { state = EGeologistState.JOBLESS; } else { diff --git a/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/PioneerStrategy.java b/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/PioneerStrategy.java index 9ba48724f7..2305f8b45e 100644 --- a/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/PioneerStrategy.java +++ b/jsettlers.logic/src/main/java/jsettlers/logic/movable/strategies/specialists/PioneerStrategy.java @@ -16,6 +16,7 @@ import jsettlers.common.map.shapes.HexGridArea; import jsettlers.common.material.ESearchType; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EDirection; import jsettlers.common.movable.EMovableAction; import jsettlers.common.position.ShortPoint2D; @@ -117,7 +118,7 @@ private boolean canWorkOnPos(ShortPoint2D pos) { } @Override - protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos) { + protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos, EMoveToMode mode) { this.state = EPioneerState.GOING_TO_POS; centerPos = null; } diff --git a/jsettlers.mapcreator/src/main/java/jsettlers/mapcreator/main/map/MapEditorControls.java b/jsettlers.mapcreator/src/main/java/jsettlers/mapcreator/main/map/MapEditorControls.java index a39da6f7b9..65f40505f0 100644 --- a/jsettlers.mapcreator/src/main/java/jsettlers/mapcreator/main/map/MapEditorControls.java +++ b/jsettlers.mapcreator/src/main/java/jsettlers/mapcreator/main/map/MapEditorControls.java @@ -18,6 +18,7 @@ import go.graphics.UIPoint; import go.graphics.event.GOEvent; import go.graphics.event.GOModalEventHandler; +import go.graphics.event.command.GOCommandEvent; import go.graphics.event.mouse.GODrawEvent; import jsettlers.common.map.shapes.MapRectangle; import jsettlers.common.menu.action.IAction; @@ -103,10 +104,11 @@ public String getDescriptionFor(UIPoint position) { @Override public void setMapViewport(MapRectangle screenArea) { + //ignored } @Override - public Action getActionFor(UIPoint position, boolean select) { + public Action getActionFor(UIPoint position, GOCommandEvent event) { return null; } diff --git a/jsettlers.tools/src/main/java/jsettlers/logic/movable/MovableTestWindow.java b/jsettlers.tools/src/main/java/jsettlers/logic/movable/MovableTestWindow.java index ad94babdb5..1aa3519e34 100644 --- a/jsettlers.tools/src/main/java/jsettlers/logic/movable/MovableTestWindow.java +++ b/jsettlers.tools/src/main/java/jsettlers/logic/movable/MovableTestWindow.java @@ -20,6 +20,7 @@ import jsettlers.common.ai.EPlayerType; import jsettlers.common.material.EMaterialType; import jsettlers.common.menu.IMapInterfaceConnector; +import jsettlers.common.menu.action.EMoveToMode; import jsettlers.common.movable.EMovableType; import jsettlers.common.player.ECivilisation; import jsettlers.common.position.ShortPoint2D; @@ -57,7 +58,7 @@ private MovableTestWindow() throws InterruptedException, JSettlersLookAndFeelExe connector.addListener(action -> { switch (action.getActionType()) { case MOVE_TO: - movable.moveTo(((PointAction) action).getPosition()); + movable.moveTo(((PointAction) action).getPosition(), EMoveToMode.NORMAL); break; case SPEED_FASTER: MatchConstants.clock().multiplyGameSpeed(1.2f); @@ -98,9 +99,9 @@ private MovableTestWindow() throws InterruptedException, JSettlersLookAndFeelExe ILogicMovable m2 = new Movable(grid.getMovableGrid(), EMovableType.PIONEER, new ShortPoint2D(51, 65), PLAYER_0); ILogicMovable m3 = new Movable(grid.getMovableGrid(), EMovableType.PIONEER, new ShortPoint2D(50, 64), PLAYER_0); - m1.moveTo(new ShortPoint2D(52, 65)); - m2.moveTo(new ShortPoint2D(49, 63)); - m3.moveTo(new ShortPoint2D(50, 66)); + m1.moveTo(new ShortPoint2D(52, 65), EMoveToMode.NORMAL); + m2.moveTo(new ShortPoint2D(49, 63), EMoveToMode.NORMAL); + m3.moveTo(new ShortPoint2D(50, 66), EMoveToMode.NORMAL); } } }