Skip to content

Commit

Permalink
feat(actions): Player move action
Browse files Browse the repository at this point in the history
  • Loading branch information
PeyaPeyaPeyang committed Sep 28, 2023
1 parent 982fc10 commit 766b02a
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.kunlab.scenamatica.action.utils.LocationComparator;
import org.kunlab.scenamatica.commons.utils.MapUtils;
import org.kunlab.scenamatica.commons.utils.Utils;
import org.kunlab.scenamatica.enums.ScenarioType;
Expand Down Expand Up @@ -62,22 +63,8 @@ public boolean isFired(@NotNull Argument argument, @NotNull ScenarioEngine engin
assert event instanceof EntityMoveEvent;
EntityMoveEvent e = (EntityMoveEvent) event;

Location fromLoc = argument.getFrom() == null ? null: argument.getFrom().toBlockLocation();
Location toLoc = argument.getTo() == null ? null: argument.getTo().toBlockLocation();

Location eFromLoc = e.getFrom().toBlockLocation();
Location eToLoc = e.getTo().toBlockLocation();

if (!(fromLoc == null || fromLoc.getWorld() == null || !fromLoc.getWorld().getUID().equals(eFromLoc.getWorld().getUID())))
return false;
else if (!(toLoc == null || toLoc.getWorld() == null || !toLoc.getWorld().getUID().equals(eToLoc.getWorld().getUID())))
return false;

eFromLoc.setWorld(null);
eToLoc.setWorld(null);

return (fromLoc == null || fromLoc.equals(eFromLoc))
&& (toLoc == null || toLoc.equals(eToLoc));
return LocationComparator.equals(argument.getFrom(), e.getFrom())
&& LocationComparator.equals(argument.getTo(), e.getTo());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static List<? extends AbstractPlayerAction<?>> getActions()
actions.add(new PlayerJoinAction());
actions.add(new PlayerKickAction());
actions.add(new PlayerLaunchProjectileAction());
actions.add(new PlayerMoveAction());
actions.add(new PlayerQuitAction());
actions.add(new PlayerRespawnAction());
actions.add(new PlayerSneakAction());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package org.kunlab.scenamatica.action.actions.player;

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.kunlab.scenamatica.action.utils.LocationComparator;
import org.kunlab.scenamatica.commons.utils.MapUtils;
import org.kunlab.scenamatica.commons.utils.Utils;
import org.kunlab.scenamatica.enums.ScenarioType;
import org.kunlab.scenamatica.interfaces.action.types.Executable;
import org.kunlab.scenamatica.interfaces.action.types.Watchable;
import org.kunlab.scenamatica.interfaces.scenario.ScenarioEngine;
import org.kunlab.scenamatica.interfaces.scenariofile.BeanSerializer;
import org.kunlab.scenamatica.interfaces.scenariofile.trigger.TriggerArgument;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class PlayerMoveAction extends AbstractPlayerAction<PlayerMoveAction.Argument>
implements Executable<PlayerMoveAction.Argument>, Watchable<PlayerMoveAction.Argument>
{
public static final String KEY_ACTION_NAME = "player_move";

@Override
public String getName()
{
return KEY_ACTION_NAME;
}

@Override
public void execute(@NotNull ScenarioEngine engine, @Nullable Argument argument)
{
argument = this.requireArgsNonNull(argument);

Location toLoc = Utils.assignWorldToLocation(argument.getTo(), engine);
Player target = argument.getTarget();
target.teleport(toLoc);
}

@Override
public boolean isFired(@NotNull Argument argument, @NotNull ScenarioEngine engine, @NotNull Event event)
{
if (!super.checkMatchedPlayerEvent(argument, engine, event))
return false;

assert event instanceof PlayerMoveEvent;
PlayerMoveEvent e = (PlayerMoveEvent) event;

return LocationComparator.equals(argument.getFrom(), e.getFrom())
&& LocationComparator.equals(argument.getTo(), e.getTo());
}

@Override
public List<Class<? extends Event>> getAttachingEvents()
{
return Collections.singletonList(
PlayerMoveEvent.class
);
}

@Override
public Argument deserializeArgument(@NotNull Map<String, Object> map, @NotNull BeanSerializer serializer)
{
return new Argument(
super.deserializeTarget(map),
MapUtils.getAsLocationOrNull(map, Argument.KEY_FROM),
MapUtils.getAsLocationOrNull(map, Argument.KEY_TO)
);
}

@Value
@EqualsAndHashCode(callSuper = true)
public static class Argument extends AbstractPlayerActionArgument
{
public static final String KEY_FROM = "from";
public static final String KEY_TO = "to";

Location from;
Location to;

public Argument(String target, Location from, Location to)
{
super(target);
this.from = from;
this.to = to;
}

@Override
public boolean isSame(TriggerArgument argument)
{
if (!(argument instanceof Argument))
return false;

Argument arg = (Argument) argument;

return super.isSame(arg)
&& Objects.equals(this.from, arg.from)
&& Objects.equals(this.to, arg.to);
}

@Override
public void validate(@NotNull ScenarioEngine engine, @NotNull ScenarioType type)
{
if (type == ScenarioType.ACTION_EXECUTE)
{
throwIfPresent(KEY_FROM, this.from);
throwIfNotPresent(KEY_TO, this.to);
}
}

@Override
public String getArgumentString()
{
return appendArgumentString(
super.getArgumentString(),
KEY_FROM, this.from,
KEY_TO, this.to
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.kunlab.scenamatica.action.utils;

import org.bukkit.Location;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;

public class LocationComparator
{
// 比較時の誤差
public static double EPSILON = 0.01;

/**
* Location を比較する。
* 比較結果は l1 を原点とした3次元座標の距離を返す。
* ワールドが違うなどの要因で比較できない場合は, null を返す。
*
* @param l1 原点となる Location
* @param l2 比較対象となる Location
* @return 比較結果
*/
public static Double compare(@Nullable Location l1, @Nullable Location l2)
{
if (l1 == null || l2 == null)
return null;

Location l1Clone = l1.clone();
Location l2Clone = l2.clone();

if (!Objects.equals(l1.getWorld(), l2.getWorld()))
return null;

double x = l2Clone.getX() - l1Clone.getX();
double y = l2Clone.getY() - l1Clone.getY();
double z = l2Clone.getZ() - l1Clone.getZ();

return Math.sqrt(x * x + y * y + z * z);
}

/**
* Location を比較し、同じ座標かどうかを返す。
*
* @param l1 原点となる Location
* @param l2 比較対象となる Location
* @return 同じ座標かどうか
* @see LocationComparator#compare(Location, Location)
* @see LocationComparator#EPSILON
*/
public static boolean equals(@Nullable Location l1, @Nullable Location l2)
{
Double result = compare(l1, l2);

if (result == null)
return false;

return Math.abs(result) < EPSILON;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# noinspection YAMLSchemaValidation
scenamatica: ${project.version}

name: actions_player_move_2
description: Testing player_move action without target works or not
on:
- type: on_load
- type: manual_dispatch

context:
actors:
- name: Actor001

scenario:
- type: execute
action: player_move
with:
target: Actor001
to:
x: 0
y: 0
z: 0
- type: expect
action: player_move
with:
to:
x: 0
y: 0
z: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# noinspection YAMLSchemaValidation
scenamatica: ${project.version}

name: actions_player_move_3
description: Testing player_move action without to-location works or not
on:
- type: on_load
- type: manual_dispatch

context:
actors:
- name: Actor001

scenario:
- type: execute
action: player_move
with:
target: Actor001
to:
x: 0
y: 0
z: 0
- type: expect
action: player_move
with:
target: Actor001
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# noinspection YAMLSchemaValidation
scenamatica: ${project.version}

name: actions_player_move_4
description: Testing player_move action without argument works or not
on:
- type: on_load
- type: manual_dispatch

context:
actors:
- name: Actor001

scenario:
- type: execute
action: player_move
with:
target: Actor001
to:
x: 0
y: 0
z: 0
- type: expect
action: player_move
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# noinspection YAMLSchemaValidation
scenamatica: ${project.version}

name: actions_player_move
description: Testing player_move action works or not
on:
- type: manual_dispatch

context:
actors:
- name: Actor001

scenario:
- type: execute
action: player_move
with:
target: Actor001
to:
x: 0
y: 0
z: 0
- type: expect
action: player_move
with:
target: Actor001
to:
x: 0
y: 0
z: 0

0 comments on commit 766b02a

Please sign in to comment.