forked from BLOCKFANTASY/LOOHP-Limbo
Re-structure + Adventure
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package com.loohp.limbo.network;
|
||||
|
||||
public class Channel {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
package com.loohp.limbo.network;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.events.player.PlayerJoinEvent;
|
||||
import com.loohp.limbo.events.player.PlayerLoginEvent;
|
||||
import com.loohp.limbo.events.player.PlayerMoveEvent;
|
||||
import com.loohp.limbo.events.player.PlayerQuitEvent;
|
||||
import com.loohp.limbo.events.player.PlayerResourcePackStatusEvent;
|
||||
import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent;
|
||||
import com.loohp.limbo.events.status.StatusPingEvent;
|
||||
import com.loohp.limbo.file.ServerProperties;
|
||||
import com.loohp.limbo.location.Location;
|
||||
import com.loohp.limbo.network.protocol.packets.Packet;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketLoginInLoginStart;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketLoginInPluginMessaging;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketLoginOutDisconnect;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketLoginOutLoginSuccess;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInChat;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus.EnumResourcePackStatus;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDeclareCommands;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDisconnect;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutKeepAlive;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutLogin;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoAction;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnPosition;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete.TabCompleteMatches;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutUpdateViewPosition;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketStatusInPing;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketStatusInRequest;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketStatusOutPong;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketStatusOutResponse;
|
||||
import com.loohp.limbo.player.Player;
|
||||
import com.loohp.limbo.player.PlayerInteractManager;
|
||||
import com.loohp.limbo.utils.BungeecordAdventureConversionUtils;
|
||||
import com.loohp.limbo.utils.CheckedBiConsumer;
|
||||
import com.loohp.limbo.utils.CustomStringUtils;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.DeclareCommands;
|
||||
import com.loohp.limbo.utils.ForwardingUtils;
|
||||
import com.loohp.limbo.utils.GameMode;
|
||||
import com.loohp.limbo.utils.MojangAPIUtils;
|
||||
import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse;
|
||||
import com.loohp.limbo.world.BlockPosition;
|
||||
import com.loohp.limbo.world.World;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
|
||||
public class ClientConnection extends Thread {
|
||||
|
||||
public static enum ClientState {
|
||||
LEGACY,
|
||||
HANDSHAKE,
|
||||
STATUS,
|
||||
LOGIN,
|
||||
PLAY,
|
||||
DISCONNECTED;
|
||||
}
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
private final Socket client_socket;
|
||||
private boolean running;
|
||||
private ClientState state;
|
||||
|
||||
private Player player;
|
||||
private TimerTask keepAliveTask;
|
||||
private AtomicLong lastPacketTimestamp;
|
||||
private AtomicLong lastKeepAlivePayLoad;
|
||||
|
||||
private DataOutputStream output;
|
||||
private DataInputStream input;
|
||||
|
||||
private InetAddress inetAddress;
|
||||
|
||||
private boolean ready;
|
||||
|
||||
public ClientConnection(Socket client_socket) {
|
||||
this.client_socket = client_socket;
|
||||
this.inetAddress = client_socket.getInetAddress();
|
||||
this.lastPacketTimestamp = new AtomicLong(-1);
|
||||
this.lastKeepAlivePayLoad = new AtomicLong(-1);
|
||||
this.running = false;
|
||||
this.ready = false;
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress() {
|
||||
return inetAddress;
|
||||
}
|
||||
|
||||
public long getLastKeepAlivePayLoad() {
|
||||
return lastKeepAlivePayLoad.get();
|
||||
}
|
||||
|
||||
public void setLastKeepAlivePayLoad(long payLoad) {
|
||||
this.lastKeepAlivePayLoad.set(payLoad);
|
||||
}
|
||||
|
||||
public long getLastPacketTimestamp() {
|
||||
return lastPacketTimestamp.get();
|
||||
}
|
||||
|
||||
public void setLastPacketTimestamp(long payLoad) {
|
||||
this.lastPacketTimestamp.set(payLoad);
|
||||
}
|
||||
|
||||
public TimerTask getKeepAliveTask() {
|
||||
return this.keepAliveTask;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public ClientState getClientState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public Socket getSocket() {
|
||||
return client_socket;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
public synchronized void sendPacket(PacketOut packet) throws IOException {
|
||||
byte[] packetByte = packet.serializePacket();
|
||||
DataTypeIO.writeVarInt(output, packetByte.length);
|
||||
output.write(packetByte);
|
||||
output.flush();
|
||||
setLastPacketTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void disconnect(BaseComponent[] reason) {
|
||||
disconnect(BungeecordAdventureConversionUtils.toComponent(reason));
|
||||
}
|
||||
|
||||
public void disconnect(Component reason) {
|
||||
try {
|
||||
PacketPlayOutDisconnect packet = new PacketPlayOutDisconnect(reason);
|
||||
sendPacket(packet);
|
||||
} catch (IOException e) {}
|
||||
try {
|
||||
client_socket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
private void disconnectDuringLogin(BaseComponent[] reason) {
|
||||
disconnectDuringLogin(BungeecordAdventureConversionUtils.toComponent(reason));
|
||||
}
|
||||
|
||||
private void disconnectDuringLogin(Component reason) {
|
||||
try {
|
||||
PacketLoginOutDisconnect packet = new PacketLoginOutDisconnect(reason);
|
||||
sendPacket(packet);
|
||||
} catch (IOException e) {}
|
||||
try {
|
||||
client_socket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void run() {
|
||||
running = true;
|
||||
state = ClientState.HANDSHAKE;
|
||||
try {
|
||||
client_socket.setKeepAlive(true);
|
||||
input = new DataInputStream(client_socket.getInputStream());
|
||||
output = new DataOutputStream(client_socket.getOutputStream());
|
||||
int handShakeSize = DataTypeIO.readVarInt(input);
|
||||
|
||||
//legacy ping
|
||||
if (handShakeSize == 0xFE) {
|
||||
state = ClientState.LEGACY;
|
||||
output.writeByte(255);
|
||||
String str = inetAddress.getHostName() + ":" + client_socket.getPort();
|
||||
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Legacy Status has pinged");
|
||||
ServerProperties p = Limbo.getInstance().getServerProperties();
|
||||
StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), p.getMotd(), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)));
|
||||
String response = Limbo.getInstance().buildLegacyPingResponse(event.getVersion(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline());
|
||||
byte[] bytes = response.getBytes(StandardCharsets.UTF_16BE);
|
||||
output.writeShort(response.length());
|
||||
output.write(bytes);
|
||||
|
||||
client_socket.close();
|
||||
state = ClientState.DISCONNECTED;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
int handShakeId = DataTypeIO.readVarInt(input);
|
||||
|
||||
PacketHandshakingIn handshake = new PacketHandshakingIn(input);
|
||||
|
||||
boolean isBungeecord = Limbo.getInstance().getServerProperties().isBungeecord();
|
||||
boolean isBungeeGuard = Limbo.getInstance().getServerProperties().isBungeeGuard();
|
||||
boolean isVelocityModern = Limbo.getInstance().getServerProperties().isVelocityModern();
|
||||
String bungeeForwarding = handshake.getServerAddress();
|
||||
UUID bungeeUUID = null;
|
||||
SkinResponse forwardedSkin = null;
|
||||
|
||||
try {
|
||||
switch (handshake.getHandshakeType()) {
|
||||
case STATUS:
|
||||
state = ClientState.STATUS;
|
||||
while (client_socket.isConnected()) {
|
||||
DataTypeIO.readVarInt(input);
|
||||
int packetId = DataTypeIO.readVarInt(input);
|
||||
Class<? extends Packet> packetType = Packet.getStatusIn().get(packetId);
|
||||
if (packetType == null) {
|
||||
//do nothing
|
||||
} else if (packetType.equals(PacketStatusInRequest.class)) {
|
||||
String str = inetAddress.getHostName() + ":" + client_socket.getPort();
|
||||
if (Limbo.getInstance().getServerProperties().handshakeVerboseEnabled()) {
|
||||
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Handshake Status has pinged");
|
||||
}
|
||||
ServerProperties p = Limbo.getInstance().getServerProperties();
|
||||
StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), p.getMotd(), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)));
|
||||
PacketStatusOutResponse packet = new PacketStatusOutResponse(Limbo.getInstance().buildServerListResponseJson(event.getVersion(), event.getProtocol(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline(), event.getFavicon()));
|
||||
sendPacket(packet);
|
||||
} else if (packetType.equals(PacketStatusInPing.class)) {
|
||||
PacketStatusInPing ping = new PacketStatusInPing(input);
|
||||
PacketStatusOutPong packet = new PacketStatusOutPong(ping.getPayload());
|
||||
sendPacket(packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOGIN:
|
||||
state = ClientState.LOGIN;
|
||||
|
||||
if (isBungeecord || isBungeeGuard) {
|
||||
try {
|
||||
String[] data = bungeeForwarding.split("\\x00");
|
||||
//String host = data[0];
|
||||
String ip = data[1];
|
||||
|
||||
bungeeUUID = UUID.fromString(data[2].replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5"));
|
||||
inetAddress = InetAddress.getByName(ip);
|
||||
|
||||
boolean bungeeGuardFound = false;
|
||||
if (data.length > 3) {
|
||||
JSONArray skinJson = (JSONArray) new JSONParser().parse(data[3]);
|
||||
|
||||
for (Object obj : skinJson) {
|
||||
JSONObject property = (JSONObject) obj;
|
||||
if (property.get("name").toString().equals("textures")) {
|
||||
String skin = property.get("value").toString();
|
||||
String signature = property.get("signature").toString();
|
||||
forwardedSkin = new SkinResponse(skin, signature);
|
||||
} else if (isBungeeGuard && property.get("name").toString().equals("bungeeguard-token")) {
|
||||
String token = property.get("value").toString();
|
||||
bungeeGuardFound = Limbo.getInstance().getServerProperties().getForwardingSecrets().contains(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isBungeeGuard && !bungeeGuardFound) {
|
||||
disconnectDuringLogin(TextComponent.fromLegacyText("Invalid information forwarding"));
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Limbo.getInstance().getConsole().sendMessage("If you wish to use bungeecord's IP forwarding, please enable that in your bungeecord config.yml as well!");
|
||||
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
|
||||
}
|
||||
}
|
||||
|
||||
int messageId = this.random.nextInt();
|
||||
while (client_socket.isConnected()) {
|
||||
int size = DataTypeIO.readVarInt(input);
|
||||
int packetId = DataTypeIO.readVarInt(input);
|
||||
Class<? extends Packet> packetType = Packet.getLoginIn().get(packetId);
|
||||
|
||||
if (packetType == null) {
|
||||
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
|
||||
} else if (packetType.equals(PacketLoginInLoginStart.class)) {
|
||||
PacketLoginInLoginStart start = new PacketLoginInLoginStart(input);
|
||||
String username = start.getUsername();
|
||||
|
||||
if (Limbo.getInstance().getServerProperties().isVelocityModern()) {
|
||||
PacketLoginOutPluginMessaging loginPluginRequest = new PacketLoginOutPluginMessaging(messageId, ForwardingUtils.VELOCITY_FORWARDING_CHANNEL);
|
||||
sendPacket(loginPluginRequest);
|
||||
continue;
|
||||
}
|
||||
|
||||
UUID uuid = isBungeecord || isBungeeGuard ? bungeeUUID : UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(uuid, username);
|
||||
sendPacket(success);
|
||||
|
||||
state = ClientState.PLAY;
|
||||
|
||||
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
||||
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
||||
Limbo.getInstance().addPlayer(player);
|
||||
|
||||
break;
|
||||
} else if (packetType.equals(PacketLoginInPluginMessaging.class)) {
|
||||
PacketLoginInPluginMessaging response = new PacketLoginInPluginMessaging(input, size, packetId);
|
||||
if (response.getMessageId() != messageId) {
|
||||
disconnectDuringLogin(TextComponent.fromLegacyText("Internal error, messageId did not match"));
|
||||
break;
|
||||
}
|
||||
if (!response.getData().isPresent()) {
|
||||
disconnectDuringLogin(TextComponent.fromLegacyText("Unknown login plugin response packet!"));
|
||||
break;
|
||||
}
|
||||
byte[] responseData = response.getData().get();
|
||||
if (!ForwardingUtils.validateVelocityModernResponse(responseData)) {
|
||||
disconnectDuringLogin(TextComponent.fromLegacyText("Invalid playerinfo forwarding!"));
|
||||
break;
|
||||
}
|
||||
ForwardingUtils.VelocityModernForwardingData data = ForwardingUtils.getVelocityDataFrom(responseData);
|
||||
inetAddress = InetAddress.getByName(data.getIpAddress());
|
||||
forwardedSkin = data.getSkinResponse();
|
||||
|
||||
PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(data.getUuid(), data.getUsername());
|
||||
sendPacket(success);
|
||||
|
||||
state = ClientState.PLAY;
|
||||
|
||||
player = new Player(this, data.getUsername(), data.getUuid(), Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
||||
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
||||
Limbo.getInstance().addPlayer(player);
|
||||
|
||||
break;
|
||||
} else {
|
||||
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
|
||||
}
|
||||
}
|
||||
|
||||
PlayerLoginEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerLoginEvent(this, false));
|
||||
if (event.isCancelled()) {
|
||||
disconnectDuringLogin(event.getCancelReason());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
client_socket.close();
|
||||
state = ClientState.DISCONNECTED;
|
||||
}
|
||||
|
||||
if (state == ClientState.PLAY) {
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
ServerProperties properties = Limbo.getInstance().getServerProperties();
|
||||
Location worldSpawn = properties.getWorldSpawn();
|
||||
|
||||
PlayerJoinEvent joinEvent = Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player, worldSpawn));
|
||||
worldSpawn = joinEvent.getSpawnLocation();
|
||||
World world = worldSpawn.getWorld();
|
||||
|
||||
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, 8, properties.isReducedDebugInfo(), true, false, true);
|
||||
sendPacket(join);
|
||||
Limbo.getInstance().getUnsafe().setPlayerGameModeSilently(player, properties.getDefaultGamemode());
|
||||
|
||||
SkinResponse skinresponce = (isVelocityModern || isBungeeGuard || isBungeecord) && forwardedSkin != null ? forwardedSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName());
|
||||
PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null;
|
||||
PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(PlayerInfoAction.ADD_PLAYER, player.getUniqueId(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), Optional.ofNullable(skin), properties.getDefaultGamemode(), 0, false, Optional.empty()));
|
||||
sendPacket(info);
|
||||
|
||||
Set<PlayerAbilityFlags> flags = new HashSet<>();
|
||||
if (properties.isAllowFlight()) {
|
||||
flags.add(PlayerAbilityFlags.FLY);
|
||||
}
|
||||
if (player.getGamemode().equals(GameMode.CREATIVE)) {
|
||||
flags.add(PlayerAbilityFlags.CREATIVE);
|
||||
}
|
||||
PacketPlayOutPlayerAbilities abilities = new PacketPlayOutPlayerAbilities(0.05F, 0.1F, flags.toArray(new PlayerAbilityFlags[flags.size()]));
|
||||
sendPacket(abilities);
|
||||
|
||||
String str = inetAddress.getHostName() + ":" + client_socket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")";
|
||||
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!");
|
||||
|
||||
PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandsPacket(player);
|
||||
if (declare != null) {
|
||||
sendPacket(declare);
|
||||
}
|
||||
|
||||
player.playerInteractManager.update();
|
||||
|
||||
PacketPlayOutSpawnPosition spawnPos = new PacketPlayOutSpawnPosition(BlockPosition.from(worldSpawn), worldSpawn.getPitch());
|
||||
sendPacket(spawnPos);
|
||||
|
||||
PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), worldSpawn.getYaw(), worldSpawn.getPitch(), 1, false);
|
||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, new Location(world, worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), worldSpawn.getYaw(), worldSpawn.getPitch()));
|
||||
sendPacket(positionLook);
|
||||
|
||||
player.getDataWatcher().update();
|
||||
PacketPlayOutEntityMetadata show = new PacketPlayOutEntityMetadata(player, false, Player.class.getDeclaredField("skinLayers"));
|
||||
sendPacket(show);
|
||||
|
||||
if (properties.isAllowFlight()) {
|
||||
PacketPlayOutGameState state = new PacketPlayOutGameState(3, player.getGamemode().getId());
|
||||
sendPacket(state);
|
||||
}
|
||||
|
||||
// RESOURCEPACK CODE CONRIBUTED BY GAMERDUCK123
|
||||
if (!properties.getResourcePackLink().equalsIgnoreCase("")) {
|
||||
if (!properties.getResourcePackSHA1().equalsIgnoreCase("")) {
|
||||
//SEND RESOURCEPACK
|
||||
player.setResourcePack(properties.getResourcePackLink(), properties.getResourcePackSHA1(), properties.getResourcePackRequired(), properties.getResourcePackPrompt());
|
||||
} else {
|
||||
//NO SHA
|
||||
Limbo.getInstance().getConsole().sendMessage("ResourcePacks require SHA1s");
|
||||
}
|
||||
} else {
|
||||
//RESOURCEPACK NOT ENABLED
|
||||
}
|
||||
|
||||
// PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123
|
||||
player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter());
|
||||
|
||||
ready = true;
|
||||
|
||||
keepAliveTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (ready) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - getLastPacketTimestamp() > 15000) {
|
||||
PacketPlayOutKeepAlive keepAlivePacket = new PacketPlayOutKeepAlive(now);
|
||||
try {
|
||||
sendPacket(keepAlivePacket);
|
||||
setLastKeepAlivePayLoad(now);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
} else {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
new Timer().schedule(keepAliveTask, 5000, 10000);
|
||||
|
||||
while (client_socket.isConnected()) {
|
||||
try {
|
||||
int size = DataTypeIO.readVarInt(input);
|
||||
int packetId = DataTypeIO.readVarInt(input);
|
||||
Class<? extends Packet> packetType = Packet.getPlayIn().get(packetId);
|
||||
//Limbo.getInstance().getConsole().sendMessage(packetId + " -> " + packetType);
|
||||
CheckedBiConsumer<PlayerMoveEvent, Location, IOException> processMoveEvent = (event, originalTo) -> {
|
||||
if (event.isCancelled()) {
|
||||
Location returnTo = event.getFrom();
|
||||
PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1, false);
|
||||
sendPacket(cancel);
|
||||
} else {
|
||||
Location to = event.getTo();
|
||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, to);
|
||||
// If an event handler used setTo, let's make sure we tell the player about it.
|
||||
if (!originalTo.equals(to)) {
|
||||
PacketPlayOutPositionAndLook pos = new PacketPlayOutPositionAndLook(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), 1, false);
|
||||
sendPacket(pos);
|
||||
}
|
||||
PacketPlayOutUpdateViewPosition response = new PacketPlayOutUpdateViewPosition((int) player.getLocation().getX() >> 4, (int) player.getLocation().getZ() >> 4);
|
||||
sendPacket(response);
|
||||
}
|
||||
};
|
||||
if (packetType == null) {
|
||||
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
|
||||
} else if (packetType.equals(PacketPlayInPositionAndLook.class)) {
|
||||
PacketPlayInPositionAndLook pos = new PacketPlayInPositionAndLook(input);
|
||||
Location from = player.getLocation();
|
||||
Location to = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ(), pos.getYaw(), pos.getPitch());
|
||||
|
||||
if (!from.equals(to)) {
|
||||
PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to));
|
||||
processMoveEvent.consume(event, to);
|
||||
}
|
||||
} else if (packetType.equals(PacketPlayInPosition.class)) {
|
||||
PacketPlayInPosition pos = new PacketPlayInPosition(input);
|
||||
Location from = player.getLocation();
|
||||
Location to = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ(), player.getLocation().getYaw(), player.getLocation().getPitch());
|
||||
|
||||
if (!from.equals(to)) {
|
||||
PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to));
|
||||
processMoveEvent.consume(event, to);
|
||||
}
|
||||
} else if (packetType.equals(PacketPlayInRotation.class)) {
|
||||
PacketPlayInRotation pos = new PacketPlayInRotation(input);
|
||||
Location from = player.getLocation();
|
||||
Location to = new Location(player.getWorld(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), pos.getYaw(), pos.getPitch());
|
||||
|
||||
if (!from.equals(to)) {
|
||||
PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to));
|
||||
processMoveEvent.consume(event, to);
|
||||
}
|
||||
} else if (packetType.equals(PacketPlayInKeepAlive.class)) {
|
||||
PacketPlayInKeepAlive alive = new PacketPlayInKeepAlive(input);
|
||||
if (alive.getPayload() != getLastKeepAlivePayLoad()) {
|
||||
Limbo.getInstance().getConsole().sendMessage("Incorrect Payload recieved in KeepAlive packet for player " + player.getName());
|
||||
break;
|
||||
}
|
||||
} else if (packetType.equals(PacketPlayInTabComplete.class)) {
|
||||
PacketPlayInTabComplete request = new PacketPlayInTabComplete(input);
|
||||
String[] command = CustomStringUtils.splitStringToArgs(request.getText().substring(1));
|
||||
|
||||
List<TabCompleteMatches> matches = new ArrayList<TabCompleteMatches>();
|
||||
|
||||
matches.addAll(Limbo.getInstance().getPluginManager().getTabOptions(player, command).stream().map(each -> new TabCompleteMatches(each)).collect(Collectors.toList()));
|
||||
|
||||
int start = CustomStringUtils.getIndexOfArg(request.getText(), command.length - 1) + 1;
|
||||
int length = command[command.length - 1].length();
|
||||
|
||||
PacketPlayOutTabComplete response = new PacketPlayOutTabComplete(request.getId(), start, length, matches.toArray(new TabCompleteMatches[matches.size()]));
|
||||
sendPacket(response);
|
||||
} else if (packetType.equals(PacketPlayInChat.class)) {
|
||||
PacketPlayInChat chat = new PacketPlayInChat(input);
|
||||
if (chat.getMessage().startsWith("/")) {
|
||||
Limbo.getInstance().dispatchCommand(player, chat.getMessage());
|
||||
} else {
|
||||
player.chat(chat.getMessage(), true);
|
||||
}
|
||||
} else if (packetType.equals(PacketPlayInHeldItemChange.class)) {
|
||||
PacketPlayInHeldItemChange change = new PacketPlayInHeldItemChange(input);
|
||||
PlayerSelectedSlotChangeEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSelectedSlotChangeEvent(player, (byte) change.getSlot()));
|
||||
if (event.isCancelled()) {
|
||||
PacketPlayOutHeldItemChange cancelPacket = new PacketPlayOutHeldItemChange(player.getSelectedSlot());
|
||||
sendPacket(cancelPacket);
|
||||
} else if (change.getSlot() != event.getSlot()) {
|
||||
PacketPlayOutHeldItemChange changePacket = new PacketPlayOutHeldItemChange(event.getSlot());
|
||||
sendPacket(changePacket);
|
||||
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
|
||||
} else {
|
||||
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
|
||||
}
|
||||
|
||||
} else if (packetType.equals(PacketPlayInResourcePackStatus.class)) {
|
||||
PacketPlayInResourcePackStatus rpcheck = new PacketPlayInResourcePackStatus(input);
|
||||
// Pass on result to the events
|
||||
Limbo.getInstance().getEventsManager().callEvent(new PlayerResourcePackStatusEvent(player, rpcheck.getLoadedValue()));
|
||||
if (rpcheck.getLoadedValue().equals(EnumResourcePackStatus.DECLINED) && properties.getResourcePackRequired()) {
|
||||
player.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"));
|
||||
}
|
||||
} else {
|
||||
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Limbo.getInstance().getEventsManager().callEvent(new PlayerQuitEvent(player));
|
||||
|
||||
str = inetAddress.getHostName() + ":" + client_socket.getPort() + "|" + player.getName();
|
||||
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had disconnected!");
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
|
||||
try {
|
||||
client_socket.close();
|
||||
} catch (IOException e) {}
|
||||
state = ClientState.DISCONNECTED;
|
||||
|
||||
if (player != null) {
|
||||
Limbo.getInstance().removePlayer(player);
|
||||
}
|
||||
Limbo.getInstance().getServerConnection().getClients().remove(this);
|
||||
running = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.loohp.limbo.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
|
||||
public class ServerConnection extends Thread {
|
||||
|
||||
private ServerSocket serverSocket;
|
||||
private List<ClientConnection> clients;
|
||||
private String ip;
|
||||
private int port;
|
||||
|
||||
public ServerConnection(String ip, int port) {
|
||||
clients = new ArrayList<ClientConnection>();
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
serverSocket = new ServerSocket(port, 50, InetAddress.getByName(ip));
|
||||
Limbo.getInstance().getConsole().sendMessage("Limbo server listening on /" + serverSocket.getInetAddress().getHostName() + ":" + serverSocket.getLocalPort());
|
||||
while (true) {
|
||||
Socket connection = serverSocket.accept();
|
||||
ClientConnection sc = new ClientConnection(connection);
|
||||
clients.add(sc);
|
||||
sc.start();
|
||||
}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ServerSocket getServerSocket() {
|
||||
return serverSocket;
|
||||
}
|
||||
|
||||
public List<ClientConnection> getClients() {
|
||||
return clients;
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ClientboundClearTitlesPacket extends PacketOut {
|
||||
|
||||
private boolean reset;
|
||||
|
||||
public ClientboundClearTitlesPacket(boolean reset) {
|
||||
this.reset = reset;
|
||||
}
|
||||
|
||||
public boolean isReset() {
|
||||
return reset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeBoolean(reset);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.loohp.limbo.registry.Registry;
|
||||
import com.loohp.limbo.utils.BitsUtils;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
import com.loohp.limbo.world.Environment;
|
||||
import com.loohp.limbo.world.GeneratedBlockDataMappings;
|
||||
|
||||
import net.querz.mca.Chunk;
|
||||
import net.querz.mca.Section;
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
import net.querz.nbt.tag.ListTag;
|
||||
|
||||
public class ClientboundLevelChunkWithLightPacket extends PacketOut {
|
||||
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
private Chunk chunk;
|
||||
private Environment environment;
|
||||
private boolean trustEdges;
|
||||
private long[] skyLightBitMasks;
|
||||
private long[] blockLightBitMasks;
|
||||
private long[] skyLightBitMasksEmpty;
|
||||
private long[] blockLightBitMasksEmpty;
|
||||
private List<Byte[]> skylightArrays;
|
||||
private List<Byte[]> blocklightArrays;
|
||||
|
||||
public ClientboundLevelChunkWithLightPacket(int chunkX, int chunkZ, Chunk chunk, Environment environment, boolean trustEdges, List<Byte[]> skylightArrays, List<Byte[]> blocklightArrays) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
this.chunk = chunk;
|
||||
this.environment = environment;
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
this.trustEdges = trustEdges;
|
||||
this.skylightArrays = skylightArrays;
|
||||
this.blocklightArrays = blocklightArrays;
|
||||
|
||||
BitSet skyLightBitSet = new BitSet();
|
||||
BitSet skyLightBitSetInverse = new BitSet();
|
||||
for (int i = Math.min(17, skylightArrays.size() - 1); i >= 0; i--) {
|
||||
skyLightBitSet.set(i, skylightArrays.get(i) != null);
|
||||
skyLightBitSetInverse.set(i, skylightArrays.get(i) == null);
|
||||
}
|
||||
skyLightBitMasks = skyLightBitSet.toLongArray();
|
||||
skyLightBitMasksEmpty = skyLightBitSetInverse.toLongArray();
|
||||
|
||||
BitSet blockLightBitSet = new BitSet();
|
||||
BitSet blockLightBitSetInverse = new BitSet();
|
||||
for (int i = Math.min(17, blocklightArrays.size() - 1); i >= 0; i--) {
|
||||
blockLightBitSet.set(i, blocklightArrays.get(i) != null);
|
||||
blockLightBitSetInverse.set(i, blocklightArrays.get(i) == null);
|
||||
}
|
||||
blockLightBitMasks = blockLightBitSet.toLongArray();
|
||||
blockLightBitMasksEmpty = blockLightBitSetInverse.toLongArray();
|
||||
}
|
||||
|
||||
public Chunk getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public int getChunkX() {
|
||||
return chunkX;
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
public Environment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
public boolean isTrustEdges() {
|
||||
return trustEdges;
|
||||
}
|
||||
|
||||
public long[] getSkyLightBitMasks() {
|
||||
return skyLightBitMasks;
|
||||
}
|
||||
|
||||
public long[] getBlockLightBitMasks() {
|
||||
return blockLightBitMasks;
|
||||
}
|
||||
|
||||
public List<Byte[]> getSkylightArrays() {
|
||||
return skylightArrays;
|
||||
}
|
||||
|
||||
public List<Byte[]> getBlocklightArrays() {
|
||||
return blocklightArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
|
||||
output.writeInt(chunkX);
|
||||
output.writeInt(chunkZ);
|
||||
DataTypeIO.writeCompoundTag(output, chunk.getHeightMaps());
|
||||
|
||||
ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
|
||||
DataOutputStream dataOut = new DataOutputStream(dataBuffer);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
Section section = chunk.getSection(i);
|
||||
if (section != null) {
|
||||
int counter = 0;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
CompoundTag tag = section.getBlockStateAt(x, y, z);
|
||||
if (tag != null && !tag.getString("Name").equals("minecraft:air")) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dataOut.writeShort(counter);
|
||||
|
||||
int newBits = 32 - Integer.numberOfLeadingZeros(section.getPalette().size() - 1);
|
||||
newBits = Math.max(newBits, 4);
|
||||
//Limbo.getInstance().getConsole().sendMessage(i + " " + newBits);
|
||||
if (newBits <= 8) {
|
||||
/*
|
||||
if (newBits == 4) {
|
||||
dataOut.writeByte(4);
|
||||
} else {
|
||||
newBits = 8;
|
||||
ChunkDataUtils.adjustBlockStateBits(newBits, section, chunk.getDataVersion());
|
||||
dataOut.writeByte(8);
|
||||
}
|
||||
*/
|
||||
dataOut.writeByte(newBits);
|
||||
|
||||
DataTypeIO.writeVarInt(dataOut, section.getPalette().size());
|
||||
//Limbo.getInstance().getConsole().sendMessage(section.getPalette().size());
|
||||
Iterator<CompoundTag> itr1 = section.getPalette().iterator();
|
||||
//Limbo.getInstance().getConsole().sendMessage("Nonnull -> " + i + " " + newBits);
|
||||
while (itr1.hasNext()) {
|
||||
CompoundTag tag = itr1.next();
|
||||
DataTypeIO.writeVarInt(dataOut, GeneratedBlockDataMappings.getGlobalPaletteIDFromState(tag));
|
||||
//Limbo.getInstance().getConsole().sendMessage(tag + " -> " + GeneratedDataUtils.getGlobalPaletteIDFromState(tag));
|
||||
}
|
||||
|
||||
BitSet bits = BitSet.valueOf(section.getBlockStates());
|
||||
int shift = 64 % newBits;
|
||||
int longsNeeded = (int) Math.ceil(4096 / (double) (64 / newBits));
|
||||
for (int u = 64; u <= bits.length(); u += 64) {
|
||||
bits = BitsUtils.shiftAfter(bits, u - shift, shift);
|
||||
}
|
||||
|
||||
long[] formattedLongs = bits.toLongArray();
|
||||
//Limbo.getInstance().getConsole().sendMessage(longsNeeded + "");
|
||||
|
||||
DataTypeIO.writeVarInt(dataOut, longsNeeded);
|
||||
for (int u = 0; u < longsNeeded; u++) {
|
||||
if (u < formattedLongs.length) {
|
||||
dataOut.writeLong(formattedLongs[u]);
|
||||
} else {
|
||||
dataOut.writeLong(0);
|
||||
}
|
||||
//Limbo.getInstance().getConsole().sendMessage(Arrays.toString(section.getBlockStates()));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
dataOut.writeByte(15);
|
||||
section.getBlockStates();
|
||||
int longsNeeded = 1024;
|
||||
List<Integer> list = new LinkedList<>();
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
list.add(GeneratedBlockDataMappings.getGlobalPaletteIDFromState(section.getBlockStateAt(x, y, z)));
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Long> globalLongs = new ArrayList<>();
|
||||
long currentLong = 0;
|
||||
int pos = 0;
|
||||
int u = 0;
|
||||
while (pos < longsNeeded) {
|
||||
if (u == 3) {
|
||||
globalLongs.add(currentLong);
|
||||
currentLong = 0;
|
||||
u = 0;
|
||||
pos++;
|
||||
} else {
|
||||
u++;
|
||||
}
|
||||
int id = list.isEmpty() ? 0 : list.remove(0);
|
||||
currentLong = currentLong << 15;
|
||||
currentLong |= (long) id;
|
||||
}
|
||||
DataTypeIO.writeVarInt(dataOut, longsNeeded);
|
||||
for (int j = 0; j < longsNeeded; j++) {
|
||||
if (j < globalLongs.size()) {
|
||||
dataOut.writeLong(globalLongs.get(j));
|
||||
} else {
|
||||
dataOut.writeLong(0);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dataOut.writeShort(0);
|
||||
dataOut.writeByte(0);
|
||||
DataTypeIO.writeVarInt(dataOut, 0);
|
||||
DataTypeIO.writeVarInt(dataOut, 0);
|
||||
}
|
||||
int biome;
|
||||
if (environment.equals(Environment.END)) {
|
||||
biome = 9; //the_end
|
||||
} else if (environment.equals(Environment.NETHER)) {
|
||||
biome = 8; //nether_waste
|
||||
} else if (environment.equals(Environment.NORMAL)) {
|
||||
biome = 1; //plains
|
||||
} else {
|
||||
biome = 1; //plains
|
||||
}
|
||||
dataOut.writeByte(0);
|
||||
DataTypeIO.writeVarInt(dataOut, biome);
|
||||
DataTypeIO.writeVarInt(dataOut, 0);
|
||||
}
|
||||
|
||||
byte[] data = dataBuffer.toByteArray();
|
||||
DataTypeIO.writeVarInt(output, data.length);
|
||||
output.write(data);
|
||||
|
||||
ListTag<CompoundTag> tileEntities = chunk.getTileEntities();
|
||||
DataTypeIO.writeVarInt(output, tileEntities.size());
|
||||
for (CompoundTag each : tileEntities) {
|
||||
int x = each.getInt("x") % 16;
|
||||
int y = each.getInt("y");
|
||||
int z = each.getInt("z") % 16;
|
||||
output.writeByte((x << 4) | z);
|
||||
output.writeShort(y);
|
||||
Integer id = Registry.BLOCK_ENTITY_TYPE.getId(new NamespacedKey(chunk.getBlockStateAt(x, y, z).getString("Name")));
|
||||
DataTypeIO.writeVarInt(output, id == null ? -1 : id);
|
||||
DataTypeIO.writeCompoundTag(output, each);
|
||||
}
|
||||
|
||||
output.writeBoolean(trustEdges);
|
||||
DataTypeIO.writeVarInt(output, skyLightBitMasks.length);
|
||||
for (long l : skyLightBitMasks) {
|
||||
output.writeLong(l);
|
||||
}
|
||||
DataTypeIO.writeVarInt(output, blockLightBitMasks.length);
|
||||
for (long l : blockLightBitMasks) {
|
||||
output.writeLong(l);
|
||||
}
|
||||
DataTypeIO.writeVarInt(output, skyLightBitMasksEmpty.length);
|
||||
for (long l : skyLightBitMasksEmpty) {
|
||||
output.writeLong(l);
|
||||
}
|
||||
DataTypeIO.writeVarInt(output, blockLightBitMasksEmpty.length);
|
||||
for (long l : blockLightBitMasksEmpty) {
|
||||
output.writeLong(l);
|
||||
}
|
||||
|
||||
DataTypeIO.writeVarInt(output, skylightArrays.stream().mapToInt(each -> each == null ? 0 : 1).sum());
|
||||
for (int i = skylightArrays.size() - 1; i >= 0; i--) {
|
||||
Byte[] array = skylightArrays.get(i);
|
||||
if (array != null) {
|
||||
DataTypeIO.writeVarInt(output, 2048);
|
||||
//System.out.println(Arrays.toString(ArrayUtils.toPrimitive(array)));
|
||||
for (int u = 0; u < array.length; u++) {
|
||||
output.writeByte(array[u]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataTypeIO.writeVarInt(output, blocklightArrays.stream().mapToInt(each -> each == null ? 0 : 1).sum());
|
||||
for (int i = blocklightArrays.size() - 1; i >= 0; i--) {
|
||||
Byte[] array = blocklightArrays.get(i);
|
||||
if (array != null) {
|
||||
DataTypeIO.writeVarInt(output, 2048);
|
||||
//System.out.println(Arrays.toString(ArrayUtils.toPrimitive(array)));
|
||||
for (int u = 0; u < array.length; u++) {
|
||||
output.writeByte(array[u]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class ClientboundSetSubtitleTextPacket extends PacketOut {
|
||||
|
||||
private Component subTitle;
|
||||
|
||||
public ClientboundSetSubtitleTextPacket(Component subTitle) {
|
||||
this.subTitle = subTitle;
|
||||
}
|
||||
|
||||
public Component getSubTitle() {
|
||||
return subTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(subTitle), StandardCharsets.UTF_8);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class ClientboundSetTitleTextPacket extends PacketOut {
|
||||
|
||||
private Component titleText;
|
||||
|
||||
public ClientboundSetTitleTextPacket(Component titleText) {
|
||||
this.titleText = titleText;
|
||||
}
|
||||
|
||||
public Component getTitle() {
|
||||
return titleText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(titleText), StandardCharsets.UTF_8);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ClientboundSetTitlesAnimationPacket extends PacketOut {
|
||||
|
||||
private int fadeIn;
|
||||
private int stay;
|
||||
private int fadeOut;
|
||||
|
||||
public ClientboundSetTitlesAnimationPacket(int fadeIn, int stay, int fadeOut) {
|
||||
this.fadeIn = fadeIn;
|
||||
this.stay = stay;
|
||||
this.fadeOut = fadeOut;
|
||||
}
|
||||
|
||||
public int getFadeIn() {
|
||||
return fadeIn;
|
||||
}
|
||||
|
||||
public int getStay() {
|
||||
return stay;
|
||||
}
|
||||
|
||||
public int getFadeOut() {
|
||||
return fadeOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
|
||||
output.writeInt(fadeIn);
|
||||
output.writeInt(stay);
|
||||
output.writeInt(fadeOut);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Packet {
|
||||
|
||||
private static Map<Integer, Class<? extends PacketIn>> HandshakeIn;
|
||||
|
||||
private static Map<Integer, Class<? extends PacketIn>> StatusIn;
|
||||
private static Map<Class<? extends PacketOut>, Integer> StatusOut;
|
||||
|
||||
private static Map<Integer, Class<? extends PacketIn>> LoginIn;
|
||||
private static Map<Class<? extends PacketOut>, Integer> LoginOut;
|
||||
|
||||
private static Map<Integer, Class<? extends PacketIn>> PlayIn;
|
||||
private static Map<Class<? extends PacketOut>, Integer> PlayOut;
|
||||
|
||||
public static Map<Integer, Class<? extends PacketIn>> getHandshakeIn() {
|
||||
return HandshakeIn;
|
||||
}
|
||||
|
||||
public static void setHandshakeIn(Map<Integer, Class<? extends PacketIn>> handshakeIn) {
|
||||
HandshakeIn = handshakeIn;
|
||||
}
|
||||
|
||||
public static Map<Integer, Class<? extends PacketIn>> getStatusIn() {
|
||||
return StatusIn;
|
||||
}
|
||||
|
||||
public static void setStatusIn(Map<Integer, Class<? extends PacketIn>> statusIn) {
|
||||
StatusIn = statusIn;
|
||||
}
|
||||
|
||||
public static Map<Class<? extends PacketOut>, Integer> getStatusOut() {
|
||||
return StatusOut;
|
||||
}
|
||||
|
||||
public static void setStatusOut(Map<Class<? extends PacketOut>, Integer> statusOut) {
|
||||
StatusOut = statusOut;
|
||||
}
|
||||
|
||||
public static Map<Integer, Class<? extends PacketIn>> getLoginIn() {
|
||||
return LoginIn;
|
||||
}
|
||||
|
||||
public static void setLoginIn(Map<Integer, Class<? extends PacketIn>> loginIn) {
|
||||
LoginIn = loginIn;
|
||||
}
|
||||
|
||||
public static Map<Class<? extends PacketOut>, Integer> getLoginOut() {
|
||||
return LoginOut;
|
||||
}
|
||||
|
||||
public static void setLoginOut(Map<Class<? extends PacketOut>, Integer> loginOut) {
|
||||
LoginOut = loginOut;
|
||||
}
|
||||
|
||||
public static Map<Integer, Class<? extends PacketIn>> getPlayIn() {
|
||||
return PlayIn;
|
||||
}
|
||||
|
||||
public static void setPlayIn(Map<Integer, Class<? extends PacketIn>> playIn) {
|
||||
PlayIn = playIn;
|
||||
}
|
||||
|
||||
public static Map<Class<? extends PacketOut>, Integer> getPlayOut() {
|
||||
return PlayOut;
|
||||
}
|
||||
|
||||
public static void setPlayOut(Map<Class<? extends PacketOut>, Integer> playOut) {
|
||||
PlayOut = playOut;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketHandshakingIn extends PacketIn {
|
||||
|
||||
public static enum HandshakeType {
|
||||
STATUS(1),
|
||||
LOGIN(2);
|
||||
|
||||
int networkId;
|
||||
|
||||
HandshakeType(int networkId) {
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
public int getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public static HandshakeType fromNetworkId(int networkId) {
|
||||
for (HandshakeType type : HandshakeType.values()) {
|
||||
if (type.getNetworkId() == networkId) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================
|
||||
|
||||
private int protocolVersion;
|
||||
private String serverAddress;
|
||||
private int serverPort;
|
||||
private HandshakeType handshakeType;
|
||||
|
||||
public PacketHandshakingIn(int protocolVersion, String serverAddress, int serverPort, HandshakeType handshakeType) {
|
||||
this.protocolVersion = protocolVersion;
|
||||
this.serverAddress = serverAddress;
|
||||
this.serverPort = serverPort;
|
||||
this.handshakeType = handshakeType;
|
||||
}
|
||||
|
||||
public PacketHandshakingIn(DataInputStream in) throws IOException {
|
||||
this(DataTypeIO.readVarInt(in), DataTypeIO.readString(in, StandardCharsets.UTF_8), in.readShort() & 0xFFFF, HandshakeType.fromNetworkId(DataTypeIO.readVarInt(in)));
|
||||
}
|
||||
|
||||
public int getProtocolVersion() {
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
public String getServerAddress() {
|
||||
return serverAddress;
|
||||
}
|
||||
|
||||
public int getServerPort() {
|
||||
return serverPort;
|
||||
}
|
||||
|
||||
public HandshakeType getHandshakeType() {
|
||||
return handshakeType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
public abstract class PacketIn extends Packet {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketLoginInLoginStart extends PacketIn {
|
||||
|
||||
private String username;
|
||||
|
||||
public PacketLoginInLoginStart(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public PacketLoginInLoginStart(DataInputStream in) throws IOException {
|
||||
this(DataTypeIO.readString(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketLoginInPluginMessaging extends PacketIn {
|
||||
|
||||
private int messageId;
|
||||
private boolean successful;
|
||||
private Optional<byte[]> data;
|
||||
|
||||
public PacketLoginInPluginMessaging(int messageId, boolean successful, byte[] data) {
|
||||
this.messageId = messageId;
|
||||
this.successful = successful;
|
||||
this.data = successful ? Optional.of(data) : Optional.empty();
|
||||
}
|
||||
|
||||
public PacketLoginInPluginMessaging(DataInputStream in, int packetLength, int packetId) throws IOException {
|
||||
messageId = DataTypeIO.readVarInt(in);
|
||||
successful = in.readBoolean();
|
||||
if (successful) {
|
||||
int dataLength = packetLength - DataTypeIO.getVarIntLength(packetId) - DataTypeIO.getVarIntLength(messageId) - 1;
|
||||
if (dataLength != 0) {
|
||||
byte[] data = new byte[dataLength];
|
||||
in.readFully(data);
|
||||
this.data = Optional.of(data);
|
||||
} else {
|
||||
this.data = Optional.of(new byte[0]);
|
||||
}
|
||||
} else {
|
||||
data = Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return successful;
|
||||
}
|
||||
|
||||
public Optional<byte[]> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketLoginOutDisconnect extends PacketOut {
|
||||
|
||||
private Component reason;
|
||||
|
||||
public PacketLoginOutDisconnect(Component reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Component getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getLoginOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(reason), StandardCharsets.UTF_8);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketLoginOutLoginSuccess extends PacketOut {
|
||||
|
||||
private UUID uuid;
|
||||
private String username;
|
||||
|
||||
public PacketLoginOutLoginSuccess(UUID uuid, String username) {
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getLoginOut().get(getClass()));
|
||||
DataTypeIO.writeUUID(output, uuid);
|
||||
DataTypeIO.writeString(output, username, StandardCharsets.UTF_8);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
|
||||
public class PacketLoginOutPluginMessaging extends PacketOut {
|
||||
|
||||
private int messageId;
|
||||
private NamespacedKey channel;
|
||||
private byte[] data;
|
||||
|
||||
public PacketLoginOutPluginMessaging(int messageId, NamespacedKey channel) {
|
||||
this(messageId, channel, null);
|
||||
}
|
||||
|
||||
public PacketLoginOutPluginMessaging(int messageId, NamespacedKey channel, byte[] data) {
|
||||
this.messageId = messageId;
|
||||
this.channel = channel;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
public NamespacedKey getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getLoginOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, messageId);
|
||||
DataTypeIO.writeString(output, channel.toString(), StandardCharsets.UTF_8);
|
||||
if (data != null) {
|
||||
output.write(data);
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class PacketOut extends Packet {
|
||||
|
||||
public abstract byte[] serializePacket() throws IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayInChat extends PacketIn {
|
||||
|
||||
private String message;
|
||||
|
||||
public PacketPlayInChat(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public PacketPlayInChat(DataInputStream in) throws IOException {
|
||||
this(DataTypeIO.readString(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInHeldItemChange extends PacketIn {
|
||||
|
||||
private short slot;
|
||||
|
||||
public PacketPlayInHeldItemChange(short slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public PacketPlayInHeldItemChange(DataInputStream in) throws IOException {
|
||||
this(in.readShort());
|
||||
}
|
||||
|
||||
public short getSlot() {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInKeepAlive extends PacketIn {
|
||||
|
||||
private long payload;
|
||||
|
||||
public PacketPlayInKeepAlive(long payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public PacketPlayInKeepAlive(DataInputStream in) throws IOException {
|
||||
this(in.readLong());
|
||||
}
|
||||
|
||||
public long getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
|
||||
public class PacketPlayInPluginMessaging extends PacketIn {
|
||||
|
||||
private NamespacedKey channel;
|
||||
private byte[] data;
|
||||
|
||||
public PacketPlayInPluginMessaging(NamespacedKey channel, byte[] data) {
|
||||
this.channel = channel;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public PacketPlayInPluginMessaging(DataInputStream in, int packetLength, int packetId) throws IOException {
|
||||
String rawChannel = DataTypeIO.readString(in, StandardCharsets.UTF_8);
|
||||
channel = new NamespacedKey(rawChannel);
|
||||
int dataLength = packetLength - DataTypeIO.getVarIntLength(packetId) - DataTypeIO.getStringLength(rawChannel, StandardCharsets.UTF_8);
|
||||
data = new byte[dataLength];
|
||||
in.read(data);
|
||||
}
|
||||
|
||||
public NamespacedKey getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInPosition extends PacketIn {
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private boolean onGround;
|
||||
|
||||
public PacketPlayInPosition(double x, double y, double z, boolean onGround) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.onGround = onGround;
|
||||
}
|
||||
|
||||
public PacketPlayInPosition(DataInputStream in) throws IOException {
|
||||
this(in.readDouble(), in.readDouble(), in.readDouble(), in.readBoolean());
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public boolean onGround() {
|
||||
return onGround;
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInPositionAndLook extends PacketIn {
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private boolean onGround;
|
||||
|
||||
public PacketPlayInPositionAndLook(double x, double y, double z, float yaw, float pitch, boolean onGround) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.onGround = onGround;
|
||||
}
|
||||
|
||||
public PacketPlayInPositionAndLook(DataInputStream in) throws IOException {
|
||||
this(in.readDouble(), in.readDouble(), in.readDouble(), in.readFloat(), in.readFloat(), in.readBoolean());
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public boolean onGround() {
|
||||
return onGround;
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayInResourcePackStatus extends PacketIn {
|
||||
|
||||
public static enum EnumResourcePackStatus {
|
||||
SUCCESS,
|
||||
DECLINED,
|
||||
FAILED,
|
||||
ACCEPTED;
|
||||
}
|
||||
|
||||
private EnumResourcePackStatus loaded;
|
||||
|
||||
public PacketPlayInResourcePackStatus(EnumResourcePackStatus loaded) {
|
||||
this.loaded = loaded;
|
||||
}
|
||||
|
||||
public PacketPlayInResourcePackStatus(DataInputStream in) throws IOException {
|
||||
this(toLoadedValue(DataTypeIO.readVarInt(in)));
|
||||
}
|
||||
|
||||
public EnumResourcePackStatus getLoadedValue() {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
private static EnumResourcePackStatus toLoadedValue(int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
return EnumResourcePackStatus.SUCCESS;
|
||||
case 1:
|
||||
return EnumResourcePackStatus.DECLINED;
|
||||
case 2:
|
||||
return EnumResourcePackStatus.FAILED;
|
||||
case 3:
|
||||
return EnumResourcePackStatus.ACCEPTED;
|
||||
default:
|
||||
return EnumResourcePackStatus.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInRotation extends PacketIn {
|
||||
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private boolean onGround;
|
||||
|
||||
public PacketPlayInRotation(float yaw, float pitch, boolean onGround) {
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.onGround = onGround;
|
||||
}
|
||||
|
||||
public PacketPlayInRotation(DataInputStream in) throws IOException {
|
||||
this(in.readFloat(), in.readFloat(), in.readBoolean());
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public boolean onGround() {
|
||||
return onGround;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayInTabComplete extends PacketIn {
|
||||
|
||||
private int id;
|
||||
private String text;
|
||||
|
||||
public PacketPlayInTabComplete(int id, String text) {
|
||||
this.id = id;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public PacketPlayInTabComplete(DataInputStream in) throws IOException {
|
||||
this(DataTypeIO.readVarInt(in), DataTypeIO.readString(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketPlayOutChat extends PacketOut {
|
||||
|
||||
private Component message;
|
||||
private int position;
|
||||
private UUID sender;
|
||||
|
||||
public PacketPlayOutChat(Component message, int position, UUID sender) {
|
||||
this.message = message;
|
||||
this.position = position;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public Component getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public UUID getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(message), StandardCharsets.UTF_8);
|
||||
output.writeByte(position);
|
||||
DataTypeIO.writeUUID(output, sender);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutDeclareCommands extends PacketOut {
|
||||
|
||||
private byte[] data;
|
||||
|
||||
public PacketPlayOutDeclareCommands(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.write(data);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketPlayOutDisconnect extends PacketOut {
|
||||
|
||||
private Component reason;
|
||||
|
||||
public PacketPlayOutDisconnect(Component reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Component getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(reason), StandardCharsets.UTF_8);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutEntityDestroy extends PacketOut {
|
||||
|
||||
private int[] entityIds;
|
||||
|
||||
public PacketPlayOutEntityDestroy(int... entityIds) {
|
||||
this.entityIds = entityIds;
|
||||
}
|
||||
|
||||
public int[] getEntityIds() {
|
||||
return entityIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entityIds.length);
|
||||
for (int entityId : entityIds) {
|
||||
DataTypeIO.writeVarInt(output, entityId);
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.entity.DataWatcher.WatchableObject;
|
||||
import com.loohp.limbo.entity.DataWatcher.WatchableObjectType;
|
||||
import com.loohp.limbo.entity.Entity;
|
||||
import com.loohp.limbo.entity.Pose;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.Rotation3f;
|
||||
import com.loohp.limbo.world.BlockPosition;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketPlayOutEntityMetadata extends PacketOut {
|
||||
|
||||
public static final int END_OFF_METADATA = 0xff;
|
||||
|
||||
private Entity entity;
|
||||
public boolean allFields;
|
||||
public Field[] fields;
|
||||
|
||||
public PacketPlayOutEntityMetadata(Entity entity, boolean allFields, Field... fields) {
|
||||
this.entity = entity;
|
||||
this.allFields = allFields;
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public PacketPlayOutEntityMetadata(Entity entity) {
|
||||
this(entity, true);
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entity.getEntityId());
|
||||
Collection<WatchableObject> watches;
|
||||
if (allFields) {
|
||||
watches = new HashSet<>(entity.getDataWatcher().getWatchableObjects().values());
|
||||
} else {
|
||||
watches = new HashSet<>();
|
||||
Map<Field, WatchableObject> entries = entity.getDataWatcher().getWatchableObjects();
|
||||
for (Field field : fields) {
|
||||
WatchableObject watch = entries.get(field);
|
||||
if (watch != null) {
|
||||
watches.add(watch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<Integer, Integer> bitmasks = new HashMap<>();
|
||||
Iterator<WatchableObject> itr = watches.iterator();
|
||||
while (itr.hasNext()) {
|
||||
WatchableObject watch = itr.next();
|
||||
if (watch.isBitmask()) {
|
||||
itr.remove();
|
||||
Integer bitmask = bitmasks.get(watch.getIndex());
|
||||
if (bitmask == null) {
|
||||
bitmask = 0;
|
||||
}
|
||||
if ((boolean) watch.getValue()) {
|
||||
bitmask |= watch.getBitmask();
|
||||
} else {
|
||||
bitmask &= ~watch.getBitmask();
|
||||
}
|
||||
bitmasks.put(watch.getIndex(), bitmask);
|
||||
}
|
||||
}
|
||||
for (Entry<Integer, Integer> entry : bitmasks.entrySet()) {
|
||||
watches.add(new WatchableObject(entry.getValue().byteValue(), entry.getKey(), WatchableObjectType.BYTE));
|
||||
}
|
||||
|
||||
for (WatchableObject watch : watches) {
|
||||
output.writeByte(watch.getIndex());
|
||||
if (watch.isOptional()) {
|
||||
DataTypeIO.writeVarInt(output, watch.getType().getOptionalTypeId());
|
||||
output.writeBoolean(watch.getValue() != null);
|
||||
} else {
|
||||
DataTypeIO.writeVarInt(output, watch.getType().getTypeId());
|
||||
}
|
||||
if (!watch.isOptional() || watch.getValue() != null) {
|
||||
switch (watch.getType()) {
|
||||
//case BLOCKID:
|
||||
// break;
|
||||
case POSITION:
|
||||
DataTypeIO.writeBlockPosition(output, (BlockPosition) watch.getValue());
|
||||
break;
|
||||
case BOOLEAN:
|
||||
output.writeBoolean((boolean) watch.getValue());
|
||||
break;
|
||||
case BYTE:
|
||||
output.writeByte((byte) watch.getValue());
|
||||
break;
|
||||
case CHAT:
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize((Component) watch.getValue()), StandardCharsets.UTF_8);
|
||||
break;
|
||||
//case DIRECTION:
|
||||
// break;
|
||||
case FLOAT:
|
||||
output.writeFloat((float) watch.getValue());
|
||||
break;
|
||||
//case NBT:
|
||||
// break;
|
||||
//case PARTICLE:
|
||||
// break;
|
||||
case POSE:
|
||||
DataTypeIO.writeVarInt(output, ((Pose) watch.getValue()).getId());
|
||||
break;
|
||||
case ROTATION:
|
||||
Rotation3f rotation = (Rotation3f) watch.getValue();
|
||||
output.writeFloat((float) rotation.getX());
|
||||
output.writeFloat((float) rotation.getY());
|
||||
output.writeFloat((float) rotation.getZ());
|
||||
break;
|
||||
//case SLOT:
|
||||
// break;
|
||||
case STRING:
|
||||
DataTypeIO.writeString(output, watch.getValue().toString(), StandardCharsets.UTF_8);
|
||||
break;
|
||||
case UUID:
|
||||
DataTypeIO.writeUUID(output, (UUID) watch.getValue());
|
||||
break;
|
||||
case VARINT:
|
||||
DataTypeIO.writeVarInt(output, (int) watch.getValue());
|
||||
break;
|
||||
//case VILLAGER_DATA:
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
output.writeByte(END_OFF_METADATA);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutGameState extends PacketOut {
|
||||
|
||||
private int reason;
|
||||
private float value;
|
||||
|
||||
public PacketPlayOutGameState(int reason, float value) {
|
||||
this.reason = reason;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeByte(reason);
|
||||
output.writeFloat(value);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutHeldItemChange extends PacketOut {
|
||||
|
||||
private final byte slot;
|
||||
|
||||
public PacketPlayOutHeldItemChange(byte slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public byte getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeByte(slot);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutKeepAlive extends PacketOut {
|
||||
|
||||
private long payload;
|
||||
|
||||
public PacketPlayOutKeepAlive(long payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public long getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeLong(payload);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.GameMode;
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
import com.loohp.limbo.world.Environment;
|
||||
import com.loohp.limbo.world.World;
|
||||
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
import net.querz.nbt.tag.ListTag;
|
||||
|
||||
public class PacketPlayOutLogin extends PacketOut {
|
||||
|
||||
private int entityId;
|
||||
private boolean isHardcore;
|
||||
private GameMode gamemode;
|
||||
private List<World> worlds;
|
||||
private CompoundTag dimensionCodec;
|
||||
private Environment dimension;
|
||||
private World world;
|
||||
private long hashedSeed;
|
||||
private byte maxPlayers;
|
||||
private int viewDistance;
|
||||
private int simulationDistance;
|
||||
private boolean reducedDebugInfo;
|
||||
private boolean enableRespawnScreen;
|
||||
private boolean isDebug;
|
||||
private boolean isFlat;
|
||||
|
||||
public PacketPlayOutLogin(int entityId, boolean isHardcore, GameMode gamemode, List<World> worlds, CompoundTag dimensionCodec, World world, long hashedSeed, byte maxPlayers, int viewDistance, int simulationDistance, boolean reducedDebugInfo, boolean enableRespawnScreen, boolean isDebug, boolean isFlat) {
|
||||
this.entityId = entityId;
|
||||
this.isHardcore = isHardcore;
|
||||
this.gamemode = gamemode;
|
||||
this.worlds = worlds;
|
||||
this.dimensionCodec = dimensionCodec;
|
||||
this.dimension = world.getEnvironment();
|
||||
this.world = world;
|
||||
this.hashedSeed = hashedSeed;
|
||||
this.maxPlayers = maxPlayers;
|
||||
this.viewDistance = viewDistance;
|
||||
this.simulationDistance = simulationDistance;
|
||||
this.reducedDebugInfo = reducedDebugInfo;
|
||||
this.enableRespawnScreen = enableRespawnScreen;
|
||||
this.isDebug = isDebug;
|
||||
this.isFlat = isFlat;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public boolean isHardcore() {
|
||||
return isHardcore;
|
||||
}
|
||||
|
||||
public GameMode getGamemode() {
|
||||
return gamemode;
|
||||
}
|
||||
|
||||
public List<World> getWorldsNames() {
|
||||
return worlds;
|
||||
}
|
||||
|
||||
public CompoundTag getDimensionCodec() {
|
||||
return dimensionCodec;
|
||||
}
|
||||
|
||||
public Environment getDimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public long getHashedSeed() {
|
||||
return hashedSeed;
|
||||
}
|
||||
|
||||
public byte getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public int getViewDistance() {
|
||||
return viewDistance;
|
||||
}
|
||||
|
||||
public int getSimulationDistance() {
|
||||
return simulationDistance;
|
||||
}
|
||||
|
||||
public boolean isReducedDebugInfo() {
|
||||
return reducedDebugInfo;
|
||||
}
|
||||
|
||||
public boolean isEnableRespawnScreen() {
|
||||
return enableRespawnScreen;
|
||||
}
|
||||
|
||||
public boolean isDebug() {
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
return isFlat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeInt(entityId);
|
||||
output.writeBoolean(isHardcore);
|
||||
output.writeByte((byte) gamemode.getId());
|
||||
output.writeByte((byte) gamemode.getId());
|
||||
DataTypeIO.writeVarInt(output, worlds.size());
|
||||
for (int u = 0; u < worlds.size(); u++) {
|
||||
DataTypeIO.writeString(output, new NamespacedKey(worlds.get(u).getName()).toString(), StandardCharsets.UTF_8);
|
||||
}
|
||||
DataTypeIO.writeCompoundTag(output, dimensionCodec);
|
||||
CompoundTag tag = null;
|
||||
ListTag<CompoundTag> list = dimensionCodec.getCompoundTag("minecraft:dimension_type").getListTag("value").asCompoundTagList();
|
||||
for (CompoundTag each : list) {
|
||||
if (each.getString("name").equals(dimension.getNamespacedKey().toString())) {
|
||||
tag = each.getCompoundTag("element");
|
||||
break;
|
||||
}
|
||||
}
|
||||
DataTypeIO.writeCompoundTag(output, tag != null ? tag : list.get(0).getCompoundTag("element"));
|
||||
DataTypeIO.writeString(output, new NamespacedKey(world.getName()).toString(), StandardCharsets.UTF_8);
|
||||
output.writeLong(hashedSeed);
|
||||
DataTypeIO.writeVarInt(output, maxPlayers);
|
||||
DataTypeIO.writeVarInt(output, viewDistance);
|
||||
DataTypeIO.writeVarInt(output, simulationDistance);
|
||||
output.writeBoolean(reducedDebugInfo);
|
||||
output.writeBoolean(enableRespawnScreen);
|
||||
output.writeBoolean(isDebug);
|
||||
output.writeBoolean(isFlat);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutPlayerAbilities extends PacketOut {
|
||||
|
||||
public enum PlayerAbilityFlags {
|
||||
INVULNERABLE(0x01),
|
||||
FLY(0x02),
|
||||
ALLOW_FLYING(0x04),
|
||||
CREATIVE(0x08);
|
||||
|
||||
int bitvalue;
|
||||
|
||||
PlayerAbilityFlags(int bitvalue) {
|
||||
this.bitvalue = bitvalue;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return bitvalue;
|
||||
}
|
||||
}
|
||||
|
||||
private PlayerAbilityFlags[] flags;
|
||||
private float flySpeed;
|
||||
private float fieldOfField;
|
||||
|
||||
public PacketPlayOutPlayerAbilities(float flySpeed, float fieldOfField, PlayerAbilityFlags... flags) {
|
||||
this.flags = flags;
|
||||
this.flySpeed = flySpeed;
|
||||
this.fieldOfField = fieldOfField;
|
||||
}
|
||||
|
||||
public PlayerAbilityFlags[] getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public float getFlySpeed() {
|
||||
return flySpeed;
|
||||
}
|
||||
|
||||
public float getFieldOfField() {
|
||||
return fieldOfField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
int value = 0;
|
||||
for (PlayerAbilityFlags flag : flags) {
|
||||
value = value | flag.getValue();
|
||||
}
|
||||
|
||||
output.writeByte(value);
|
||||
output.writeFloat(flySpeed);
|
||||
output.writeFloat(fieldOfField);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.GameMode;
|
||||
|
||||
public class PacketPlayOutPlayerInfo extends PacketOut {
|
||||
|
||||
public enum PlayerInfoAction {
|
||||
ADD_PLAYER(0), UPDATE_GAMEMODE(1), UPDATE_LATENCY(2), UPDATE_DISPLAY_NAME(3), REMOVE_PLAYER(4);
|
||||
|
||||
int id;
|
||||
|
||||
PlayerInfoAction(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
private PlayerInfoAction action;
|
||||
private UUID uuid;
|
||||
private PlayerInfoData data;
|
||||
|
||||
public PacketPlayOutPlayerInfo(PlayerInfoAction action, UUID uuid, PlayerInfoData data) {
|
||||
this.action = action;
|
||||
this.uuid = uuid;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public PlayerInfoAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public PlayerInfoData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, action.getId());
|
||||
DataTypeIO.writeVarInt(output, 1);
|
||||
DataTypeIO.writeUUID(output, uuid);
|
||||
|
||||
switch (action) {
|
||||
case ADD_PLAYER:
|
||||
PlayerInfoDataAddPlayer data = (PlayerInfoDataAddPlayer) this.data;
|
||||
DataTypeIO.writeString(output, data.getName(), StandardCharsets.UTF_8);
|
||||
if (data.getProperty().isPresent()) {
|
||||
DataTypeIO.writeVarInt(output, 1);
|
||||
DataTypeIO.writeString(output, "textures", StandardCharsets.UTF_8);
|
||||
DataTypeIO.writeString(output, data.getProperty().get().getSkin(), StandardCharsets.UTF_8);
|
||||
output.writeBoolean(true);
|
||||
DataTypeIO.writeString(output, data.getProperty().get().getSignature(), StandardCharsets.UTF_8);
|
||||
} else {
|
||||
DataTypeIO.writeVarInt(output, 0);
|
||||
}
|
||||
DataTypeIO.writeVarInt(output, data.getGamemode().getId());
|
||||
DataTypeIO.writeVarInt(output, data.getPing());
|
||||
if (data.getDisplayNameJson().isPresent()) {
|
||||
output.writeBoolean(true);
|
||||
DataTypeIO.writeString(output, data.getDisplayNameJson().get(), StandardCharsets.UTF_8);
|
||||
} else {
|
||||
output.writeBoolean(false);
|
||||
}
|
||||
break;
|
||||
case REMOVE_PLAYER:
|
||||
break;
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
break;
|
||||
case UPDATE_GAMEMODE:
|
||||
break;
|
||||
case UPDATE_LATENCY:
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
// =========
|
||||
|
||||
public static class PlayerInfoData {
|
||||
|
||||
public static class PlayerInfoDataAddPlayer extends PlayerInfoData {
|
||||
|
||||
private String name;
|
||||
private Optional<PlayerSkinProperty> skin;
|
||||
private GameMode gamemode;
|
||||
private int ping;
|
||||
private boolean hasDisplayName;
|
||||
private Optional<String> displayNameJson;
|
||||
|
||||
public PlayerInfoDataAddPlayer(String name, Optional<PlayerSkinProperty> skin, GameMode gamemode, int ping,
|
||||
boolean hasDisplayName, Optional<String> displayNameJson) {
|
||||
this.name = name;
|
||||
this.skin = skin;
|
||||
this.gamemode = gamemode;
|
||||
this.ping = ping;
|
||||
this.hasDisplayName = hasDisplayName;
|
||||
this.displayNameJson = displayNameJson;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Optional<PlayerSkinProperty> getProperty() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
public GameMode getGamemode() {
|
||||
return gamemode;
|
||||
}
|
||||
|
||||
public int getPing() {
|
||||
return ping;
|
||||
}
|
||||
|
||||
public boolean isHasDisplayName() {
|
||||
return hasDisplayName;
|
||||
}
|
||||
|
||||
public Optional<String> getDisplayNameJson() {
|
||||
return displayNameJson;
|
||||
}
|
||||
|
||||
public static class PlayerSkinProperty {
|
||||
|
||||
private String skin;
|
||||
private String signature;
|
||||
|
||||
public PlayerSkinProperty(String skin, String signature) {
|
||||
this.skin = skin;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public String getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketPlayOutPlayerListHeaderFooter extends PacketOut{
|
||||
|
||||
private Component header;
|
||||
private Component footer;
|
||||
|
||||
public PacketPlayOutPlayerListHeaderFooter(Component header, Component footer) {
|
||||
this.header = header;
|
||||
this.footer = footer;
|
||||
}
|
||||
|
||||
public Component getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public Component getFooter() {
|
||||
return footer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(header), StandardCharsets.UTF_8);
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(footer), StandardCharsets.UTF_8);
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
|
||||
public class PacketPlayOutPluginMessaging extends PacketOut {
|
||||
|
||||
private NamespacedKey channel;
|
||||
private byte[] data;
|
||||
|
||||
public PacketPlayOutPluginMessaging(NamespacedKey channel, byte[] data) {
|
||||
this.channel = channel;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public NamespacedKey getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, channel.toString(), StandardCharsets.UTF_8);
|
||||
output.write(data);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutPositionAndLook extends PacketOut {
|
||||
|
||||
public enum PlayerTeleportFlags {
|
||||
X((byte) 0x01),
|
||||
Y((byte) 0x02),
|
||||
Z((byte) 0x04),
|
||||
Y_ROT((byte) 0x08),
|
||||
X_ROT((byte) 0x10);
|
||||
|
||||
byte bit;
|
||||
|
||||
PlayerTeleportFlags(byte bit) {
|
||||
this.bit = bit;
|
||||
}
|
||||
|
||||
public byte getBit() {
|
||||
return bit;
|
||||
}
|
||||
}
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private Set<PlayerTeleportFlags> flags;
|
||||
private int teleportId;
|
||||
private boolean dismountVehicle;
|
||||
|
||||
public PacketPlayOutPositionAndLook(double x, double y, double z, float yaw, float pitch, int teleportId, boolean dismountVehicle, PlayerTeleportFlags... flags) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.teleportId = teleportId;
|
||||
this.flags = Arrays.asList(flags).stream().collect(Collectors.toSet());
|
||||
this.dismountVehicle = dismountVehicle;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public Set<PlayerTeleportFlags> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public int getTeleportId() {
|
||||
return teleportId;
|
||||
}
|
||||
|
||||
public boolean isDismountVehicle() {
|
||||
return dismountVehicle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeDouble(x);
|
||||
output.writeDouble(y);
|
||||
output.writeDouble(z);
|
||||
output.writeFloat(yaw);
|
||||
output.writeFloat(pitch);
|
||||
|
||||
byte flag = 0;
|
||||
for (PlayerTeleportFlags each : flags) {
|
||||
flag = (byte) (flag | each.getBit());
|
||||
}
|
||||
|
||||
output.writeByte(flag);
|
||||
DataTypeIO.writeVarInt(output, teleportId);
|
||||
output.writeBoolean(dismountVehicle);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketPlayOutResourcePackSend extends PacketOut {
|
||||
|
||||
public static final int MAX_HASH_LENGTH = 40;
|
||||
|
||||
private String url;
|
||||
private String hash;
|
||||
private boolean isForced;
|
||||
private boolean hasPromptMessage;
|
||||
private Component promptMessage;
|
||||
|
||||
public PacketPlayOutResourcePackSend(String url, String hash, boolean isForced, boolean hasPromptMessage, Component promptMessage) {
|
||||
if (hash.length() > MAX_HASH_LENGTH) {
|
||||
throw new IllegalArgumentException("Hash is too long (max " + MAX_HASH_LENGTH + ", was " + hash.length() + ")");
|
||||
}
|
||||
this.url = url;
|
||||
this.hash = hash;
|
||||
this.isForced = isForced;
|
||||
this.hasPromptMessage = hasPromptMessage;
|
||||
if (hasPromptMessage && promptMessage == null) {
|
||||
throw new IllegalArgumentException("promptMessage cannot be null when hasPromptMessage is true");
|
||||
}
|
||||
this.promptMessage = promptMessage;
|
||||
}
|
||||
|
||||
public String getURL() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public boolean isForced() {
|
||||
return isForced;
|
||||
}
|
||||
|
||||
public boolean hasPromptMessage() {
|
||||
return hasPromptMessage;
|
||||
}
|
||||
|
||||
public Component getPromptMessage() {
|
||||
return promptMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, url, StandardCharsets.UTF_8);
|
||||
DataTypeIO.writeString(output, hash, StandardCharsets.UTF_8);
|
||||
output.writeBoolean(isForced);
|
||||
output.writeBoolean(hasPromptMessage);
|
||||
if (hasPromptMessage) {
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(promptMessage), StandardCharsets.UTF_8);
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.utils.GameMode;
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
import com.loohp.limbo.world.Environment;
|
||||
import com.loohp.limbo.world.World;
|
||||
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
import net.querz.nbt.tag.ListTag;
|
||||
|
||||
public class PacketPlayOutRespawn extends PacketOut {
|
||||
|
||||
private Environment dimension;
|
||||
private String worldName;
|
||||
private CompoundTag dimensionCodec;
|
||||
private long hashedSeed;
|
||||
private GameMode gamemode;
|
||||
private boolean isDebug;
|
||||
private boolean isFlat;
|
||||
private boolean copyMetaData;
|
||||
|
||||
public PacketPlayOutRespawn(World world, CompoundTag dimensionCodec, long hashedSeed, GameMode gamemode, boolean isDebug, boolean isFlat, boolean copyMetaData) {
|
||||
this.dimension = world.getEnvironment();
|
||||
this.dimensionCodec = dimensionCodec;
|
||||
this.worldName = new NamespacedKey(world.getName()).toString();
|
||||
this.hashedSeed = hashedSeed;
|
||||
this.gamemode = gamemode;
|
||||
this.isDebug = isDebug;
|
||||
this.isFlat = isFlat;
|
||||
this.copyMetaData = copyMetaData;
|
||||
}
|
||||
|
||||
public CompoundTag getDimensionCodec() {
|
||||
return dimensionCodec;
|
||||
}
|
||||
|
||||
public Environment getDimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public long getHashedSeed() {
|
||||
return hashedSeed;
|
||||
}
|
||||
|
||||
public GameMode getGamemode() {
|
||||
return gamemode;
|
||||
}
|
||||
|
||||
public boolean isDebug() {
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
return isFlat;
|
||||
}
|
||||
|
||||
public boolean isCopyMetaData() {
|
||||
return copyMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
CompoundTag tag = null;
|
||||
ListTag<CompoundTag> list = dimensionCodec.getCompoundTag("minecraft:dimension_type").getListTag("value").asCompoundTagList();
|
||||
for (CompoundTag each : list) {
|
||||
if (each.getString("name").equals(dimension.getNamespacedKey().toString())) {
|
||||
tag = each.getCompoundTag("element");
|
||||
break;
|
||||
}
|
||||
}
|
||||
DataTypeIO.writeCompoundTag(output, tag != null ? tag : list.get(0));
|
||||
DataTypeIO.writeString(output, worldName, StandardCharsets.UTF_8);
|
||||
output.writeLong(hashedSeed);
|
||||
output.writeByte((byte) gamemode.getId());
|
||||
output.writeByte((byte) gamemode.getId());
|
||||
output.writeBoolean(isDebug);
|
||||
output.writeBoolean(isFlat);
|
||||
output.writeBoolean(copyMetaData);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.entity.EntityType;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutSpawnEntity extends PacketOut {
|
||||
|
||||
private int entityId;
|
||||
private UUID uuid;
|
||||
private EntityType type;
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float pitch;
|
||||
private float yaw;
|
||||
private int data;
|
||||
private short velocityX;
|
||||
private short velocityY;
|
||||
private short velocityZ;
|
||||
|
||||
public PacketPlayOutSpawnEntity(int entityId, UUID uuid, EntityType type, double x, double y, double z, float pitch, float yaw, short velocityX, short velocityY, short velocityZ) {
|
||||
this.entityId = entityId;
|
||||
this.uuid = uuid;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
this.data = 0; //TO-DO
|
||||
this.velocityX = velocityX;
|
||||
this.velocityY = velocityY;
|
||||
this.velocityZ = velocityZ;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public EntityType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public short getVelocityX() {
|
||||
return velocityX;
|
||||
}
|
||||
|
||||
public short getVelocityY() {
|
||||
return velocityY;
|
||||
}
|
||||
|
||||
public short getVelocityZ() {
|
||||
return velocityZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entityId);
|
||||
DataTypeIO.writeUUID(output, uuid);
|
||||
DataTypeIO.writeVarInt(output, type.getTypeId());
|
||||
output.writeDouble(x);
|
||||
output.writeDouble(y);
|
||||
output.writeDouble(z);
|
||||
output.writeByte((byte) (int) (pitch * 256.0F / 360.0F));
|
||||
output.writeByte((byte) (int) (yaw * 256.0F / 360.0F));
|
||||
output.writeInt(data);
|
||||
output.writeShort((int) (velocityX * 8000));
|
||||
output.writeShort((int) (velocityY * 8000));
|
||||
output.writeShort((int) (velocityZ * 8000));
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.loohp.limbo.entity.EntityType;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutSpawnEntityLiving extends PacketOut {
|
||||
|
||||
private int entityId;
|
||||
private UUID uuid;
|
||||
private EntityType type;
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
private float headPitch;
|
||||
private short velocityX;
|
||||
private short velocityY;
|
||||
private short velocityZ;
|
||||
|
||||
public PacketPlayOutSpawnEntityLiving(int entityId, UUID uuid, EntityType type, double x, double y, double z, float yaw, float pitch, float headPitch, short velocityX, short velocityY, short velocityZ) {
|
||||
this.entityId = entityId;
|
||||
this.uuid = uuid;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.headPitch = headPitch;
|
||||
this.velocityX = velocityX;
|
||||
this.velocityY = velocityY;
|
||||
this.velocityZ = velocityZ;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public EntityType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public float getHeadPitch() {
|
||||
return headPitch;
|
||||
}
|
||||
|
||||
public short getVelocityX() {
|
||||
return velocityX;
|
||||
}
|
||||
|
||||
public short getVelocityY() {
|
||||
return velocityY;
|
||||
}
|
||||
|
||||
public short getVelocityZ() {
|
||||
return velocityZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, entityId);
|
||||
DataTypeIO.writeUUID(output, uuid);
|
||||
DataTypeIO.writeVarInt(output, type.getTypeId());
|
||||
output.writeDouble(x);
|
||||
output.writeDouble(y);
|
||||
output.writeDouble(z);
|
||||
output.writeByte((byte) (int) (yaw * 256.0F / 360.0F));
|
||||
output.writeByte((byte) (int) (pitch * 256.0F / 360.0F));
|
||||
output.writeByte((byte) (int) (headPitch * 256.0F / 360.0F));
|
||||
output.writeShort((int) (velocityX * 8000));
|
||||
output.writeShort((int) (velocityY * 8000));
|
||||
output.writeShort((int) (velocityZ * 8000));
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.world.BlockPosition;
|
||||
|
||||
public class PacketPlayOutSpawnPosition extends PacketOut {
|
||||
|
||||
private BlockPosition position;
|
||||
private float angle;
|
||||
|
||||
public PacketPlayOutSpawnPosition(BlockPosition position, float angle) {
|
||||
this.position = position;
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
public BlockPosition getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public float getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeBlockPosition(output, position);
|
||||
output.writeFloat(angle);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
public class PacketPlayOutTabComplete extends PacketOut {
|
||||
|
||||
private int id;
|
||||
private int start;
|
||||
private int length;
|
||||
private TabCompleteMatches[] matches;
|
||||
|
||||
public PacketPlayOutTabComplete(int id, int start, int length, TabCompleteMatches... matches) {
|
||||
this.id = id;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
this.matches = matches;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public TabCompleteMatches[] getMatches() {
|
||||
return matches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, id);
|
||||
DataTypeIO.writeVarInt(output, start);
|
||||
DataTypeIO.writeVarInt(output, length);
|
||||
DataTypeIO.writeVarInt(output, matches.length);
|
||||
|
||||
for (TabCompleteMatches match : matches) {
|
||||
DataTypeIO.writeString(output, match.getMatch(), StandardCharsets.UTF_8);
|
||||
if (match.getTooltip().isPresent()) {
|
||||
output.writeBoolean(true);
|
||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(match.getTooltip().get()), StandardCharsets.UTF_8);
|
||||
} else {
|
||||
output.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
public static class TabCompleteMatches {
|
||||
|
||||
private String match;
|
||||
private Optional<Component> tooltip;
|
||||
|
||||
public TabCompleteMatches(String match) {
|
||||
this.match = match;
|
||||
this.tooltip = Optional.empty();
|
||||
}
|
||||
|
||||
public TabCompleteMatches(String match, Component tooltip) {
|
||||
this.match = match;
|
||||
this.tooltip = Optional.ofNullable(tooltip);
|
||||
}
|
||||
|
||||
public String getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
public Optional<Component> getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayOutUnloadChunk extends PacketOut {
|
||||
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
|
||||
public PacketPlayOutUnloadChunk(int chunkX, int chunkZ) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
public int getChunkX() {
|
||||
return chunkX;
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
output.writeInt(chunkX);
|
||||
output.writeInt(chunkZ);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketPlayOutUpdateViewPosition extends PacketOut {
|
||||
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
|
||||
public PacketPlayOutUpdateViewPosition(int chunkX, int chunkZ) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
public int getChunkX() {
|
||||
return chunkX;
|
||||
}
|
||||
|
||||
public int getChunkZ() {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||
DataTypeIO.writeVarInt(output, chunkX);
|
||||
DataTypeIO.writeVarInt(output, chunkZ);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketStatusInPing extends PacketIn {
|
||||
|
||||
private long payload;
|
||||
|
||||
public PacketStatusInPing(long payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public PacketStatusInPing(DataInputStream in) throws IOException {
|
||||
this(in.readLong());
|
||||
}
|
||||
|
||||
public long getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
|
||||
public class PacketStatusInRequest extends PacketIn {
|
||||
|
||||
public PacketStatusInRequest() {
|
||||
|
||||
}
|
||||
|
||||
public PacketStatusInRequest(DataInputStream in) {
|
||||
this();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketStatusOutPong extends PacketOut {
|
||||
|
||||
private long payload;
|
||||
|
||||
public PacketStatusOutPong(long payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public long getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getStatusOut().get(getClass()));
|
||||
output.writeLong(payload);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
public class PacketStatusOutResponse extends PacketOut {
|
||||
|
||||
private String json;
|
||||
|
||||
public PacketStatusOutResponse(String json) {
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public String getJson() {
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializePacket() throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
DataOutputStream output = new DataOutputStream(buffer);
|
||||
output.writeByte(Packet.getStatusOut().get(getClass()));
|
||||
DataTypeIO.writeString(output, json, StandardCharsets.UTF_8);
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user