Fix player position being wrong inside tests

This commit is contained in:
themode 2022-03-14 19:01:48 +01:00
parent 9215e33e80
commit acee29c20a
10 changed files with 66 additions and 50 deletions

View File

@ -23,5 +23,6 @@ tasks {
useJUnitPlatform()
// Viewable packets make tracking harder. Could be re-enabled later.
jvmArgs("-Dminestom.viewable-packet=false")
jvmArgs("-Dminestom.inside-test=true")
}
}

View File

@ -236,7 +236,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*
* @param spawnInstance the player spawn instance (defined in {@link PlayerLoginEvent})
*/
public void UNSAFE_init(@NotNull Instance spawnInstance) {
public CompletableFuture<Void> UNSAFE_init(@NotNull Instance spawnInstance) {
this.dimensionType = spawnInstance.getDimensionType();
NBTCompound nbt = NBT.Compound(Map.of(
@ -301,7 +301,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
refreshHealth(); // Heal and send health packet
refreshAbilities(); // Send abilities packet
setInstance(spawnInstance);
return setInstance(spawnInstance);
}
/**

View File

@ -15,6 +15,7 @@ import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.network.player.PlayerSocketConnection;
import net.minestom.server.utils.StringUtils;
import net.minestom.server.utils.async.AsyncUtils;
import net.minestom.server.utils.debug.DebugUtils;
import net.minestom.server.utils.validate.Check;
import org.jctools.queues.MessagePassingQueue;
import org.jctools.queues.MpscUnboundedArrayQueue;
@ -22,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Function;
@ -213,8 +215,8 @@ public final class ConnectionManager {
* @param player the player
* @param register true to register the newly created player in {@link ConnectionManager} lists
*/
public void startPlayState(@NotNull Player player, boolean register) {
AsyncUtils.runAsync(() -> {
public CompletableFuture<Void> startPlayState(@NotNull Player player, boolean register) {
return AsyncUtils.runAsync(() -> {
final PlayerConnection playerConnection = player.getPlayerConnection();
// Call pre login event
AsyncPlayerPreLoginEvent asyncPlayerPreLoginEvent = new AsyncPlayerPreLoginEvent(player);
@ -290,7 +292,12 @@ public final class ConnectionManager {
final Instance spawningInstance = loginEvent.getSpawningInstance();
Check.notNull(spawningInstance, "You need to specify a spawning instance in the PlayerLoginEvent");
// Spawn the player at Player#getRespawnPoint
waitingPlayer.UNSAFE_init(spawningInstance);
if (DebugUtils.INSIDE_TEST) {
// Required to get the exact moment the player spawns
waitingPlayer.UNSAFE_init(spawningInstance).join();
} else {
waitingPlayer.UNSAFE_init(spawningInstance);
}
});
}

View File

@ -49,9 +49,9 @@ import java.util.zip.Inflater;
public final class PacketUtils {
private static final LocalCache<Deflater> LOCAL_DEFLATER = LocalCache.of(Deflater::new);
public static final boolean GROUPED_PACKET = getBoolean("minestom.grouped-packet", true);
public static final boolean CACHED_PACKET = getBoolean("minestom.cached-packet", true);
public static final boolean VIEWABLE_PACKET = getBoolean("minestom.viewable-packet", true);
public static final boolean GROUPED_PACKET = PropertyUtils.getBoolean("minestom.grouped-packet", true);
public static final boolean CACHED_PACKET = PropertyUtils.getBoolean("minestom.cached-packet", true);
public static final boolean VIEWABLE_PACKET = PropertyUtils.getBoolean("minestom.viewable-packet", true);
// Viewable packets
private static final Cache<Viewable, ViewableStorage> VIEWABLE_STORAGE_MAP = Caffeine.newBuilder().weakKeys().build();
@ -339,14 +339,4 @@ public final class PacketUtils {
// TODO for non-socket connection
}
}
private static boolean getBoolean(String name, boolean defaultValue) {
boolean result = defaultValue;
try {
final String value = System.getProperty(name);
if (value != null) result = Boolean.parseBoolean(value);
} catch (IllegalArgumentException | NullPointerException ignored) {
}
return result;
}
}

View File

@ -0,0 +1,18 @@
package net.minestom.server.utils;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
public final class PropertyUtils {
private PropertyUtils() {}
public static boolean getBoolean(String name, boolean defaultValue) {
boolean result = defaultValue;
try {
final String value = System.getProperty(name);
if (value != null) result = Boolean.parseBoolean(value);
} catch (IllegalArgumentException | NullPointerException ignored) {
}
return result;
}
}

View File

@ -1,12 +1,16 @@
package net.minestom.server.utils.debug;
import net.minestom.server.utils.PropertyUtils;
import org.jetbrains.annotations.ApiStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utils class useful for debugging purpose.
*/
@ApiStatus.Internal
public final class DebugUtils {
public static boolean INSIDE_TEST = PropertyUtils.getBoolean("minestom.inside-test", false);
public final static Logger LOGGER = LoggerFactory.getLogger(DebugUtils.class);

View File

@ -0,0 +1,13 @@
package net.minestom.server;
import net.minestom.server.utils.debug.DebugUtils;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class InsideTest {
@Test
public void inside() {
assertTrue(DebugUtils.INSIDE_TEST);
}
}

View File

@ -7,15 +7,9 @@ import net.minestom.server.network.packet.server.ServerPacket;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public interface TestConnection {
@NotNull CompletableFuture<@NotNull Player> connect(@NotNull Instance instance, @NotNull Pos pos, @NotNull Consumer<Player> loginCallback);
default @NotNull CompletableFuture<@NotNull Player> connect(@NotNull Instance instance, @NotNull Pos pos) {
return connect(instance, pos, (player) -> {
});
}
@NotNull CompletableFuture<@NotNull Player> connect(@NotNull Instance instance, @NotNull Pos pos);
<T extends ServerPacket> @NotNull Collector<T> trackIncoming(@NotNull Class<T> type);

View File

@ -3,7 +3,6 @@ package net.minestom.server.api;
import net.minestom.server.ServerProcess;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventListener;
import net.minestom.server.event.player.PlayerLoginEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.network.packet.server.SendablePacket;
@ -17,8 +16,6 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
final class TestConnectionImpl implements TestConnection {
private final Env env;
@ -27,32 +24,24 @@ final class TestConnectionImpl implements TestConnection {
private final List<IncomingCollector<ServerPacket>> incomingTrackers = new CopyOnWriteArrayList<>();
public TestConnectionImpl(Env env) {
TestConnectionImpl(Env env) {
this.env = env;
this.process = env.process();
}
@Override
public @NotNull CompletableFuture<Player> connect(@NotNull Instance instance, @NotNull Pos pos, @NotNull Consumer<Player> loginCallback) {
AtomicReference<EventListener<PlayerLoginEvent>> listenerRef = new AtomicReference<>();
var listener = EventListener.builder(PlayerLoginEvent.class)
.handler(event -> {
if (event.getPlayer().getPlayerConnection() == playerConnection) {
event.setSpawningInstance(instance);
event.getPlayer().setRespawnPoint(pos);
process.eventHandler().removeListener(listenerRef.get());
loginCallback.accept(event.getPlayer());
}
}).build();
listenerRef.set(listener);
process.eventHandler().addListener(listener);
public @NotNull CompletableFuture<Player> connect(@NotNull Instance instance, @NotNull Pos pos) {
Player player = new Player(UUID.randomUUID(), "RandName", playerConnection);
player.eventNode().addListener(PlayerLoginEvent.class, event -> {
event.setSpawningInstance(instance);
event.getPlayer().setRespawnPoint(pos);
});
var player = new Player(UUID.randomUUID(), "RandName", playerConnection);
process.connection().startPlayState(player, true);
while (player.getInstance() != instance) { // TODO replace with proper future
env.tick();
}
return CompletableFuture.completedFuture(player);
return process.connection().startPlayState(player, true)
.thenApply(unused -> {
process.connection().updateWaitingPlayers();
return player;
});
}
@Override

View File

@ -25,9 +25,9 @@ public class EntityInstanceIntegrationTest {
@Test
public void playerJoin(Env env) {
var instance = env.createFlatInstance();
var connection = env.createConnection();
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
var player = env.createPlayer(instance, new Pos(0, 42, 0));
assertEquals(instance, player.getInstance());
assertEquals(new Pos(0, 42, 0), player.getPosition());
}
@Test