Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -3,6 +3,7 @@
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Player;
import net.minestom.server.tag.Tag;
import net.onelitefeather.cygnus.stamina.SlenderBarHelper;
import org.jetbrains.annotations.Nullable;

Expand All @@ -17,13 +18,25 @@
* <p>
* Without a map or without a slender spawn nothing happens and {@link #perform(Player)} says so.
* </p>
* <p>
* A survivor who was just sent to the spawn is not sent there again for {@link #COOLDOWN_MILLIS}.
* The trickster teleports on every catch, and without the pause the same survivor could land next
* to the slender over and over. During the pause {@link #perform(Player)} refuses, so the creek
* falls back to another trick.
* </p>
*
* @author TheMeinerLP
* @version 1.0.0
* @since 2.21.0
*/
public final class CatchSpawnTeleport implements CatchTrick {

/** How long a survivor is safe from another trip to the slender spawn, in milliseconds. */
static final long COOLDOWN_MILLIS = 60_000L;

/** Until when a survivor is safe from another trip to the slender spawn, in epoch milliseconds. */
static final Tag<Long> COOLDOWN_UNTIL = Tag.Transient("creekSpawnTeleportUntil");

private final Supplier<@Nullable Pos> slenderSpawn;

/**
Expand All @@ -38,13 +51,17 @@ public CatchSpawnTeleport(Supplier<@Nullable Pos> slenderSpawn) {
@Override
public boolean perform(Player caught) {
if (caught.getInstance() == null) return false;
long now = System.currentTimeMillis();
Long cooldown = caught.getTag(COOLDOWN_UNTIL);
if (cooldown != null && now < cooldown) return false;
Pos spawn = this.slenderSpawn.get();
if (spawn == null) return false;

Pos from = caught.getPosition();
caught.teleport(spawn.withView(from.yaw(), from.pitch()));
caught.setVelocity(Vec.ZERO);
caught.playSound(SlenderBarHelper.TELEPORT);
caught.setTag(COOLDOWN_UNTIL, now + COOLDOWN_MILLIS);
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,42 @@ void noSpawn(Env env) {

assertEquals(new Vec(0, 40, 0), caught.getPosition().asVec());
}

@Test
@DisplayName("A survivor who was just sent to the spawn is not sent there again during the cooldown")
void refusesDuringTheCooldown(Env env) {
Instance instance = env.createFlatInstance();
Player caught = env.createConnection().connect(instance, new Pos(0, 40, 0));
CatchSpawnTeleport teleport = new CatchSpawnTeleport(() -> SPAWN);

assertTrue(teleport.perform(caught));

assertFalse(teleport.perform(caught));
}

@Test
@DisplayName("Once the cooldown is over the survivor can be sent to the spawn again")
void teleportsAgainAfterTheCooldown(Env env) {
Instance instance = env.createFlatInstance();
Player caught = env.createConnection().connect(instance, new Pos(0, 40, 0));
CatchSpawnTeleport teleport = new CatchSpawnTeleport(() -> SPAWN);

assertTrue(teleport.perform(caught));
caught.setTag(CatchSpawnTeleport.COOLDOWN_UNTIL, System.currentTimeMillis() - 1);

assertTrue(teleport.perform(caught));
}

@Test
@DisplayName("The cooldown of one survivor does not protect another one")
void cooldownIsPerSurvivor(Env env) {
Instance instance = env.createFlatInstance();
Player first = env.createConnection().connect(instance, new Pos(0, 40, 0));
Player second = env.createConnection().connect(instance, new Pos(5, 40, 0));
CatchSpawnTeleport teleport = new CatchSpawnTeleport(() -> SPAWN);

assertTrue(teleport.perform(first));

assertTrue(teleport.perform(second));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,24 @@ void noPartnerTeleportsToSpawn(Env env) {
assertEquals(SPAWN.asVec(), caught.getPosition().asVec());
}

@Test
@DisplayName("A survivor just sent to the spawn falls back to the next trick on the following catch")
void spawnCooldownFallsBack(Env env) {
Instance instance = env.createFlatInstance();
Player caught = env.createConnection().connect(instance, new Pos(0, 40, 0));
CatchTricks tricks = tricks(_ -> {
}, 1.0D, Set.of(caught), SPAWN, CreekMood.TRICKSTER);

tricks.apply(caught);
env.tick();
assertEquals(SPAWN.asVec(), caught.getPosition().asVec());
caught.setVelocity(Vec.ZERO);

tricks.apply(caught);

assertTrue(caught.getVelocity().y() > 0.0D, "without a partner and on cooldown the survivor is thrown");
}

@Test
@DisplayName("A teleport chooses between the swap and the slender spawn")
void teleportUsesBoth(Env env) {
Expand Down
Loading