2022-01-29 14:56:45 +01:00
|
|
|
package net.minestom.server.entity.player;
|
|
|
|
|
2023-08-05 16:30:53 +02:00
|
|
|
import net.kyori.adventure.text.Component;
|
2022-01-29 14:56:45 +01:00
|
|
|
import net.minestom.server.coordinate.Pos;
|
|
|
|
import net.minestom.server.entity.GameMode;
|
|
|
|
import net.minestom.server.entity.Player;
|
2024-01-16 15:47:38 +01:00
|
|
|
import net.minestom.server.entity.damage.DamageType;
|
|
|
|
import net.minestom.server.event.player.PlayerGameModeChangeEvent;
|
|
|
|
import net.minestom.server.message.ChatMessageType;
|
|
|
|
import net.minestom.server.network.packet.client.common.ClientSettingsPacket;
|
2022-01-29 14:56:45 +01:00
|
|
|
import net.minestom.server.network.packet.server.ServerPacket;
|
|
|
|
import net.minestom.server.network.packet.server.play.*;
|
|
|
|
import net.minestom.server.utils.NamespaceID;
|
|
|
|
import net.minestom.server.world.DimensionType;
|
2024-01-16 15:47:38 +01:00
|
|
|
import net.minestom.testing.Collector;
|
|
|
|
import net.minestom.testing.Env;
|
|
|
|
import net.minestom.testing.EnvTest;
|
2022-01-29 14:56:45 +01:00
|
|
|
import org.junit.jupiter.api.Assertions;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
|
|
|
|
import java.time.Duration;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
2024-03-28 02:45:55 +01:00
|
|
|
import static net.minestom.server.entity.Player.*;
|
2023-03-30 03:03:36 +02:00
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
2022-01-29 14:56:45 +01:00
|
|
|
|
|
|
|
@EnvTest
|
|
|
|
public class PlayerIntegrationTest {
|
|
|
|
|
|
|
|
/**
|
2023-08-05 18:53:57 +02:00
|
|
|
* Test to see whether player abilities are updated correctly and events
|
|
|
|
* are handled properly when changing gamemode.
|
2022-01-29 14:56:45 +01:00
|
|
|
*/
|
|
|
|
@Test
|
|
|
|
public void gamemodeTest(Env env) {
|
|
|
|
var instance = env.createFlatInstance();
|
|
|
|
var connection = env.createConnection();
|
|
|
|
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
|
|
|
|
assertEquals(instance, player.getInstance());
|
|
|
|
|
2023-08-05 18:53:57 +02:00
|
|
|
// Abilities
|
|
|
|
{
|
|
|
|
player.setGameMode(GameMode.CREATIVE);
|
|
|
|
assertAbilities(player, true, false, true, true);
|
|
|
|
player.setGameMode(GameMode.SPECTATOR);
|
|
|
|
assertAbilities(player, true, true, true, false);
|
|
|
|
player.setGameMode(GameMode.CREATIVE);
|
|
|
|
assertAbilities(player, true, true, true, true);
|
|
|
|
player.setGameMode(GameMode.ADVENTURE);
|
|
|
|
assertAbilities(player, false, false, false, false);
|
|
|
|
player.setGameMode(GameMode.SURVIVAL);
|
|
|
|
assertAbilities(player, false, false, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
var listener = env.listen(PlayerGameModeChangeEvent.class);
|
|
|
|
// Normal change
|
|
|
|
{
|
|
|
|
listener.followup();
|
|
|
|
assertTrue(player.setGameMode(GameMode.ADVENTURE));
|
|
|
|
}
|
|
|
|
// Change target gamemode event
|
|
|
|
{
|
|
|
|
listener.followup(event -> event.setNewGameMode(GameMode.SPECTATOR));
|
|
|
|
assertTrue(player.setGameMode(GameMode.CREATIVE));
|
|
|
|
assertEquals(GameMode.SPECTATOR, player.getGameMode());
|
|
|
|
}
|
|
|
|
// Cancel event
|
|
|
|
{
|
|
|
|
listener.followup(event -> event.setCancelled(true));
|
|
|
|
assertFalse(player.setGameMode(GameMode.CREATIVE));
|
|
|
|
assertEquals(GameMode.SPECTATOR, player.getGameMode());
|
|
|
|
}
|
2022-01-29 14:56:45 +01:00
|
|
|
}
|
|
|
|
|
2023-01-29 13:05:28 +01:00
|
|
|
@Test
|
|
|
|
public void handSwapTest(Env env) {
|
|
|
|
ClientSettingsPacket packet = new ClientSettingsPacket("en_us", (byte) 16, ChatMessageType.FULL,
|
|
|
|
true, (byte) 127, Player.MainHand.LEFT, true, true);
|
|
|
|
|
|
|
|
var instance = env.createFlatInstance();
|
|
|
|
var connection = env.createConnection();
|
|
|
|
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
|
|
|
|
assertEquals(instance, player.getInstance());
|
|
|
|
env.tick();
|
|
|
|
env.tick();
|
|
|
|
|
2024-01-16 15:47:38 +01:00
|
|
|
player.addPacketToQueue(packet);
|
2023-01-29 13:05:28 +01:00
|
|
|
var collector = connection.trackIncoming();
|
|
|
|
env.tick();
|
|
|
|
env.tick();
|
|
|
|
assertEquals(Player.MainHand.LEFT, player.getSettings().getMainHand());
|
|
|
|
|
|
|
|
boolean found = false;
|
|
|
|
for (ServerPacket serverPacket : collector.collect()) {
|
|
|
|
if (!(serverPacket instanceof EntityMetaDataPacket metaDataPacket)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
assertEquals((byte) 0, metaDataPacket.entries().get(18).value(),
|
|
|
|
"EntityMetaDataPacket has the incorrect hand after client settings update.");
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
Assertions.assertTrue(found, "EntityMetaDataPacket not sent after client settings update.");
|
|
|
|
}
|
|
|
|
|
2022-01-29 14:56:45 +01:00
|
|
|
private void assertAbilities(Player player, boolean isInvulnerable, boolean isFlying, boolean isAllowFlying,
|
|
|
|
boolean isInstantBreak) {
|
|
|
|
assertEquals(isInvulnerable, player.isInvulnerable());
|
|
|
|
assertEquals(isFlying, player.isFlying());
|
|
|
|
assertEquals(isAllowFlying, player.isAllowFlying());
|
|
|
|
assertEquals(isInstantBreak, player.isInstantBreak());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void playerJoinPackets(Env env) {
|
|
|
|
var instance = env.createFlatInstance();
|
|
|
|
var connection = env.createConnection();
|
2022-01-29 15:01:15 +01:00
|
|
|
|
2022-01-29 14:56:45 +01:00
|
|
|
final var packets = List.of(
|
2022-01-29 15:01:15 +01:00
|
|
|
JoinGamePacket.class, ServerDifficultyPacket.class, SpawnPositionPacket.class,
|
|
|
|
DeclareCommandsPacket.class, EntityPropertiesPacket.class, EntityStatusPacket.class,
|
|
|
|
UpdateHealthPacket.class, PlayerAbilitiesPacket.class
|
2022-01-29 14:56:45 +01:00
|
|
|
);
|
2022-01-29 15:01:15 +01:00
|
|
|
final List<Collector<?>> trackers = new ArrayList<>();
|
2022-01-29 14:56:45 +01:00
|
|
|
for (var packet : packets) {
|
|
|
|
trackers.add(connection.trackIncoming(packet));
|
|
|
|
}
|
|
|
|
|
|
|
|
var trackerAll = connection.trackIncoming(ServerPacket.class);
|
|
|
|
|
|
|
|
var player = connection.connect(instance, new Pos(0, 40, 0)).join();
|
|
|
|
assertEquals(instance, player.getInstance());
|
|
|
|
assertEquals(new Pos(0, 40, 0), player.getPosition());
|
|
|
|
|
|
|
|
for (var tracker : trackers) {
|
|
|
|
assertEquals(1, tracker.collect().size());
|
|
|
|
}
|
|
|
|
assertTrue(trackerAll.collect().size() > packets.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test to see whether the packets from Player#refreshPlayer are sent
|
|
|
|
* when changing dimensions
|
|
|
|
*/
|
|
|
|
@Test
|
|
|
|
public void refreshPlayerTest(Env env) {
|
|
|
|
final int TEST_PERMISSION_LEVEL = 2;
|
|
|
|
final var testDimension = DimensionType.builder(NamespaceID.from("minestom:test_dimension")).build();
|
|
|
|
env.process().dimension().addDimension(testDimension);
|
|
|
|
|
|
|
|
var instance = env.createFlatInstance();
|
|
|
|
var instance2 = env.process().instance().createInstanceContainer(testDimension);
|
|
|
|
|
|
|
|
var connection = env.createConnection();
|
|
|
|
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
|
|
|
|
assertEquals(instance, player.getInstance());
|
|
|
|
|
|
|
|
var tracker1 = connection.trackIncoming(UpdateHealthPacket.class);
|
|
|
|
var tracker2 = connection.trackIncoming(SetExperiencePacket.class);
|
|
|
|
var trackerStatus = connection.trackIncoming(EntityStatusPacket.class);
|
|
|
|
var tracker4 = connection.trackIncoming(PlayerAbilitiesPacket.class);
|
|
|
|
|
|
|
|
player.setPermissionLevel(TEST_PERMISSION_LEVEL);
|
|
|
|
|
|
|
|
// #join may cause the thread to hang as scheduled for the next tick when initially in a pool
|
|
|
|
Assertions.assertTimeout(Duration.ofSeconds(2), () -> player.setInstance(instance2).join());
|
|
|
|
assertEquals(instance2, player.getInstance());
|
|
|
|
|
|
|
|
assertEquals(1, tracker1.collect().size());
|
|
|
|
assertEquals(1, tracker2.collect().size());
|
|
|
|
assertEquals(2, trackerStatus.collect().size());
|
|
|
|
assertEquals(1, tracker4.collect().size());
|
|
|
|
|
|
|
|
// Ensure that the player was sent the permission levels
|
|
|
|
for (var statusPacket : trackerStatus.collect()) {
|
|
|
|
assertEquals(player.getEntityId(), statusPacket.entityId());
|
|
|
|
assertEquals(24 + TEST_PERMISSION_LEVEL, statusPacket.status()); // TODO: Remove magic value of 24
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-30 03:03:36 +02:00
|
|
|
@Test
|
|
|
|
public void deathLocationTest(Env env) {
|
|
|
|
String dimensionNamespace = "minestom:test_dimension";
|
|
|
|
final var testDimension = DimensionType.builder(NamespaceID.from(dimensionNamespace)).build();
|
|
|
|
env.process().dimension().addDimension(testDimension);
|
|
|
|
|
|
|
|
var instance = env.process().instance().createInstanceContainer(testDimension);
|
|
|
|
var connection = env.createConnection();
|
|
|
|
var player = connection.connect(instance, new Pos(5, 42, 2)).join();
|
|
|
|
|
|
|
|
assertNull(player.getDeathLocation());
|
2024-01-02 12:42:23 +01:00
|
|
|
player.damage(DamageType.OUT_OF_WORLD, 30);
|
2023-08-05 18:53:57 +02:00
|
|
|
|
2023-03-30 03:03:36 +02:00
|
|
|
assertNotNull(player.getDeathLocation());
|
|
|
|
assertEquals(dimensionNamespace, player.getDeathLocation().dimension());
|
|
|
|
assertEquals(5, player.getDeathLocation().position().x());
|
|
|
|
}
|
2023-08-05 16:30:53 +02:00
|
|
|
|
|
|
|
@Test
|
|
|
|
public void displayNameTest(Env env) {
|
|
|
|
var instance = env.createFlatInstance();
|
|
|
|
var connection = env.createConnection();
|
|
|
|
var tracker = connection.trackIncoming(PlayerInfoUpdatePacket.class);
|
|
|
|
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
|
|
|
|
|
|
|
|
player.setDisplayName(Component.text("Display Name!"));
|
|
|
|
|
|
|
|
var connection2 = env.createConnection();
|
|
|
|
var tracker2 = connection2.trackIncoming(PlayerInfoUpdatePacket.class);
|
|
|
|
connection2.connect(instance, new Pos(0, 42, 0)).join();
|
|
|
|
|
|
|
|
var displayNamePackets = tracker2.collect().stream().filter((packet) ->
|
|
|
|
packet.actions().stream().anyMatch((act) -> act == PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME))
|
|
|
|
.count();
|
|
|
|
assertEquals(1, displayNamePackets);
|
|
|
|
|
|
|
|
var tracker3 = connection2.trackIncoming(PlayerInfoUpdatePacket.class);
|
|
|
|
|
|
|
|
player.setDisplayName(Component.text("Other Name!"));
|
|
|
|
|
|
|
|
var displayNamePackets2 = tracker3.collect().stream().filter((packet) ->
|
|
|
|
packet.actions().stream().anyMatch((act) -> act == PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME))
|
|
|
|
.count();
|
|
|
|
assertEquals(1, displayNamePackets2);
|
|
|
|
|
|
|
|
var displayNamePackets3 = tracker.collect().stream().filter((packet) ->
|
|
|
|
packet.actions().stream().anyMatch((act) -> act == PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME))
|
|
|
|
.count();
|
|
|
|
assertEquals(2, displayNamePackets3);
|
|
|
|
}
|
2022-01-29 14:56:45 +01:00
|
|
|
}
|