mirror of
https://github.com/Minestom/Minestom.git
synced 2024-08-26 22:50:29 +02:00
hollow-cube/1.19.3
Signed-off-by: mworzala <mattheworzala@gmail.com> fix sounds v2 (cherry picked from commit e6d4a2cc919d6ab5aa9402cc871a70535069d803) fix command packet (cherry picked from commit f3efd64f7bd1d0473e0899d202268f77bab35abf) fix sound effect packets (cherry picked from commit 8530b37b354129a2149aafe2820183b28766be00) remove named sound effect & fix sound effect, entity sound effect packet is still wrong (cherry picked from commit 612f6065a12c465c07816c8551b1c44f17c21159) update NamedSoundEffectPacket to 1.19.3 (cherry picked from commit 8c78d9beac96f94770f6fd0e9216452c3421bcfd) update datagen, add read method to player info update (though it seems kinda broken) (cherry picked from commit 6464a72dabc5edaf9b09ef1b8100815965bbad74) Add ChatSession Signed-off-by: TheMode <themode@outlook.fr> (cherry picked from commit0488915fda
) Unnecessary line change Signed-off-by: TheMode <themode@outlook.fr> (cherry picked from commit915836f490
) Make tests compile Signed-off-by: TheMode <themode@outlook.fr> (cherry picked from commit220217fcc1
) Fix info update Signed-off-by: TheMode <themode@outlook.fr> (cherry picked from commit1a606285c0
) Fix unsigned message Signed-off-by: TheMode <themode@outlook.fr> (cherry picked from commit7ba55fdfef
) 1.19.3 support (cherry picked from commitf09fdd862b
)
This commit is contained in:
parent
79ce9570ea
commit
fe9a4291bf
|
@ -17,6 +17,8 @@ application {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(rootProject)
|
implementation(rootProject)
|
||||||
implementation(libs.jNoise)
|
implementation(libs.jNoise)
|
||||||
|
implementation("ch.qos.logback:logback-core:1.4.5")
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.4.5")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<ShadowJar> {
|
tasks.withType<ShadowJar> {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.minestom.demo;
|
package net.minestom.demo;
|
||||||
|
|
||||||
|
import net.kyori.adventure.sound.Sound;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.format.Style;
|
import net.kyori.adventure.text.format.Style;
|
||||||
|
@ -8,6 +9,7 @@ import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.minestom.demo.commands.*;
|
import net.minestom.demo.commands.*;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.command.CommandManager;
|
import net.minestom.server.command.CommandManager;
|
||||||
|
import net.minestom.server.event.player.PlayerChatEvent;
|
||||||
import net.minestom.server.event.server.ServerListPingEvent;
|
import net.minestom.server.event.server.ServerListPingEvent;
|
||||||
import net.minestom.server.extras.lan.OpenToLAN;
|
import net.minestom.server.extras.lan.OpenToLAN;
|
||||||
import net.minestom.server.extras.lan.OpenToLANConfig;
|
import net.minestom.server.extras.lan.OpenToLANConfig;
|
||||||
|
@ -15,6 +17,7 @@ import net.minestom.server.extras.optifine.OptifineSupport;
|
||||||
import net.minestom.server.instance.block.BlockManager;
|
import net.minestom.server.instance.block.BlockManager;
|
||||||
import net.minestom.server.instance.block.rule.vanilla.RedstonePlacementRule;
|
import net.minestom.server.instance.block.rule.vanilla.RedstonePlacementRule;
|
||||||
import net.minestom.server.ping.ResponseData;
|
import net.minestom.server.ping.ResponseData;
|
||||||
|
import net.minestom.server.sound.SoundEvent;
|
||||||
import net.minestom.server.utils.identity.NamedAndIdentified;
|
import net.minestom.server.utils.identity.NamedAndIdentified;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
|
|
||||||
|
@ -96,6 +99,27 @@ public class Main {
|
||||||
//responseData.setPlayersHidden(true);
|
//responseData.setPlayersHidden(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
MinecraftServer.getGlobalEventHandler().addListener(PlayerChatEvent.class, e -> {
|
||||||
|
var playPos = e.getPlayer().getPosition().add(5.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
switch (e.getMessage()) {
|
||||||
|
case "a" -> {
|
||||||
|
System.out.println("with position");
|
||||||
|
e.getPlayer().playSound(Sound.sound(SoundEvent.AMBIENT_CRIMSON_FOREST_MOOD, Sound.Source.MASTER, 1f, 1f), playPos.x(), playPos.y(), playPos.z());
|
||||||
|
}
|
||||||
|
case "b" -> {
|
||||||
|
System.out.println("without anything");
|
||||||
|
e.getPlayer().playSound(Sound.sound(SoundEvent.AMBIENT_CRIMSON_FOREST_MOOD, Sound.Source.MASTER, 1f, 1f));
|
||||||
|
}
|
||||||
|
case "c" -> {
|
||||||
|
System.out.println("with self emitter");
|
||||||
|
e.getPlayer().playSound(Sound.sound(SoundEvent.AMBIENT_CRIMSON_FOREST_MOOD, Sound.Source.MASTER, 1f, 1f), Sound.Emitter.self());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
PlayerInit.init();
|
PlayerInit.init();
|
||||||
|
|
||||||
OptifineSupport.enable();
|
OptifineSupport.enable();
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package net.minestom.demo.commands;
|
package net.minestom.demo.commands;
|
||||||
|
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.sound.Sound;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||||
import net.minestom.server.command.CommandSender;
|
import net.minestom.server.command.CommandSender;
|
||||||
import net.minestom.server.command.builder.Command;
|
import net.minestom.server.command.builder.Command;
|
||||||
import net.minestom.server.command.builder.CommandContext;
|
import net.minestom.server.command.builder.CommandContext;
|
||||||
import net.minestom.server.command.builder.arguments.ArgumentType;
|
import net.minestom.server.command.builder.arguments.ArgumentType;
|
||||||
|
import net.minestom.server.sound.SoundEvent;
|
||||||
|
|
||||||
public class TestCommand extends Command {
|
public class TestCommand extends Command {
|
||||||
|
|
||||||
|
@ -15,7 +19,12 @@ public class TestCommand extends Command {
|
||||||
var block = ArgumentType.BlockState("block");
|
var block = ArgumentType.BlockState("block");
|
||||||
block.setCallback((sender, exception) -> exception.printStackTrace());
|
block.setCallback((sender, exception) -> exception.printStackTrace());
|
||||||
|
|
||||||
|
setDefaultExecutor((sender, context) -> {
|
||||||
|
sender.playSound(Sound.sound(Key.key("item.trumpet.doot"), Sound.Source.PLAYER, 1, 1));
|
||||||
|
AdventurePacketConvertor.createSoundPacket(Sound.sound(Key.key(SoundEvent.BLOCK_ANVIL_HIT.name()), Sound.Source.HOSTILE, 1, 1), sender.asPlayer());
|
||||||
|
});
|
||||||
addSyntax((sender, context) -> System.out.println("executed"), block);
|
addSyntax((sender, context) -> System.out.println("executed"), block);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void usage(CommandSender sender, CommandContext context) {
|
private void usage(CommandSender sender, CommandContext context) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ adventure = "4.12.0"
|
||||||
kotlin = "1.7.22"
|
kotlin = "1.7.22"
|
||||||
hydrazine = "1.7.2"
|
hydrazine = "1.7.2"
|
||||||
dependencyGetter = "v1.0.1"
|
dependencyGetter = "v1.0.1"
|
||||||
minestomData = "1c1921cd41"
|
minestomData = "53e0da5be1"
|
||||||
hephaistos = "2.5.3"
|
hephaistos = "2.5.3"
|
||||||
jetbrainsAnnotations = "23.0.0"
|
jetbrainsAnnotations = "23.0.0"
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ public final class MinecraftServer {
|
||||||
|
|
||||||
public static final ComponentLogger LOGGER = ComponentLogger.logger(MinecraftServer.class);
|
public static final ComponentLogger LOGGER = ComponentLogger.logger(MinecraftServer.class);
|
||||||
|
|
||||||
public static final String VERSION_NAME = "1.19.2";
|
public static final String VERSION_NAME = "1.19.3";
|
||||||
public static final int PROTOCOL_VERSION = 760;
|
public static final int PROTOCOL_VERSION = 761;
|
||||||
|
|
||||||
// Threads
|
// Threads
|
||||||
public static final String THREAD_NAME_BENCHMARK = "Ms-Benchmark";
|
public static final String THREAD_NAME_BENCHMARK = "Ms-Benchmark";
|
||||||
|
|
|
@ -11,6 +11,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.title.Title;
|
import net.kyori.adventure.title.Title;
|
||||||
import net.kyori.adventure.title.TitlePart;
|
import net.kyori.adventure.title.TitlePart;
|
||||||
import net.minestom.server.coordinate.Pos;
|
import net.minestom.server.coordinate.Pos;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
import net.minestom.server.entity.Entity;
|
import net.minestom.server.entity.Entity;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.play.*;
|
import net.minestom.server.network.packet.server.play.*;
|
||||||
|
@ -111,11 +112,11 @@ public class AdventurePacketConvertor {
|
||||||
public static @NotNull ServerPacket createSoundPacket(@NotNull Sound sound, double x, double y, double z) {
|
public static @NotNull ServerPacket createSoundPacket(@NotNull Sound sound, double x, double y, double z) {
|
||||||
final SoundEvent minestomSound = SoundEvent.fromNamespaceId(sound.name().asString());
|
final SoundEvent minestomSound = SoundEvent.fromNamespaceId(sound.name().asString());
|
||||||
if (minestomSound == null) {
|
if (minestomSound == null) {
|
||||||
return new NamedSoundEffectPacket(sound.name().asString(), sound.source(),
|
return new SoundEffectPacket(sound.name().asString(), null, sound.source(),
|
||||||
(int) x, (int) y, (int) z, sound.volume(), sound.pitch(), 0);
|
new Vec(x, y, z), sound.volume(), sound.pitch(), 0);
|
||||||
} else {
|
} else {
|
||||||
return new SoundEffectPacket(minestomSound.id(), sound.source(),
|
return new SoundEffectPacket(minestomSound, null, sound.source(),
|
||||||
(int) x, (int) y, (int) z, sound.volume(), sound.pitch(), 0);
|
new Vec(x, y, z), sound.volume(), sound.pitch(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,11 +136,9 @@ public class AdventurePacketConvertor {
|
||||||
final SoundEvent minestomSound = SoundEvent.fromNamespaceId(sound.name().asString());
|
final SoundEvent minestomSound = SoundEvent.fromNamespaceId(sound.name().asString());
|
||||||
|
|
||||||
if (minestomSound != null) {
|
if (minestomSound != null) {
|
||||||
return new EntitySoundEffectPacket(minestomSound.id(), sound.source(), entity.getEntityId(), sound.volume(), sound.pitch(), 0);
|
return new EntitySoundEffectPacket(minestomSound, null, sound.source(), entity.getEntityId(), sound.volume(), sound.pitch(), 0);
|
||||||
} else {
|
} else {
|
||||||
final Pos pos = entity.getPosition();
|
return new EntitySoundEffectPacket(sound.name().asString(), null, sound.source(), entity.getEntityId(), sound.volume(), sound.pitch(), 0);
|
||||||
return new NamedSoundEffectPacket(sound.name().asString(), sound.source(),
|
|
||||||
(int) pos.x(), (int) pos.y(), (int) pos.z(), sound.volume(), sound.pitch(), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ public class ArgumentPotionEffect extends ArgumentRegistry<PotionEffect> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String parser() {
|
public String parser() {
|
||||||
return "minecraft:mob_effect";
|
// TODO: what replace `minecraft:mob_effect`?
|
||||||
|
return "minecraft:uuid";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
22
src/main/java/net/minestom/server/crypto/ChatBound.java
Normal file
22
src/main/java/net/minestom/server/crypto/ChatBound.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package net.minestom.server.crypto;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.COMPONENT;
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.VAR_INT;
|
||||||
|
|
||||||
|
public record ChatBound(int chatType, Component name, @Nullable Component targetName) implements NetworkBuffer.Writer {
|
||||||
|
public ChatBound(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.read(VAR_INT), reader.read(COMPONENT), reader.readOptional(COMPONENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.write(VAR_INT, chatType);
|
||||||
|
writer.write(COMPONENT, name);
|
||||||
|
writer.writeOptional(COMPONENT, targetName);
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/net/minestom/server/crypto/ChatSession.java
Normal file
18
src/main/java/net/minestom/server/crypto/ChatSession.java
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package net.minestom.server.crypto;
|
||||||
|
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record ChatSession(@NotNull UUID sessionId, @NotNull PlayerPublicKey publicKey) implements NetworkBuffer.Writer {
|
||||||
|
public ChatSession(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.read(NetworkBuffer.UUID), new PlayerPublicKey(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.write(NetworkBuffer.UUID, sessionId);
|
||||||
|
writer.write(publicKey);
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/net/minestom/server/crypto/FilterMask.java
Normal file
28
src/main/java/net/minestom/server/crypto/FilterMask.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package net.minestom.server.crypto;
|
||||||
|
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.LONG_ARRAY;
|
||||||
|
|
||||||
|
public record FilterMask(@NotNull Type type, @NotNull BitSet mask) implements NetworkBuffer.Writer {
|
||||||
|
public FilterMask(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.readEnum(Type.class), BitSet.valueOf(reader.read(LONG_ARRAY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.writeEnum(Type.class, type);
|
||||||
|
if (type == Type.PARTIALLY_FILTERED) {
|
||||||
|
writer.write(LONG_ARRAY, mask.toLongArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
PASS_THROUGH,
|
||||||
|
FULLY_FILTERED,
|
||||||
|
PARTIALLY_FILTERED
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,45 +2,47 @@ package net.minestom.server.crypto;
|
||||||
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public record LastSeenMessages(@NotNull List<@NotNull Entry> entries) implements NetworkBuffer.Writer {
|
import static net.minestom.server.network.NetworkBuffer.VAR_INT;
|
||||||
|
|
||||||
|
public record LastSeenMessages(@NotNull List<@NotNull MessageSignature> entries) implements NetworkBuffer.Writer {
|
||||||
public LastSeenMessages {
|
public LastSeenMessages {
|
||||||
entries = List.copyOf(entries);
|
entries = List.copyOf(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LastSeenMessages(@NotNull NetworkBuffer reader) {
|
public LastSeenMessages(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.readCollection(Entry::new));
|
this(reader.readCollection(MessageSignature::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Entry(UUID from, MessageSignature lastSignature) implements NetworkBuffer.Writer {
|
public record Packed(@NotNull List<MessageSignature.@NotNull Packed> entries) implements NetworkBuffer.Writer {
|
||||||
public Entry(@NotNull NetworkBuffer reader) {
|
public static final Packed EMPTY = new Packed(List.of());
|
||||||
this(reader.read(NetworkBuffer.UUID), new MessageSignature(reader));
|
|
||||||
|
public Packed(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.readCollection(MessageSignature.Packed::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(NetworkBuffer.UUID, from);
|
writer.writeCollection(entries);
|
||||||
writer.write(lastSignature);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Update(LastSeenMessages lastSeen, @Nullable Entry lastReceived) implements NetworkBuffer.Writer {
|
public record Update(int offset, @NotNull BitSet acknowledged) implements NetworkBuffer.Writer {
|
||||||
public Update(@NotNull NetworkBuffer reader) {
|
public Update(@NotNull NetworkBuffer reader) {
|
||||||
this(new LastSeenMessages(reader), reader.readOptional(Entry::new));
|
this(reader.read(VAR_INT), reader.readFixedBitSet(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(lastSeen);
|
writer.write(VAR_INT, offset);
|
||||||
writer.writeOptional(lastReceived);
|
writer.writeFixedBitSet(acknowledged, 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,45 @@ package net.minestom.server.crypto;
|
||||||
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.BYTE_ARRAY;
|
import static net.minestom.server.network.NetworkBuffer.RAW_BYTES;
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.VAR_INT;
|
||||||
|
|
||||||
public record MessageSignature(byte @NotNull [] signature) implements NetworkBuffer.Writer {
|
public record MessageSignature(byte @NotNull [] signature) implements NetworkBuffer.Writer {
|
||||||
|
public MessageSignature {
|
||||||
|
if (signature.length != 256) {
|
||||||
|
throw new IllegalArgumentException("Signature must be 256 bytes long");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MessageSignature(@NotNull NetworkBuffer reader) {
|
public MessageSignature(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(BYTE_ARRAY));
|
this(reader.readBytes(256));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(BYTE_ARRAY, signature);
|
writer.write(RAW_BYTES, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Packed(int id, @UnknownNullability MessageSignature fullSignature) implements NetworkBuffer.Writer {
|
||||||
|
public Packed(@NotNull NetworkBuffer reader) {
|
||||||
|
this(read(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Packed(@NotNull Packed packed) {
|
||||||
|
this(packed.id, packed.fullSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.write(VAR_INT, id + 1);
|
||||||
|
if (id == 0) writer.write(fullSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Packed read(NetworkBuffer reader) {
|
||||||
|
final int id = reader.read(VAR_INT) - 1;
|
||||||
|
return new Packed(id, id == -1 ? new MessageSignature(reader) : null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package net.minestom.server.crypto;
|
||||||
|
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public final class SignedMessageBody {
|
||||||
|
|
||||||
|
public record Packed(@NotNull String content, @NotNull Instant timeStamp, long salt,
|
||||||
|
LastSeenMessages.@NotNull Packed lastSeen) implements NetworkBuffer.Writer {
|
||||||
|
public Packed {
|
||||||
|
if (content.length() > 256) {
|
||||||
|
throw new IllegalArgumentException("Message content too long");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packed(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.read(NetworkBuffer.STRING), Instant.ofEpochMilli(reader.read(NetworkBuffer.LONG)),
|
||||||
|
reader.read(NetworkBuffer.LONG), new LastSeenMessages.Packed(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.write(NetworkBuffer.STRING, content);
|
||||||
|
writer.write(NetworkBuffer.LONG, timeStamp.toEpochMilli());
|
||||||
|
writer.write(NetworkBuffer.LONG, salt);
|
||||||
|
writer.write(lastSeen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -374,8 +374,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||||
// TODO: separate living entity categories
|
// TODO: separate living entity categories
|
||||||
soundCategory = Source.HOSTILE;
|
soundCategory = Source.HOSTILE;
|
||||||
}
|
}
|
||||||
sendPacketToViewersAndSelf(new SoundEffectPacket(sound, soundCategory,
|
sendPacketToViewersAndSelf(new SoundEffectPacket(sound, null, soundCategory,
|
||||||
getPosition(), 1.0f, 1.0f));
|
getPosition(), 1.0f, 1.0f, 0));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,10 @@ public final class Metadata {
|
||||||
return new MetadataImpl.EntryImpl<>(TYPE_VARINT, value, NetworkBuffer.VAR_INT);
|
return new MetadataImpl.EntryImpl<>(TYPE_VARINT, value, NetworkBuffer.VAR_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Entry<Long> Long(long value) {
|
||||||
|
return new MetadataImpl.EntryImpl<>(TYPE_LONG, value, NetworkBuffer.LONG);
|
||||||
|
}
|
||||||
|
|
||||||
public static Entry<Float> Float(float value) {
|
public static Entry<Float> Float(float value) {
|
||||||
return new MetadataImpl.EntryImpl<>(TYPE_FLOAT, value, NetworkBuffer.FLOAT);
|
return new MetadataImpl.EntryImpl<>(TYPE_FLOAT, value, NetworkBuffer.FLOAT);
|
||||||
}
|
}
|
||||||
|
@ -97,23 +101,24 @@ public final class Metadata {
|
||||||
|
|
||||||
public static final byte TYPE_BYTE = 0;
|
public static final byte TYPE_BYTE = 0;
|
||||||
public static final byte TYPE_VARINT = 1;
|
public static final byte TYPE_VARINT = 1;
|
||||||
public static final byte TYPE_FLOAT = 2;
|
public static final byte TYPE_LONG = 2;
|
||||||
public static final byte TYPE_STRING = 3;
|
public static final byte TYPE_FLOAT = 3;
|
||||||
public static final byte TYPE_CHAT = 4;
|
public static final byte TYPE_STRING = 4;
|
||||||
public static final byte TYPE_OPTCHAT = 5;
|
public static final byte TYPE_CHAT = 5;
|
||||||
public static final byte TYPE_SLOT = 6;
|
public static final byte TYPE_OPTCHAT = 6;
|
||||||
public static final byte TYPE_BOOLEAN = 7;
|
public static final byte TYPE_SLOT = 7;
|
||||||
public static final byte TYPE_ROTATION = 8;
|
public static final byte TYPE_BOOLEAN = 8;
|
||||||
public static final byte TYPE_POSITION = 9;
|
public static final byte TYPE_ROTATION = 9;
|
||||||
public static final byte TYPE_OPTPOSITION = 10;
|
public static final byte TYPE_POSITION = 10;
|
||||||
public static final byte TYPE_DIRECTION = 11;
|
public static final byte TYPE_OPTPOSITION = 11;
|
||||||
public static final byte TYPE_OPTUUID = 12;
|
public static final byte TYPE_DIRECTION = 12;
|
||||||
public static final byte TYPE_OPTBLOCKID = 13;
|
public static final byte TYPE_OPTUUID = 13;
|
||||||
public static final byte TYPE_NBT = 14;
|
public static final byte TYPE_OPTBLOCKID = 14;
|
||||||
public static final byte TYPE_PARTICLE = 15;
|
public static final byte TYPE_NBT = 15;
|
||||||
public static final byte TYPE_VILLAGERDATA = 16;
|
public static final byte TYPE_PARTICLE = 16;
|
||||||
public static final byte TYPE_OPTVARINT = 17;
|
public static final byte TYPE_VILLAGERDATA = 17;
|
||||||
public static final byte TYPE_POSE = 18;
|
public static final byte TYPE_OPTVARINT = 18;
|
||||||
|
public static final byte TYPE_POSE = 19;
|
||||||
|
|
||||||
private static final VarHandle NOTIFIED_CHANGES;
|
private static final VarHandle NOTIFIED_CHANGES;
|
||||||
|
|
||||||
|
|
|
@ -944,8 +944,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||||
*/
|
*/
|
||||||
public void setDisplayName(@Nullable Component displayName) {
|
public void setDisplayName(@Nullable Component displayName) {
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
PacketUtils.broadcastPacket(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_DISPLAY_NAME,
|
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME, infoEntry()));
|
||||||
new PlayerInfoPacket.UpdateDisplayName(getUuid(), displayName)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -973,8 +972,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||||
|
|
||||||
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket(getEntityId());
|
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket(getEntityId());
|
||||||
|
|
||||||
final PlayerInfoPacket removePlayerPacket = getRemovePlayerToList();
|
final PlayerInfoRemovePacket removePlayerPacket = getRemovePlayerToList();
|
||||||
final PlayerInfoPacket addPlayerPacket = getAddPlayerToList();
|
final PlayerInfoUpdatePacket addPlayerPacket = getAddPlayerToList();
|
||||||
|
|
||||||
RespawnPacket respawnPacket = new RespawnPacket(getDimensionType().toString(), getDimensionType().getName().asString(),
|
RespawnPacket respawnPacket = new RespawnPacket(getDimensionType().toString(), getDimensionType().getName().asString(),
|
||||||
0, gameMode, gameMode, false, levelFlat, true, deathLocation);
|
0, gameMode, gameMode, false, levelFlat, true, deathLocation);
|
||||||
|
@ -1308,8 +1307,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||||
// Condition to prevent sending the packets before spawning the player
|
// Condition to prevent sending the packets before spawning the player
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.CHANGE_GAMEMODE, gameMode.id()));
|
sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.CHANGE_GAMEMODE, gameMode.id()));
|
||||||
PacketUtils.broadcastPacket(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_GAMEMODE,
|
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, infoEntry()));
|
||||||
new PlayerInfoPacket.UpdateGameMode(getUuid(), gameMode)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The client updates their abilities based on the GameMode as follows
|
// The client updates their abilities based on the GameMode as follows
|
||||||
|
@ -1809,8 +1807,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||||
*/
|
*/
|
||||||
public void refreshLatency(int latency) {
|
public void refreshLatency(int latency) {
|
||||||
this.latency = latency;
|
this.latency = latency;
|
||||||
PacketUtils.broadcastPacket(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_LATENCY,
|
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_LATENCY, infoEntry()));
|
||||||
new PlayerInfoPacket.UpdateLatency(getUuid(), latency)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshOnGround(boolean onGround) {
|
public void refreshOnGround(boolean onGround) {
|
||||||
|
@ -1928,24 +1925,29 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||||
/**
|
/**
|
||||||
* Gets the packet to add the player from the tab-list.
|
* Gets the packet to add the player from the tab-list.
|
||||||
*
|
*
|
||||||
* @return a {@link PlayerInfoPacket} to add the player
|
* @return a {@link PlayerInfoUpdatePacket} to add the player
|
||||||
*/
|
*/
|
||||||
protected @NotNull PlayerInfoPacket getAddPlayerToList() {
|
protected @NotNull PlayerInfoUpdatePacket getAddPlayerToList() {
|
||||||
final PlayerSkin skin = this.skin;
|
return new PlayerInfoUpdatePacket(EnumSet.of(PlayerInfoUpdatePacket.Action.ADD_PLAYER, PlayerInfoUpdatePacket.Action.UPDATE_LISTED),
|
||||||
List<PlayerInfoPacket.AddPlayer.Property> prop = skin != null ?
|
List.of(infoEntry()));
|
||||||
List.of(new PlayerInfoPacket.AddPlayer.Property("textures", skin.textures(), skin.signature())) :
|
|
||||||
List.of();
|
|
||||||
return new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER,
|
|
||||||
new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), prop, getGameMode(), getLatency(), displayName, null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the packet to remove the player from the tab-list.
|
* Gets the packet to remove the player from the tab-list.
|
||||||
*
|
*
|
||||||
* @return a {@link PlayerInfoPacket} to remove the player
|
* @return a {@link PlayerInfoRemovePacket} to remove the player
|
||||||
*/
|
*/
|
||||||
protected @NotNull PlayerInfoPacket getRemovePlayerToList() {
|
protected @NotNull PlayerInfoRemovePacket getRemovePlayerToList() {
|
||||||
return new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER, new PlayerInfoPacket.RemovePlayer(getUuid()));
|
return new PlayerInfoRemovePacket(getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerInfoUpdatePacket.Entry infoEntry() {
|
||||||
|
final PlayerSkin skin = this.skin;
|
||||||
|
List<PlayerInfoUpdatePacket.Property> prop = skin != null ?
|
||||||
|
List.of(new PlayerInfoUpdatePacket.Property("textures", skin.textures(), skin.signature())) :
|
||||||
|
List.of();
|
||||||
|
return new PlayerInfoUpdatePacket.Entry(getUuid(), getUsername(), prop,
|
||||||
|
true, getLatency(), getGameMode(), displayName, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,9 +16,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTWriter;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -204,6 +202,43 @@ public final class NetworkBuffer {
|
||||||
return enumClass.getEnumConstants()[read(VAR_INT)];
|
return enumClass.getEnumConstants()[read(VAR_INT)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <E extends Enum<E>> void writeEnumSet(EnumSet<E> enumSet, Class<E> enumType) {
|
||||||
|
final E[] values = enumType.getEnumConstants();
|
||||||
|
BitSet bitSet = new BitSet(values.length);
|
||||||
|
for (int i = 0; i < values.length; ++i) {
|
||||||
|
bitSet.set(i, enumSet.contains(values[i]));
|
||||||
|
}
|
||||||
|
writeFixedBitSet(bitSet, values.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E extends Enum<E>> @NotNull EnumSet<E> readEnumSet(Class<E> enumType) {
|
||||||
|
final E[] values = enumType.getEnumConstants();
|
||||||
|
BitSet bitSet = readFixedBitSet(values.length);
|
||||||
|
EnumSet<E> enumSet = EnumSet.noneOf(enumType);
|
||||||
|
for (int i = 0; i < values.length; ++i) {
|
||||||
|
if (bitSet.get(i)) {
|
||||||
|
enumSet.add(values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeFixedBitSet(BitSet set, int length) {
|
||||||
|
final int setLength = set.length();
|
||||||
|
if (setLength > length) {
|
||||||
|
throw new IllegalArgumentException("BitSet is larger than expected size (" + setLength + ">" + length + ")");
|
||||||
|
} else {
|
||||||
|
final byte[] array = set.toByteArray();
|
||||||
|
write(RAW_BYTES, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public BitSet readFixedBitSet(int length) {
|
||||||
|
final byte[] array = readBytes((length + 7) / 8);
|
||||||
|
return BitSet.valueOf(array);
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] readBytes(int length) {
|
public byte[] readBytes(int length) {
|
||||||
byte[] bytes = new byte[length];
|
byte[] bytes = new byte[length];
|
||||||
nioBuffer.get(readIndex, bytes, 0, length);
|
nioBuffer.get(readIndex, bytes, 0, length);
|
||||||
|
|
|
@ -58,33 +58,33 @@ public sealed class ClientPacketsHandler permits ClientPacketsHandler.Status, Cl
|
||||||
register(0x03, ClientChatAckPacket::new);
|
register(0x03, ClientChatAckPacket::new);
|
||||||
register(0x04, ClientCommandChatPacket::new);
|
register(0x04, ClientCommandChatPacket::new);
|
||||||
register(0x05, ClientChatMessagePacket::new);
|
register(0x05, ClientChatMessagePacket::new);
|
||||||
register(0x06, ClientChatPreviewPacket::new);
|
register(0x06, ClientStatusPacket::new);
|
||||||
register(0x07, ClientStatusPacket::new);
|
register(0x07, ClientSettingsPacket::new);
|
||||||
register(0x08, ClientSettingsPacket::new);
|
register(0x08, ClientTabCompletePacket::new);
|
||||||
register(0x09, ClientTabCompletePacket::new);
|
register(0x09, ClientClickWindowButtonPacket::new);
|
||||||
register(0x0A, ClientClickWindowButtonPacket::new);
|
register(0x0A, ClientClickWindowPacket::new);
|
||||||
register(0x0B, ClientClickWindowPacket::new);
|
register(0x0B, ClientCloseWindowPacket::new);
|
||||||
register(0x0C, ClientCloseWindowPacket::new);
|
register(0x0C, ClientPluginMessagePacket::new);
|
||||||
register(0x0D, ClientPluginMessagePacket::new);
|
register(0x0D, ClientEditBookPacket::new);
|
||||||
register(0x0E, ClientEditBookPacket::new);
|
register(0x0E, ClientQueryEntityNbtPacket::new);
|
||||||
register(0x0F, ClientQueryEntityNbtPacket::new);
|
register(0x0F, ClientInteractEntityPacket::new);
|
||||||
register(0x10, ClientInteractEntityPacket::new);
|
register(0x10, ClientGenerateStructurePacket::new);
|
||||||
register(0x11, ClientGenerateStructurePacket::new);
|
register(0x11, ClientKeepAlivePacket::new);
|
||||||
register(0x12, ClientKeepAlivePacket::new);
|
|
||||||
// 0x12 packet not used server-side
|
// 0x12 packet not used server-side
|
||||||
register(0x14, ClientPlayerPositionPacket::new);
|
register(0x13, ClientPlayerPositionPacket::new);
|
||||||
register(0x15, ClientPlayerPositionAndRotationPacket::new);
|
register(0x14, ClientPlayerPositionAndRotationPacket::new);
|
||||||
register(0x16, ClientPlayerRotationPacket::new);
|
register(0x15, ClientPlayerRotationPacket::new);
|
||||||
register(0x17, ClientPlayerPacket::new);
|
register(0x16, ClientPlayerPacket::new);
|
||||||
register(0x18, ClientVehicleMovePacket::new);
|
register(0x17, ClientVehicleMovePacket::new);
|
||||||
register(0x19, ClientSteerBoatPacket::new);
|
register(0x18, ClientSteerBoatPacket::new);
|
||||||
register(0x1A, ClientPickItemPacket::new);
|
register(0x19, ClientPickItemPacket::new);
|
||||||
register(0x1B, ClientCraftRecipeRequest::new);
|
register(0x1A, ClientCraftRecipeRequest::new);
|
||||||
register(0x1C, ClientPlayerAbilitiesPacket::new);
|
register(0x1B, ClientPlayerAbilitiesPacket::new);
|
||||||
register(0x1D, ClientPlayerDiggingPacket::new);
|
register(0x1C, ClientPlayerDiggingPacket::new);
|
||||||
register(0x1E, ClientEntityActionPacket::new);
|
register(0x1D, ClientEntityActionPacket::new);
|
||||||
register(0x1F, ClientSteerVehiclePacket::new);
|
register(0x1E, ClientSteerVehiclePacket::new);
|
||||||
register(0x20, ClientPongPacket::new);
|
register(0x1F, ClientPongPacket::new);
|
||||||
|
register(0x20, ClientChatSessionUpdatePacket::new);
|
||||||
register(0x21, ClientSetRecipeBookStatePacket::new);
|
register(0x21, ClientSetRecipeBookStatePacket::new);
|
||||||
register(0x22, ClientSetDisplayedRecipePacket::new);
|
register(0x22, ClientSetDisplayedRecipePacket::new);
|
||||||
register(0x23, ClientNameItemPacket::new);
|
register(0x23, ClientNameItemPacket::new);
|
||||||
|
|
|
@ -3,18 +3,13 @@ package net.minestom.server.network.packet.client.login;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.crypto.SaltSignaturePair;
|
|
||||||
import net.minestom.server.crypto.SignatureValidator;
|
|
||||||
import net.minestom.server.extras.MojangAuth;
|
import net.minestom.server.extras.MojangAuth;
|
||||||
import net.minestom.server.extras.mojangAuth.MojangCrypt;
|
import net.minestom.server.extras.mojangAuth.MojangCrypt;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.client.ClientPreplayPacket;
|
import net.minestom.server.network.packet.client.ClientPreplayPacket;
|
||||||
import net.minestom.server.network.player.PlayerConnection;
|
import net.minestom.server.network.player.PlayerConnection;
|
||||||
import net.minestom.server.network.player.PlayerSocketConnection;
|
import net.minestom.server.network.player.PlayerSocketConnection;
|
||||||
import net.minestom.server.utils.Either;
|
|
||||||
import net.minestom.server.utils.InterfaceUtils;
|
|
||||||
import net.minestom.server.utils.async.AsyncUtils;
|
import net.minestom.server.utils.async.AsyncUtils;
|
||||||
import net.minestom.server.utils.crypto.KeyUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
@ -28,14 +23,14 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.BYTE_ARRAY;
|
||||||
|
|
||||||
public record EncryptionResponsePacket(byte[] sharedSecret,
|
public record EncryptionResponsePacket(byte[] sharedSecret,
|
||||||
Either<byte[], SaltSignaturePair> nonceOrSignature) implements ClientPreplayPacket {
|
byte[] encryptedVerifyToken) implements ClientPreplayPacket {
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
|
|
||||||
public EncryptionResponsePacket(@NotNull NetworkBuffer reader) {
|
public EncryptionResponsePacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(BYTE_ARRAY), reader.readEither(networkBuffer -> networkBuffer.read(BYTE_ARRAY), SaltSignaturePair::new));
|
this(reader.read(BYTE_ARRAY), reader.read(BYTE_ARRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,15 +45,8 @@ public record EncryptionResponsePacket(byte[] sharedSecret,
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasPublicKey = connection.playerPublicKey() != null;
|
final boolean hasPublicKey = connection.playerPublicKey() != null;
|
||||||
final boolean verificationFailed = nonceOrSignature.map(
|
final boolean verificationFailed = hasPublicKey || !Arrays.equals(socketConnection.getNonce(),
|
||||||
nonce -> hasPublicKey || !Arrays.equals(socketConnection.getNonce(),
|
MojangCrypt.decryptUsingKey(MojangAuth.getKeyPair().getPrivate(), encryptedVerifyToken));
|
||||||
MojangCrypt.decryptUsingKey(MojangAuth.getKeyPair().getPrivate(), nonce)),
|
|
||||||
signature -> !hasPublicKey || !SignatureValidator
|
|
||||||
.from(connection.playerPublicKey().publicKey(), KeyUtils.SignatureAlgorithm.SHA256withRSA)
|
|
||||||
.validate(binaryWriter -> {
|
|
||||||
binaryWriter.write(RAW_BYTES, socketConnection.getNonce());
|
|
||||||
binaryWriter.write(LONG, signature.salt());
|
|
||||||
}, signature.signature()));
|
|
||||||
|
|
||||||
if (verificationFailed) {
|
if (verificationFailed) {
|
||||||
MinecraftServer.LOGGER.error("Encryption failed for {}", loginUsername);
|
MinecraftServer.LOGGER.error("Encryption failed for {}", loginUsername);
|
||||||
|
@ -111,8 +99,7 @@ public record EncryptionResponsePacket(byte[] sharedSecret,
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(BYTE_ARRAY, sharedSecret);
|
writer.write(BYTE_ARRAY, sharedSecret);
|
||||||
writer.writeEither(nonceOrSignature, (networkBuffer, bytes) -> networkBuffer.write(BYTE_ARRAY, bytes),
|
writer.write(BYTE_ARRAY, encryptedVerifyToken);
|
||||||
InterfaceUtils.flipBiConsumer(SaltSignaturePair::write));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKey getSecretKey() {
|
private SecretKey getSecretKey() {
|
||||||
|
|
|
@ -2,9 +2,6 @@ package net.minestom.server.network.packet.client.login;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.minestom.server.MinecraftServer;
|
|
||||||
import net.minestom.server.crypto.PlayerPublicKey;
|
|
||||||
import net.minestom.server.crypto.SignatureValidator;
|
|
||||||
import net.minestom.server.extras.MojangAuth;
|
import net.minestom.server.extras.MojangAuth;
|
||||||
import net.minestom.server.extras.bungee.BungeeCordProxy;
|
import net.minestom.server.extras.bungee.BungeeCordProxy;
|
||||||
import net.minestom.server.extras.velocity.VelocityProxy;
|
import net.minestom.server.extras.velocity.VelocityProxy;
|
||||||
|
@ -19,45 +16,22 @@ import net.minestom.server.network.player.PlayerSocketConnection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.STRING;
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.UUID;
|
||||||
|
|
||||||
public record LoginStartPacket(@NotNull String username,
|
public record LoginStartPacket(@NotNull String username,
|
||||||
@Nullable PlayerPublicKey publicKey,
|
|
||||||
@Nullable UUID profileId) implements ClientPreplayPacket {
|
@Nullable UUID profileId) implements ClientPreplayPacket {
|
||||||
private static final Component ALREADY_CONNECTED = Component.text("You are already on this server", NamedTextColor.RED);
|
private static final Component ALREADY_CONNECTED = Component.text("You are already on this server", NamedTextColor.RED);
|
||||||
|
|
||||||
public LoginStartPacket(@NotNull NetworkBuffer reader) {
|
public LoginStartPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(STRING), reader.readOptional(PlayerPublicKey::new), reader.readOptional(UUID));
|
this(reader.read(STRING), reader.readOptional(UUID));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(@NotNull PlayerConnection connection) {
|
public void process(@NotNull PlayerConnection connection) {
|
||||||
// TODO use uuid
|
|
||||||
// TODO configurable check & messages
|
|
||||||
if (publicKey != null) {
|
|
||||||
if (!SignatureValidator.YGGDRASIL.validate(binaryWriter -> {
|
|
||||||
if (profileId != null) {
|
|
||||||
binaryWriter.write(LONG, profileId.getMostSignificantBits());
|
|
||||||
binaryWriter.write(LONG, profileId.getLeastSignificantBits());
|
|
||||||
} else {
|
|
||||||
MinecraftServer.LOGGER.warn("Profile ID was null for player {}, signature will not match!", username);
|
|
||||||
}
|
|
||||||
binaryWriter.write(LONG, publicKey.expiresAt().toEpochMilli());
|
|
||||||
binaryWriter.write(RAW_BYTES, publicKey.publicKey().getEncoded());
|
|
||||||
}, publicKey.signature())) {
|
|
||||||
connection.sendPacket(new LoginDisconnectPacket(Component.text("Invalid Profile Public Key!")));
|
|
||||||
connection.disconnect();
|
|
||||||
}
|
|
||||||
if (publicKey.expiresAt().isBefore(Instant.now())) {
|
|
||||||
connection.sendPacket(new LoginDisconnectPacket(Component.text("Expired Profile Public Key!")));
|
|
||||||
connection.disconnect();
|
|
||||||
}
|
|
||||||
connection.setPlayerPublicKey(publicKey);
|
|
||||||
}
|
|
||||||
final boolean isSocketConnection = connection instanceof PlayerSocketConnection;
|
final boolean isSocketConnection = connection instanceof PlayerSocketConnection;
|
||||||
// Proxy support (only for socket clients) and cache the login username
|
// Proxy support (only for socket clients) and cache the login username
|
||||||
if (isSocketConnection) {
|
if (isSocketConnection) {
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
package net.minestom.server.network.packet.client.play;
|
package net.minestom.server.network.packet.client.play;
|
||||||
|
|
||||||
import net.minestom.server.crypto.LastSeenMessages;
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.client.ClientPacket;
|
import net.minestom.server.network.packet.client.ClientPacket;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public record ClientChatAckPacket(@NotNull LastSeenMessages.Update update) implements ClientPacket {
|
import static net.minestom.server.network.NetworkBuffer.VAR_INT;
|
||||||
|
|
||||||
|
public record ClientChatAckPacket(int offset) implements ClientPacket {
|
||||||
public ClientChatAckPacket(@NotNull NetworkBuffer reader) {
|
public ClientChatAckPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(new LastSeenMessages.Update(reader));
|
this(reader.read(VAR_INT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(update);
|
writer.write(VAR_INT, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,23 @@
|
||||||
package net.minestom.server.network.packet.client.play;
|
package net.minestom.server.network.packet.client.play;
|
||||||
|
|
||||||
import net.minestom.server.crypto.LastSeenMessages;
|
|
||||||
import net.minestom.server.crypto.MessageSignature;
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.client.ClientPacket;
|
import net.minestom.server.network.packet.client.ClientPacket;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record ClientChatMessagePacket(@NotNull String message,
|
public record ClientChatMessagePacket(String message, long timestamp,
|
||||||
long timestamp, long salt, @NotNull MessageSignature signature,
|
long salt, byte @Nullable [] signature,
|
||||||
boolean signedPreview,
|
int ackOffset, BitSet ackList) implements ClientPacket {
|
||||||
@NotNull LastSeenMessages.Update lastSeenMessages) implements ClientPacket {
|
|
||||||
public ClientChatMessagePacket {
|
|
||||||
if (message.length() > 256) {
|
|
||||||
throw new IllegalArgumentException("Message cannot be more than 256 characters long.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientChatMessagePacket(@NotNull NetworkBuffer reader) {
|
public ClientChatMessagePacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(STRING),
|
this(reader.read(STRING), reader.read(LONG),
|
||||||
reader.read(LONG), reader.read(LONG), new MessageSignature(reader),
|
reader.read(LONG), reader.readOptional(r -> r.readBytes(256)),
|
||||||
reader.read(BOOLEAN),
|
reader.read(VAR_INT), BitSet.valueOf(reader.readBytes(3)));
|
||||||
new LastSeenMessages.Update(reader));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,8 +25,8 @@ public record ClientChatMessagePacket(@NotNull String message,
|
||||||
writer.write(STRING, message);
|
writer.write(STRING, message);
|
||||||
writer.write(LONG, timestamp);
|
writer.write(LONG, timestamp);
|
||||||
writer.write(LONG, salt);
|
writer.write(LONG, salt);
|
||||||
writer.write(signature);
|
writer.writeOptional(BYTE_ARRAY, signature);
|
||||||
writer.write(BOOLEAN, signedPreview);
|
writer.write(VAR_INT, ackOffset);
|
||||||
writer.write(lastSeenMessages);
|
writer.write(RAW_BYTES, Arrays.copyOf(ackList.toByteArray(), 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package net.minestom.server.network.packet.client.play;
|
|
||||||
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
|
||||||
import net.minestom.server.network.packet.client.ClientPacket;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.INT;
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.STRING;
|
|
||||||
|
|
||||||
public record ClientChatPreviewPacket(int queryId, @NotNull String query) implements ClientPacket {
|
|
||||||
public ClientChatPreviewPacket {
|
|
||||||
if (query.length() > 256) {
|
|
||||||
throw new IllegalArgumentException("Query length cannot be greater than 256");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientChatPreviewPacket(@NotNull NetworkBuffer reader) {
|
|
||||||
this(reader.read(INT), reader.read(STRING));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(INT, queryId);
|
|
||||||
writer.write(STRING, query);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package net.minestom.server.network.packet.client.play;
|
||||||
|
|
||||||
|
import net.minestom.server.crypto.ChatSession;
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import net.minestom.server.network.packet.client.ClientPacket;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public record ClientChatSessionUpdatePacket(@NotNull ChatSession chatSession) implements ClientPacket {
|
||||||
|
public ClientChatSessionUpdatePacket(@NotNull NetworkBuffer reader) {
|
||||||
|
this(new ChatSession(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.write(chatSession);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,11 @@ import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.client.ClientPacket;
|
import net.minestom.server.network.packet.client.ClientPacket;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.LONG;
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.STRING;
|
||||||
|
|
||||||
public record ClientCommandChatPacket(@NotNull String message, long timestamp,
|
public record ClientCommandChatPacket(@NotNull String message, long timestamp,
|
||||||
long salt, @NotNull ArgumentSignatures signatures,
|
long salt, @NotNull ArgumentSignatures signatures,
|
||||||
boolean signedPreview,
|
|
||||||
LastSeenMessages.@NotNull Update lastSeenMessages) implements ClientPacket {
|
LastSeenMessages.@NotNull Update lastSeenMessages) implements ClientPacket {
|
||||||
public ClientCommandChatPacket {
|
public ClientCommandChatPacket {
|
||||||
if (message.length() > 256) {
|
if (message.length() > 256) {
|
||||||
|
@ -20,7 +20,8 @@ public record ClientCommandChatPacket(@NotNull String message, long timestamp,
|
||||||
|
|
||||||
public ClientCommandChatPacket(@NotNull NetworkBuffer reader) {
|
public ClientCommandChatPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(STRING), reader.read(LONG),
|
this(reader.read(STRING), reader.read(LONG),
|
||||||
reader.read(LONG), new ArgumentSignatures(reader), reader.read(BOOLEAN), new LastSeenMessages.Update(reader));
|
reader.read(LONG), new ArgumentSignatures(reader),
|
||||||
|
new LastSeenMessages.Update(reader));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,7 +30,6 @@ public record ClientCommandChatPacket(@NotNull String message, long timestamp,
|
||||||
writer.write(LONG, timestamp);
|
writer.write(LONG, timestamp);
|
||||||
writer.write(LONG, salt);
|
writer.write(LONG, salt);
|
||||||
writer.write(signatures);
|
writer.write(signatures);
|
||||||
writer.write(BOOLEAN, signedPreview);
|
|
||||||
writer.write(lastSeenMessages);
|
writer.write(lastSeenMessages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ public final class ServerPacketIdentifier {
|
||||||
public static final int BLOCK_CHANGE = nextPlayId();
|
public static final int BLOCK_CHANGE = nextPlayId();
|
||||||
public static final int BOSS_BAR = nextPlayId();
|
public static final int BOSS_BAR = nextPlayId();
|
||||||
public static final int SERVER_DIFFICULTY = nextPlayId();
|
public static final int SERVER_DIFFICULTY = nextPlayId();
|
||||||
public static final int CHAT_PREVIEW = nextPlayId();
|
|
||||||
public static final int CLEAR_TITLES = nextPlayId();
|
public static final int CLEAR_TITLES = nextPlayId();
|
||||||
public static final int TAB_COMPLETE = nextPlayId();
|
public static final int TAB_COMPLETE = nextPlayId();
|
||||||
public static final int DECLARE_COMMANDS = nextPlayId();
|
public static final int DECLARE_COMMANDS = nextPlayId();
|
||||||
|
@ -34,9 +33,9 @@ public final class ServerPacketIdentifier {
|
||||||
public static final int SET_COOLDOWN = nextPlayId();
|
public static final int SET_COOLDOWN = nextPlayId();
|
||||||
public static final int CUSTOM_CHAT_COMPLETIONS = nextPlayId();
|
public static final int CUSTOM_CHAT_COMPLETIONS = nextPlayId();
|
||||||
public static final int PLUGIN_MESSAGE = nextPlayId();
|
public static final int PLUGIN_MESSAGE = nextPlayId();
|
||||||
public static final int NAMED_SOUND_EFFECT = nextPlayId();
|
|
||||||
public static final int DELETE_CHAT_MESSAGE = nextPlayId();
|
public static final int DELETE_CHAT_MESSAGE = nextPlayId();
|
||||||
public static final int DISCONNECT = nextPlayId();
|
public static final int DISCONNECT = nextPlayId();
|
||||||
|
public static final int DISGUISED_CHAT = nextPlayId();
|
||||||
public static final int ENTITY_STATUS = nextPlayId();
|
public static final int ENTITY_STATUS = nextPlayId();
|
||||||
public static final int EXPLOSION = nextPlayId();
|
public static final int EXPLOSION = nextPlayId();
|
||||||
public static final int UNLOAD_CHUNK = nextPlayId();
|
public static final int UNLOAD_CHUNK = nextPlayId();
|
||||||
|
@ -61,12 +60,12 @@ public final class ServerPacketIdentifier {
|
||||||
public static final int PING = nextPlayId();
|
public static final int PING = nextPlayId();
|
||||||
public static final int CRAFT_RECIPE_RESPONSE = nextPlayId();
|
public static final int CRAFT_RECIPE_RESPONSE = nextPlayId();
|
||||||
public static final int PLAYER_ABILITIES = nextPlayId();
|
public static final int PLAYER_ABILITIES = nextPlayId();
|
||||||
public static final int PLAYER_CHAT_HEADER = nextPlayId();
|
|
||||||
public static final int PLAYER_CHAT = nextPlayId();
|
public static final int PLAYER_CHAT = nextPlayId();
|
||||||
public static final int END_COMBAT_EVENT = nextPlayId();
|
public static final int END_COMBAT_EVENT = nextPlayId();
|
||||||
public static final int ENTER_COMBAT_EVENT = nextPlayId();
|
public static final int ENTER_COMBAT_EVENT = nextPlayId();
|
||||||
public static final int DEATH_COMBAT_EVENT = nextPlayId();
|
public static final int DEATH_COMBAT_EVENT = nextPlayId();
|
||||||
public static final int PLAYER_INFO = nextPlayId();
|
public static final int PLAYER_INFO_REMOVE = nextPlayId();
|
||||||
|
public static final int PLAYER_INFO_UPDATE = nextPlayId();
|
||||||
public static final int FACE_PLAYER = nextPlayId();
|
public static final int FACE_PLAYER = nextPlayId();
|
||||||
public static final int PLAYER_POSITION_AND_LOOK = nextPlayId();
|
public static final int PLAYER_POSITION_AND_LOOK = nextPlayId();
|
||||||
public static final int UNLOCK_RECIPES = nextPlayId();
|
public static final int UNLOCK_RECIPES = nextPlayId();
|
||||||
|
@ -89,7 +88,6 @@ public final class ServerPacketIdentifier {
|
||||||
public static final int UPDATE_VIEW_POSITION = nextPlayId();
|
public static final int UPDATE_VIEW_POSITION = nextPlayId();
|
||||||
public static final int UPDATE_VIEW_DISTANCE = nextPlayId(); // Not used by the dedicated server
|
public static final int UPDATE_VIEW_DISTANCE = nextPlayId(); // Not used by the dedicated server
|
||||||
public static final int SPAWN_POSITION = nextPlayId();
|
public static final int SPAWN_POSITION = nextPlayId();
|
||||||
public static final int SET_DISPLAY_CHAT_PREVIEW = nextPlayId();
|
|
||||||
public static final int DISPLAY_SCOREBOARD = nextPlayId();
|
public static final int DISPLAY_SCOREBOARD = nextPlayId();
|
||||||
public static final int ENTITY_METADATA = nextPlayId();
|
public static final int ENTITY_METADATA = nextPlayId();
|
||||||
public static final int ATTACH_ENTITY = nextPlayId();
|
public static final int ATTACH_ENTITY = nextPlayId();
|
||||||
|
@ -116,6 +114,7 @@ public final class ServerPacketIdentifier {
|
||||||
public static final int ENTITY_TELEPORT = nextPlayId();
|
public static final int ENTITY_TELEPORT = nextPlayId();
|
||||||
public static final int ADVANCEMENTS = nextPlayId();
|
public static final int ADVANCEMENTS = nextPlayId();
|
||||||
public static final int ENTITY_PROPERTIES = nextPlayId();
|
public static final int ENTITY_PROPERTIES = nextPlayId();
|
||||||
|
public static final int UPDATE_ENABLED_FEATURES = nextPlayId();
|
||||||
public static final int ENTITY_EFFECT = nextPlayId();
|
public static final int ENTITY_EFFECT = nextPlayId();
|
||||||
public static final int DECLARE_RECIPES = nextPlayId();
|
public static final int DECLARE_RECIPES = nextPlayId();
|
||||||
public static final int TAGS = nextPlayId();
|
public static final int TAGS = nextPlayId();
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
|
||||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
|
||||||
|
|
||||||
public record ChatPreviewPacket(int queryId, @Nullable Component preview) implements ComponentHoldingServerPacket {
|
|
||||||
public ChatPreviewPacket(@NotNull NetworkBuffer reader) {
|
|
||||||
this(reader.read(INT), reader.readOptional(COMPONENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(INT, queryId);
|
|
||||||
writer.writeOptional(COMPONENT, preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return ServerPacketIdentifier.CHAT_PREVIEW;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<Component> components() {
|
|
||||||
return List.of(preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
|
||||||
return new ChatPreviewPacket(queryId, operator.apply(preview));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,23 +2,86 @@ package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
import net.kyori.adventure.sound.Sound;
|
import net.kyori.adventure.sound.Sound;
|
||||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
|
import net.minestom.server.sound.SoundEvent;
|
||||||
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record EntitySoundEffectPacket(int soundId, Sound.Source source, int entityId,
|
public record EntitySoundEffectPacket(
|
||||||
float volume, float pitch, long seed) implements ServerPacket {
|
// only one of soundEvent and soundName may be present
|
||||||
|
@Nullable SoundEvent soundEvent,
|
||||||
|
@Nullable String soundName,
|
||||||
|
@Nullable Float range, // Only allowed with soundName
|
||||||
|
@NotNull Sound.Source source,
|
||||||
|
int entityId,
|
||||||
|
float volume,
|
||||||
|
float pitch,
|
||||||
|
long seed
|
||||||
|
) implements ServerPacket {
|
||||||
|
|
||||||
|
public EntitySoundEffectPacket {
|
||||||
|
Check.argCondition(soundEvent == null && soundName == null, "soundEvent and soundName cannot both be null");
|
||||||
|
Check.argCondition(soundEvent != null && soundName != null, "soundEvent and soundName cannot both be present");
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntitySoundEffectPacket(@NotNull SoundEvent soundEvent, @Nullable Float range, @NotNull Sound.Source source,
|
||||||
|
int entityId, float volume, float pitch, long seed) {
|
||||||
|
this(soundEvent, null, range, source, entityId, volume, pitch, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntitySoundEffectPacket(@NotNull String soundName, @Nullable Float range, @NotNull Sound.Source source,
|
||||||
|
int entityId, float volume, float pitch, long seed) {
|
||||||
|
this(null, soundName, range, source, entityId, volume, pitch, seed);
|
||||||
|
}
|
||||||
|
|
||||||
public EntitySoundEffectPacket(@NotNull NetworkBuffer reader) {
|
public EntitySoundEffectPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(VAR_INT), Sound.Source.values()[reader.read(VAR_INT)], reader.read(VAR_INT),
|
this(fromReader(reader));
|
||||||
reader.read(FLOAT), reader.read(FLOAT), reader.read(LONG));
|
}
|
||||||
|
|
||||||
|
private EntitySoundEffectPacket(@NotNull EntitySoundEffectPacket packet) {
|
||||||
|
this(packet.soundEvent, packet.soundName, packet.range, packet.source, packet.entityId, packet.volume, packet.pitch, packet.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull EntitySoundEffectPacket fromReader(@NotNull NetworkBuffer reader) {
|
||||||
|
int soundId = reader.read(VAR_INT);
|
||||||
|
SoundEvent soundEvent;
|
||||||
|
String soundName;
|
||||||
|
Float range = null;
|
||||||
|
if (soundId == 0) {
|
||||||
|
soundEvent = null;
|
||||||
|
soundName = reader.read(STRING);
|
||||||
|
range = reader.readOptional(FLOAT);
|
||||||
|
} else {
|
||||||
|
soundEvent = SoundEvent.fromId(soundId - 1);
|
||||||
|
soundName = null;
|
||||||
|
}
|
||||||
|
return new EntitySoundEffectPacket(
|
||||||
|
soundEvent,
|
||||||
|
soundName,
|
||||||
|
range,
|
||||||
|
reader.readEnum(Sound.Source.class),
|
||||||
|
reader.read(VAR_INT),
|
||||||
|
reader.read(FLOAT),
|
||||||
|
reader.read(FLOAT),
|
||||||
|
reader.read(LONG)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(VAR_INT, soundId);
|
if (soundEvent != null) {
|
||||||
|
writer.write(VAR_INT, soundEvent.id() + 1);
|
||||||
|
} else {
|
||||||
|
writer.write(VAR_INT, 0);
|
||||||
|
writer.write(STRING, soundName);
|
||||||
|
writer.writeOptional(FLOAT, null);
|
||||||
|
}
|
||||||
writer.write(VAR_INT, AdventurePacketConvertor.getSoundSourceValue(source));
|
writer.write(VAR_INT, AdventurePacketConvertor.getSoundSourceValue(source));
|
||||||
writer.write(VAR_INT, entityId);
|
writer.write(VAR_INT, entityId);
|
||||||
writer.write(FLOAT, volume);
|
writer.write(FLOAT, volume);
|
||||||
|
|
|
@ -7,19 +7,19 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record ExplosionPacket(float x, float y, float z, float radius, byte @NotNull [] records,
|
public record ExplosionPacket(double x, double y, double z, float radius, byte @NotNull [] records,
|
||||||
float playerMotionX, float playerMotionY, float playerMotionZ) implements ServerPacket {
|
float playerMotionX, float playerMotionY, float playerMotionZ) implements ServerPacket {
|
||||||
public ExplosionPacket(@NotNull NetworkBuffer reader) {
|
public ExplosionPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(FLOAT), reader.read(FLOAT), reader.read(FLOAT),
|
this(reader.read(DOUBLE), reader.read(DOUBLE), reader.read(DOUBLE),
|
||||||
reader.read(FLOAT), reader.readBytes(reader.read(VAR_INT) * 3),
|
reader.read(FLOAT), reader.readBytes(reader.read(VAR_INT) * 3),
|
||||||
reader.read(FLOAT), reader.read(FLOAT), reader.read(FLOAT));
|
reader.read(FLOAT), reader.read(FLOAT), reader.read(FLOAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(FLOAT, x);
|
writer.write(DOUBLE, x);
|
||||||
writer.write(FLOAT, y);
|
writer.write(DOUBLE, y);
|
||||||
writer.write(FLOAT, z);
|
writer.write(DOUBLE, z);
|
||||||
writer.write(FLOAT, radius);
|
writer.write(FLOAT, radius);
|
||||||
writer.write(VAR_INT, records.length / 3); // each record is 3 bytes long
|
writer.write(VAR_INT, records.length / 3); // each record is 3 bytes long
|
||||||
writer.write(RAW_BYTES, records);
|
writer.write(RAW_BYTES, records);
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
|
||||||
|
|
||||||
import net.kyori.adventure.sound.Sound.Source;
|
|
||||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
|
||||||
|
|
||||||
public record NamedSoundEffectPacket(String soundName, Source source, int x, int y, int z,
|
|
||||||
float volume, float pitch, long seed) implements ServerPacket {
|
|
||||||
public NamedSoundEffectPacket(@NotNull NetworkBuffer reader) {
|
|
||||||
this(reader.read(STRING), Source.values()[reader.read(VAR_INT)],
|
|
||||||
reader.read(INT) / 8, reader.read(INT) / 8, reader.read(INT) / 8,
|
|
||||||
reader.read(FLOAT), reader.read(FLOAT), reader.read(LONG));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(STRING, soundName);
|
|
||||||
writer.write(VAR_INT, AdventurePacketConvertor.getSoundSourceValue(source));
|
|
||||||
writer.write(INT, x * 8);
|
|
||||||
writer.write(INT, y * 8);
|
|
||||||
writer.write(INT, z * 8);
|
|
||||||
writer.write(FLOAT, volume);
|
|
||||||
writer.write(FLOAT, pitch);
|
|
||||||
writer.write(LONG, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return ServerPacketIdentifier.NAMED_SOUND_EFFECT;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
|
||||||
|
|
||||||
import net.minestom.server.crypto.MessageSignature;
|
|
||||||
import net.minestom.server.crypto.SignedMessageHeader;
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.BYTE_ARRAY;
|
|
||||||
|
|
||||||
public record PlayerChatHeaderPacket(@NotNull SignedMessageHeader messageHeader, @NotNull MessageSignature signature,
|
|
||||||
byte[] bodyDigest) implements ServerPacket {
|
|
||||||
public PlayerChatHeaderPacket(@NotNull NetworkBuffer reader) {
|
|
||||||
this(new SignedMessageHeader(reader), new MessageSignature(reader), reader.read(BYTE_ARRAY));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(messageHeader);
|
|
||||||
writer.write(signature);
|
|
||||||
writer.write(BYTE_ARRAY, bodyDigest);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return ServerPacketIdentifier.PLAYER_CHAT_HEADER;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,8 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.crypto.MessageSignature;
|
import net.minestom.server.crypto.FilterMask;
|
||||||
|
import net.minestom.server.crypto.SignedMessageBody;
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
|
@ -9,6 +10,7 @@ import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -19,26 +21,30 @@ import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
/**
|
/**
|
||||||
* Represents an outgoing chat message packet.
|
* Represents an outgoing chat message packet.
|
||||||
*/
|
*/
|
||||||
public record PlayerChatMessagePacket(@NotNull Component signedContent, @Nullable Component unsignedContent,
|
public record PlayerChatMessagePacket(UUID sender, int index, byte @Nullable [] signature,
|
||||||
int type, @NotNull UUID uuid,
|
SignedMessageBody.@NotNull Packed messageBody,
|
||||||
@NotNull Component displayName, @Nullable Component teamDisplayName,
|
@Nullable Component unsignedContent, FilterMask filterMask,
|
||||||
@NotNull MessageSignature signature) implements ComponentHoldingServerPacket {
|
int msgTypeId, Component msgTypeName,
|
||||||
|
@Nullable Component msgTypeTarget) implements ComponentHoldingServerPacket {
|
||||||
public PlayerChatMessagePacket(@NotNull NetworkBuffer reader) {
|
public PlayerChatMessagePacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.read(COMPONENT), reader.readOptional(COMPONENT),
|
this(reader.read(UUID), reader.read(VAR_INT), reader.readOptional(r -> r.readBytes(256)),
|
||||||
reader.read(VAR_INT), reader.read(NetworkBuffer.UUID),
|
new SignedMessageBody.Packed(reader),
|
||||||
reader.read(COMPONENT), reader.readOptional(COMPONENT),
|
reader.readOptional(COMPONENT), new FilterMask(reader),
|
||||||
new MessageSignature(reader));
|
reader.read(VAR_INT), reader.read(COMPONENT),
|
||||||
|
reader.readOptional(COMPONENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(COMPONENT, signedContent);
|
writer.write(UUID, sender);
|
||||||
|
writer.write(VAR_INT, index);
|
||||||
|
writer.writeOptional(RAW_BYTES, signature);
|
||||||
|
writer.write(messageBody);
|
||||||
writer.writeOptional(COMPONENT, unsignedContent);
|
writer.writeOptional(COMPONENT, unsignedContent);
|
||||||
writer.write(VAR_INT, type);
|
writer.write(filterMask);
|
||||||
writer.write(UUID, uuid);
|
writer.write(VAR_INT, msgTypeId);
|
||||||
writer.write(COMPONENT, displayName);
|
writer.write(COMPONENT, msgTypeName);
|
||||||
writer.writeOptional(COMPONENT, teamDisplayName);
|
writer.writeOptional(COMPONENT, msgTypeTarget);
|
||||||
writer.write(signature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,12 +54,19 @@ public record PlayerChatMessagePacket(@NotNull Component signedContent, @Nullabl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Collection<Component> components() {
|
public @NotNull Collection<Component> components() {
|
||||||
return List.of(signedContent);
|
final ArrayList<Component> list = new ArrayList<>();
|
||||||
|
list.add(msgTypeName);
|
||||||
|
if (unsignedContent != null) list.add(unsignedContent);
|
||||||
|
if (msgTypeTarget != null) list.add(msgTypeTarget);
|
||||||
|
return List.copyOf(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||||
return new PlayerChatMessagePacket(signedContent, unsignedContent, type,
|
return new PlayerChatMessagePacket(sender, index, signature,
|
||||||
uuid, displayName, teamDisplayName, signature);
|
messageBody,
|
||||||
|
operator.apply(unsignedContent), filterMask,
|
||||||
|
msgTypeId, operator.apply(msgTypeName),
|
||||||
|
operator.apply(msgTypeTarget));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,242 +0,0 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.minestom.server.adventure.ComponentHolder;
|
|
||||||
import net.minestom.server.crypto.PlayerPublicKey;
|
|
||||||
import net.minestom.server.entity.GameMode;
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
|
||||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
|
||||||
|
|
||||||
public record PlayerInfoPacket(@NotNull Action action,
|
|
||||||
@NotNull List<Entry> entries) implements ComponentHoldingServerPacket {
|
|
||||||
public PlayerInfoPacket {
|
|
||||||
entries = List.copyOf(entries);
|
|
||||||
for (Entry entry : entries) {
|
|
||||||
if (!entry.getClass().equals(action.getClazz()))
|
|
||||||
throw new IllegalArgumentException("Invalid entry class for action " + action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayerInfoPacket(@NotNull Action action, @NotNull Entry entry) {
|
|
||||||
this(action, List.of(entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayerInfoPacket(@NotNull NetworkBuffer reader) {
|
|
||||||
this(read(reader));
|
|
||||||
}
|
|
||||||
|
|
||||||
private PlayerInfoPacket(PlayerInfoPacket packet) {
|
|
||||||
this(packet.action, packet.entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PlayerInfoPacket read(@NotNull NetworkBuffer reader) {
|
|
||||||
var action = Action.values()[reader.read(VAR_INT)];
|
|
||||||
final int playerInfoCount = reader.read(VAR_INT);
|
|
||||||
List<Entry> entries = new ArrayList<>(playerInfoCount);
|
|
||||||
for (int i = 0; i < playerInfoCount; i++) {
|
|
||||||
final UUID uuid = reader.read(UUID);
|
|
||||||
entries.add(switch (action) {
|
|
||||||
case ADD_PLAYER -> new AddPlayer(uuid, reader);
|
|
||||||
case UPDATE_GAMEMODE -> new UpdateGameMode(uuid, reader);
|
|
||||||
case UPDATE_LATENCY -> new UpdateLatency(uuid, reader);
|
|
||||||
case UPDATE_DISPLAY_NAME -> new UpdateDisplayName(uuid, reader);
|
|
||||||
case REMOVE_PLAYER -> new RemovePlayer(uuid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return new PlayerInfoPacket(action, entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(VAR_INT, action.ordinal());
|
|
||||||
writer.writeCollection(entries, (w, entry) -> {
|
|
||||||
w.write(UUID, entry.uuid());
|
|
||||||
entry.write(w);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return ServerPacketIdentifier.PLAYER_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<Component> components() {
|
|
||||||
switch (this.action) {
|
|
||||||
case ADD_PLAYER, UPDATE_DISPLAY_NAME -> {
|
|
||||||
List<Component> components = new ArrayList<>();
|
|
||||||
for (Entry entry : entries) {
|
|
||||||
if (entry instanceof ComponentHolder) {
|
|
||||||
components.addAll(((ComponentHolder<? extends Entry>) entry).components());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return components;
|
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
|
||||||
return switch (action) {
|
|
||||||
case ADD_PLAYER, UPDATE_DISPLAY_NAME -> {
|
|
||||||
List<Entry> entries = new ArrayList<>(this.entries.size());
|
|
||||||
for (Entry entry : this.entries) {
|
|
||||||
if (entry instanceof ComponentHolder) {
|
|
||||||
entries.add(((ComponentHolder<? extends Entry>) entry).copyWithOperator(operator));
|
|
||||||
} else {
|
|
||||||
entries.add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yield new PlayerInfoPacket(action, entries);
|
|
||||||
}
|
|
||||||
default -> this;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Action {
|
|
||||||
ADD_PLAYER(AddPlayer.class),
|
|
||||||
UPDATE_GAMEMODE(UpdateGameMode.class),
|
|
||||||
UPDATE_LATENCY(UpdateLatency.class),
|
|
||||||
UPDATE_DISPLAY_NAME(UpdateDisplayName.class),
|
|
||||||
REMOVE_PLAYER(RemovePlayer.class);
|
|
||||||
|
|
||||||
private final Class<? extends Entry> clazz;
|
|
||||||
|
|
||||||
Action(Class<? extends Entry> clazz) {
|
|
||||||
this.clazz = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Class<? extends Entry> getClazz() {
|
|
||||||
return clazz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed interface Entry extends NetworkBuffer.Writer
|
|
||||||
permits AddPlayer, UpdateGameMode, UpdateLatency, UpdateDisplayName, RemovePlayer {
|
|
||||||
UUID uuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
public record AddPlayer(UUID uuid, String name, List<Property> properties, GameMode gameMode, int ping,
|
|
||||||
@Nullable Component displayName,
|
|
||||||
@Nullable PlayerPublicKey playerPublicKey) implements Entry, ComponentHolder<AddPlayer> {
|
|
||||||
public AddPlayer {
|
|
||||||
properties = List.copyOf(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddPlayer(UUID uuid, NetworkBuffer reader) {
|
|
||||||
this(uuid, reader.read(STRING),
|
|
||||||
reader.readCollection(Property::new),
|
|
||||||
GameMode.values()[reader.read(VAR_INT)], reader.read(VAR_INT),
|
|
||||||
reader.read(BOOLEAN) ? reader.read(COMPONENT) : null,
|
|
||||||
reader.read(BOOLEAN) ? new PlayerPublicKey(reader) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(STRING, name);
|
|
||||||
writer.writeCollection(properties);
|
|
||||||
writer.write(VAR_INT, (int) gameMode.id());
|
|
||||||
writer.write(VAR_INT, ping);
|
|
||||||
writer.writeOptional(COMPONENT, displayName);
|
|
||||||
writer.writeOptional(playerPublicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<Component> components() {
|
|
||||||
return displayName != null ? List.of(displayName) : List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull AddPlayer copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
|
||||||
return displayName != null ?
|
|
||||||
new AddPlayer(uuid, name, properties, gameMode, ping, operator.apply(displayName), playerPublicKey) : this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public record Property(@NotNull String name, @NotNull String value,
|
|
||||||
@Nullable String signature) implements NetworkBuffer.Writer {
|
|
||||||
public Property(String name, String value) {
|
|
||||||
this(name, value, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Property(@NotNull NetworkBuffer reader) {
|
|
||||||
this(reader.read(STRING), reader.read(STRING),
|
|
||||||
reader.read(BOOLEAN) ? reader.read(STRING) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(STRING, name);
|
|
||||||
writer.write(STRING, value);
|
|
||||||
writer.write(BOOLEAN, signature != null);
|
|
||||||
if (signature != null) writer.write(STRING, signature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record UpdateGameMode(UUID uuid, GameMode gameMode) implements Entry {
|
|
||||||
public UpdateGameMode(UUID uuid, NetworkBuffer reader) {
|
|
||||||
this(uuid, GameMode.fromId(reader.read(VAR_INT).byteValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(VAR_INT, (int) gameMode.id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record UpdateLatency(UUID uuid, int ping) implements Entry {
|
|
||||||
public UpdateLatency(UUID uuid, NetworkBuffer reader) {
|
|
||||||
this(uuid, reader.read(VAR_INT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(VAR_INT, ping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record UpdateDisplayName(@NotNull UUID uuid,
|
|
||||||
@Nullable Component displayName) implements Entry, ComponentHolder<UpdateDisplayName> {
|
|
||||||
public UpdateDisplayName(UUID uuid, NetworkBuffer reader) {
|
|
||||||
this(uuid, reader.read(BOOLEAN) ? reader.read(COMPONENT) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(BOOLEAN, displayName != null);
|
|
||||||
if (displayName != null) writer.write(COMPONENT, displayName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Collection<Component> components() {
|
|
||||||
return displayName != null ? List.of(displayName) : List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull UpdateDisplayName copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
|
||||||
return displayName != null ? new UpdateDisplayName(uuid, operator.apply(displayName)) : this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record RemovePlayer(@NotNull UUID uuid) implements Entry {
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record PlayerInfoRemovePacket(@NotNull List<@NotNull UUID> uuids) implements ServerPacket {
|
||||||
|
public PlayerInfoRemovePacket(@NotNull UUID uuid) {
|
||||||
|
this(List.of(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerInfoRemovePacket {
|
||||||
|
uuids = List.copyOf(uuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerInfoRemovePacket(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.readCollection(NetworkBuffer.UUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.writeCollection(NetworkBuffer.UUID, uuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return ServerPacketIdentifier.PLAYER_INFO_REMOVE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.crypto.ChatSession;
|
||||||
|
import net.minestom.server.entity.GameMode;
|
||||||
|
import net.minestom.server.network.NetworkBuffer;
|
||||||
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
|
public final class PlayerInfoUpdatePacket implements ServerPacket {
|
||||||
|
private final @NotNull EnumSet<@NotNull Action> actions;
|
||||||
|
private final @NotNull List<@NotNull Entry> entries;
|
||||||
|
|
||||||
|
public PlayerInfoUpdatePacket(@NotNull EnumSet<@NotNull Action> actions, @NotNull List<@NotNull Entry> entries) {
|
||||||
|
this.actions = EnumSet.copyOf(actions);
|
||||||
|
this.entries = List.copyOf(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerInfoUpdatePacket(@NotNull Action action, @NotNull Entry entry) {
|
||||||
|
this.actions = EnumSet.of(action);
|
||||||
|
this.entries = List.of(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerInfoUpdatePacket(@NotNull NetworkBuffer reader) {
|
||||||
|
this.actions = reader.readEnumSet(Action.class);
|
||||||
|
this.entries = reader.readCollection(buffer -> {
|
||||||
|
UUID uuid = buffer.read(NetworkBuffer.UUID);
|
||||||
|
String username = "";
|
||||||
|
List<Property> properties = List.of();
|
||||||
|
boolean listed = false;
|
||||||
|
int latency = 0;
|
||||||
|
GameMode gameMode = GameMode.SURVIVAL;
|
||||||
|
Component displayName = null;
|
||||||
|
ChatSession chatSession = null;
|
||||||
|
for (Action action : actions) {
|
||||||
|
switch (action) {
|
||||||
|
case ADD_PLAYER -> {
|
||||||
|
username = reader.read(STRING);
|
||||||
|
properties = reader.readCollection(Property::new);
|
||||||
|
}
|
||||||
|
case INITIALIZE_CHAT -> chatSession = new ChatSession(reader);
|
||||||
|
case UPDATE_GAME_MODE -> gameMode = reader.readEnum(GameMode.class);
|
||||||
|
case UPDATE_LISTED -> listed = reader.read(BOOLEAN);
|
||||||
|
case UPDATE_LATENCY -> latency = reader.read(VAR_INT);
|
||||||
|
case UPDATE_DISPLAY_NAME -> displayName = reader.read(COMPONENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Entry(uuid, username, properties, listed, latency, gameMode, displayName, chatSession);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.writeEnumSet(actions, Action.class);
|
||||||
|
writer.writeCollection(entries, (buffer, entry) -> {
|
||||||
|
buffer.write(NetworkBuffer.UUID, entry.uuid);
|
||||||
|
for (Action action : actions) {
|
||||||
|
action.writer.write(buffer, entry);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return ServerPacketIdentifier.PLAYER_INFO_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull EnumSet<Action> actions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull List<Entry> entries() {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
PlayerInfoUpdatePacket that = (PlayerInfoUpdatePacket) o;
|
||||||
|
return actions.equals(that.actions) && entries.equals(that.entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(actions, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PlayerInfoUpdatePacket{" +
|
||||||
|
"actions=" + actions +
|
||||||
|
", entries=" + entries +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Entry(UUID uuid, String username, List<Property> properties,
|
||||||
|
boolean listed, int latency, GameMode gameMode,
|
||||||
|
@Nullable Component displayName, @Nullable ChatSession chatSession) {
|
||||||
|
public Entry {
|
||||||
|
properties = List.copyOf(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Property(@NotNull String name, @NotNull String value,
|
||||||
|
@Nullable String signature) implements NetworkBuffer.Writer {
|
||||||
|
public Property(@NotNull String name, @NotNull String value) {
|
||||||
|
this(name, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property(@NotNull NetworkBuffer reader) {
|
||||||
|
this(reader.read(STRING), reader.read(STRING),
|
||||||
|
reader.readOptional(STRING));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
|
writer.write(STRING, name);
|
||||||
|
writer.write(STRING, value);
|
||||||
|
writer.writeOptional(STRING, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
ADD_PLAYER((writer, entry) -> {
|
||||||
|
writer.write(STRING, entry.username);
|
||||||
|
writer.writeCollection(entry.properties);
|
||||||
|
}),
|
||||||
|
INITIALIZE_CHAT((writer, entry) -> writer.writeOptional(entry.chatSession)),
|
||||||
|
UPDATE_GAME_MODE((writer, entry) -> writer.write(VAR_INT, entry.gameMode.ordinal())),
|
||||||
|
UPDATE_LISTED((writer, entry) -> writer.write(BOOLEAN, entry.listed)),
|
||||||
|
UPDATE_LATENCY((writer, entry) -> writer.write(VAR_INT, entry.latency)),
|
||||||
|
UPDATE_DISPLAY_NAME((writer, entry) -> writer.writeOptional(COMPONENT, entry.displayName));
|
||||||
|
|
||||||
|
final Writer writer;
|
||||||
|
|
||||||
|
Action(Writer writer) {
|
||||||
|
this.writer = writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Writer {
|
||||||
|
void write(NetworkBuffer writer, Entry entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,17 +10,16 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record ServerDataPacket(@Nullable Component motd, @Nullable String iconBase64,
|
public record ServerDataPacket(@Nullable Component motd, @Nullable String iconBase64,
|
||||||
boolean previewsChat, boolean enforcesSecureChat) implements ServerPacket {
|
boolean enforcesSecureChat) implements ServerPacket {
|
||||||
public ServerDataPacket(@NotNull NetworkBuffer reader) {
|
public ServerDataPacket(@NotNull NetworkBuffer reader) {
|
||||||
this(reader.readOptional(COMPONENT), reader.readOptional(STRING),
|
this(reader.readOptional(COMPONENT), reader.readOptional(STRING),
|
||||||
reader.read(BOOLEAN), reader.read(BOOLEAN));
|
reader.read(BOOLEAN));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.writeOptional(COMPONENT, this.motd);
|
writer.writeOptional(COMPONENT, this.motd);
|
||||||
writer.writeOptional(STRING, this.iconBase64);
|
writer.writeOptional(STRING, this.iconBase64);
|
||||||
writer.write(BOOLEAN, previewsChat);
|
|
||||||
writer.write(BOOLEAN, enforcesSecureChat);
|
writer.write(BOOLEAN, enforcesSecureChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package net.minestom.server.network.packet.server.play;
|
|
||||||
|
|
||||||
import net.minestom.server.network.NetworkBuffer;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.BOOLEAN;
|
|
||||||
|
|
||||||
public record SetChatPreviewPacket(boolean enable) implements ServerPacket {
|
|
||||||
public SetChatPreviewPacket(@NotNull NetworkBuffer reader) {
|
|
||||||
this(reader.read(BOOLEAN));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
|
||||||
writer.write(BOOLEAN, enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return ServerPacketIdentifier.SET_DISPLAY_CHAT_PREVIEW;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,27 +8,78 @@ import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import net.minestom.server.sound.SoundEvent;
|
import net.minestom.server.sound.SoundEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import static net.minestom.server.network.NetworkBuffer.*;
|
import static net.minestom.server.network.NetworkBuffer.*;
|
||||||
|
|
||||||
public record SoundEffectPacket(int soundId, @NotNull Source source,
|
public record SoundEffectPacket(
|
||||||
int x, int y, int z,
|
// only one of soundEvent and soundName may be present
|
||||||
float volume, float pitch, long seed) implements ServerPacket {
|
@Nullable SoundEvent soundEvent,
|
||||||
public SoundEffectPacket(@NotNull NetworkBuffer reader) {
|
@Nullable String soundName,
|
||||||
this(reader.read(VAR_INT), reader.readEnum(Source.class),
|
@Nullable Float range, // Only allowed with soundName
|
||||||
reader.read(INT) * 8, reader.read(INT) * 8, reader.read(INT) * 8,
|
@NotNull Source source,
|
||||||
reader.read(FLOAT), reader.read(FLOAT), reader.read(LONG));
|
int x,
|
||||||
|
int y,
|
||||||
|
int z,
|
||||||
|
float volume,
|
||||||
|
float pitch,
|
||||||
|
long seed
|
||||||
|
) implements ServerPacket {
|
||||||
|
private static @NotNull SoundEffectPacket fromReader(@NotNull NetworkBuffer reader) {
|
||||||
|
int soundId = reader.read(VAR_INT);
|
||||||
|
SoundEvent soundEvent;
|
||||||
|
String soundName;
|
||||||
|
Float range = null;
|
||||||
|
if (soundId == 0) {
|
||||||
|
soundEvent = null;
|
||||||
|
soundName = reader.read(STRING);
|
||||||
|
range = reader.readOptional(FLOAT);
|
||||||
|
} else {
|
||||||
|
soundEvent = SoundEvent.fromId(soundId - 1);
|
||||||
|
soundName = null;
|
||||||
|
}
|
||||||
|
return new SoundEffectPacket(
|
||||||
|
soundEvent,
|
||||||
|
soundName,
|
||||||
|
range,
|
||||||
|
reader.readEnum(Source.class),
|
||||||
|
reader.read(INT) * 8,
|
||||||
|
reader.read(INT) * 8,
|
||||||
|
reader.read(INT) * 8,
|
||||||
|
reader.read(FLOAT),
|
||||||
|
reader.read(FLOAT),
|
||||||
|
reader.read(LONG)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SoundEffectPacket(@NotNull SoundEvent sound, @NotNull Source source,
|
public SoundEffectPacket(@NotNull SoundEvent soundEvent, @Nullable Float range, @NotNull Source source,
|
||||||
@NotNull Point position, float volume, float pitch) {
|
@NotNull Point position, float volume, float pitch, long seed) {
|
||||||
this(sound.id(), source, (int) position.x(), (int) position.y(), (int) position.z(),
|
this(soundEvent, null, range, source, position.blockX(), position.blockY(), position.blockZ(), volume, pitch, seed);
|
||||||
volume, pitch, 0);
|
}
|
||||||
|
|
||||||
|
public SoundEffectPacket(@NotNull String soundName, @Nullable Float range, @NotNull Source source,
|
||||||
|
@NotNull Point position, float volume, float pitch, long seed) {
|
||||||
|
this(null, soundName, range, source, position.blockX(), position.blockY(), position.blockZ(), volume, pitch, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundEffectPacket(@NotNull NetworkBuffer reader) {
|
||||||
|
this(fromReader(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SoundEffectPacket(@NotNull SoundEffectPacket packet) {
|
||||||
|
this(packet.soundEvent, packet.soundName, packet.range, packet.source,
|
||||||
|
packet.x, packet.y, packet.z, packet.volume, packet.pitch, packet.seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(@NotNull NetworkBuffer writer) {
|
public void write(@NotNull NetworkBuffer writer) {
|
||||||
writer.write(VAR_INT, soundId);
|
if (soundEvent != null) {
|
||||||
|
writer.write(VAR_INT, soundEvent.id() + 1);
|
||||||
|
} else {
|
||||||
|
writer.write(VAR_INT, 0);
|
||||||
|
writer.write(STRING, soundName);
|
||||||
|
writer.writeOptional(FLOAT, range);
|
||||||
|
}
|
||||||
writer.write(VAR_INT, AdventurePacketConvertor.getSoundSourceValue(source));
|
writer.write(VAR_INT, AdventurePacketConvertor.getSoundSourceValue(source));
|
||||||
writer.write(INT, x * 8);
|
writer.write(INT, x * 8);
|
||||||
writer.write(INT, y * 8);
|
writer.write(INT, y * 8);
|
||||||
|
@ -42,4 +93,5 @@ public record SoundEffectPacket(int soundId, @NotNull Source source,
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return ServerPacketIdentifier.SOUND_EFFECT;
|
return ServerPacketIdentifier.SOUND_EFFECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,12 @@ import com.google.gson.JsonObject;
|
||||||
import net.kyori.adventure.bossbar.BossBar;
|
import net.kyori.adventure.bossbar.BossBar;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.crypto.ChatSession;
|
||||||
|
import net.minestom.server.crypto.PlayerPublicKey;
|
||||||
import net.minestom.server.entity.EquipmentSlot;
|
import net.minestom.server.entity.EquipmentSlot;
|
||||||
import net.minestom.server.entity.GameMode;
|
import net.minestom.server.entity.GameMode;
|
||||||
import net.minestom.server.entity.Metadata;
|
import net.minestom.server.entity.Metadata;
|
||||||
|
import net.minestom.server.entity.PlayerSkin;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
import net.minestom.server.network.packet.client.ClientPacket;
|
import net.minestom.server.network.packet.client.ClientPacket;
|
||||||
|
@ -19,11 +22,18 @@ import net.minestom.server.network.packet.server.login.SetCompressionPacket;
|
||||||
import net.minestom.server.network.packet.server.play.*;
|
import net.minestom.server.network.packet.server.play.*;
|
||||||
import net.minestom.server.network.packet.server.play.DeclareRecipesPacket.Ingredient;
|
import net.minestom.server.network.packet.server.play.DeclareRecipesPacket.Ingredient;
|
||||||
import net.minestom.server.network.packet.server.status.PongPacket;
|
import net.minestom.server.network.packet.server.status.PongPacket;
|
||||||
|
import net.minestom.server.utils.crypto.KeyUtils;
|
||||||
|
import org.apache.commons.net.util.Base64;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
import org.jglrxavpok.hephaistos.nbt.NBT;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -110,18 +120,20 @@ public class PacketWriteReadTest {
|
||||||
SERVER_PACKETS.add(new EntityPropertiesPacket(5, List.of()));
|
SERVER_PACKETS.add(new EntityPropertiesPacket(5, List.of()));
|
||||||
SERVER_PACKETS.add(new EntityRotationPacket(5, 45f, 45f, false));
|
SERVER_PACKETS.add(new EntityRotationPacket(5, 45f, 45f, false));
|
||||||
|
|
||||||
SERVER_PACKETS.add(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_DISPLAY_NAME,
|
final PlayerSkin skin = new PlayerSkin("hh", "hh");
|
||||||
new PlayerInfoPacket.UpdateDisplayName(UUID.randomUUID(), COMPONENT)));
|
List<PlayerInfoUpdatePacket.Property> prop = List.of(new PlayerInfoUpdatePacket.Property("textures", skin.textures(), skin.signature()));
|
||||||
SERVER_PACKETS.add(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_DISPLAY_NAME,
|
|
||||||
new PlayerInfoPacket.UpdateDisplayName(UUID.randomUUID(), (Component) null)));
|
SERVER_PACKETS.add(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.ADD_PLAYER,
|
||||||
SERVER_PACKETS.add(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_GAMEMODE,
|
new PlayerInfoUpdatePacket.Entry(UUID.randomUUID(), "TheMode911", prop, false, 0, GameMode.SURVIVAL, null, null)));
|
||||||
new PlayerInfoPacket.UpdateGameMode(UUID.randomUUID(), GameMode.CREATIVE)));
|
// SERVER_PACKETS.add(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME,
|
||||||
SERVER_PACKETS.add(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_LATENCY,
|
// new PlayerInfoUpdatePacket.Entry(UUID.randomUUID(), "", List.of(), false, 0, GameMode.SURVIVAL, Component.text("NotTheMode911"), null)));
|
||||||
new PlayerInfoPacket.UpdateLatency(UUID.randomUUID(), 5)));
|
SERVER_PACKETS.add(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE,
|
||||||
SERVER_PACKETS.add(new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER,
|
new PlayerInfoUpdatePacket.Entry(UUID.randomUUID(), "", List.of(), false, 0, GameMode.CREATIVE, null, null)));
|
||||||
new PlayerInfoPacket.AddPlayer(UUID.randomUUID(), "TheMode911",
|
SERVER_PACKETS.add(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_LATENCY,
|
||||||
List.of(new PlayerInfoPacket.AddPlayer.Property("name", "value")), GameMode.CREATIVE, 5, COMPONENT, null)));
|
new PlayerInfoUpdatePacket.Entry(UUID.randomUUID(), "", List.of(), false, 20, GameMode.SURVIVAL, null, null)));
|
||||||
SERVER_PACKETS.add(new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER, new PlayerInfoPacket.RemovePlayer(UUID.randomUUID())));
|
SERVER_PACKETS.add(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_LISTED,
|
||||||
|
new PlayerInfoUpdatePacket.Entry(UUID.randomUUID(), "", List.of(), true, 0, GameMode.SURVIVAL, null, null)));
|
||||||
|
SERVER_PACKETS.add(new PlayerInfoRemovePacket(UUID.randomUUID()));
|
||||||
|
|
||||||
//SERVER_PACKETS.add(new MultiBlockChangePacket(5,5,5,true, new long[]{0,5,543534,1321}));
|
//SERVER_PACKETS.add(new MultiBlockChangePacket(5,5,5,true, new long[]{0,5,543534,1321}));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user