carpet client synchronizations and protocols

This commit is contained in:
gnembon committed 2020-05-28 00:06:28 -03:00
1 parent 2522884da3
commit e540f9e238
19 files changed
+406 -173

No files matched your search

@@ -0,0 +1,52 @@
package carpet.network;
import carpet.CarpetServer;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.util.Identifier;
public class CarpetClient
{
public static final Object sync = new Object();
public static final int HI = 69;
public static final int HELLO = 420;
public static final int DATA = 1;
private static ClientPlayerEntity clientPlayer = null;
private static boolean isServerCarpet = false;
public static String serverCarpetVersion;
public static final Identifier CARPET_CHANNEL = new Identifier("carpet:hello");
public static void gameJoined(ClientPlayerEntity player)
{
synchronized (sync)
{
clientPlayer = player;
// client didn't say hi back yet
if (isServerCarpet)
ClientNetworkHandler.respondHello();
}
}
public static void disconnect()
{
isServerCarpet = false;
clientPlayer = null;
CarpetServer.disconnect();
}
public static void setCarpet()
{
isServerCarpet = true;
}
public static ClientPlayerEntity getPlayer()
{
return clientPlayer;
}
public static boolean isCarpet()
{
return isServerCarpet;
}
}
@@ -0,0 +1,93 @@
package carpet.network;
import carpet.CarpetServer;
import carpet.CarpetSettings;
import carpet.helpers.TickSpeed;
import carpet.settings.ParsedRule;
import io.netty.buffer.Unpooled;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.nbt.AbstractNumberTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket;
import net.minecraft.util.PacketByteBuf;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class ClientNetworkHandler
{
private static Map<String, BiConsumer<ClientPlayerEntity, Tag>> dataHandlers = new HashMap<String, BiConsumer<ClientPlayerEntity, Tag>>(){{
put("Rules", (p, t) -> {
CompoundTag ruleset = (CompoundTag)t;
for (String ruleName: ruleset.getKeys())
{
ParsedRule<?> rule = CarpetServer.settingsManager.getRule(ruleName);
if (rule == null)
CarpetSettings.LOG.error("Received unknown rule: "+ruleName);
else
{
CompoundTag ruleNBT = (CompoundTag) ruleset.get(ruleName);
String value = ruleNBT.getString("Value");
rule.set(null, value);
}
}
});
put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false));
}};
public static void handleData(PacketByteBuf data, ClientPlayerEntity player)
{
if (data != null)
{
int id = data.readVarInt();
if (id == CarpetClient.HI)
onHi(data);
if (id == CarpetClient.DATA)
onSyncData(data, player);
}
}
private static void onHi(PacketByteBuf data)
{
synchronized (CarpetClient.sync)
{
CarpetClient.setCarpet();
CarpetClient.serverCarpetVersion = data.readString(64);
if (CarpetSettings.carpetVersion.equals(CarpetClient.serverCarpetVersion))
{
CarpetSettings.LOG.info("Joined carpet server with matching carpet version");
}
else
{
CarpetSettings.LOG.warn("Joined carpet server with another carpet version: "+CarpetClient.serverCarpetVersion);
}
if (CarpetClient.getPlayer() != null)
respondHello();
}
}
public static void respondHello()
{
CarpetClient.getPlayer().networkHandler.sendPacket(new CustomPayloadC2SPacket(
CarpetClient.CARPET_CHANNEL,
(new PacketByteBuf(Unpooled.buffer())).writeVarInt(CarpetClient.HELLO).writeString(CarpetSettings.carpetVersion)
));
}
private static void onSyncData(PacketByteBuf data, ClientPlayerEntity player)
{
CompoundTag compound = data.readCompoundTag();
if (compound == null) return;
for (String key: compound.getKeys())
{
if (dataHandlers.containsKey(key))
dataHandlers.get(key).accept(player, compound.get(key));
else
CarpetSettings.LOG.error("Unknown carpet data: "+key);
}
}
}
@@ -0,0 +1,123 @@
package carpet.network;
import carpet.CarpetServer;
import carpet.CarpetSettings;
import carpet.helpers.TickSpeed;
import carpet.settings.ParsedRule;
import io.netty.buffer.Unpooled;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.PacketByteBuf;
import java.util.ArrayList;
import java.util.List;
public class ServerNetworkHandler
{
private static List<ServerPlayerEntity> carpetPlayers = new ArrayList<>();
public static void handleData(PacketByteBuf data, ServerPlayerEntity player)
{
if (data != null)
{
int id = data.readVarInt();
if (id == CarpetClient.HELLO)
onHello(player, data);
}
}
public static void onPlayerJoin(ServerPlayerEntity playerEntity)
{
if (!playerEntity.networkHandler.connection.isLocal())
{
playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(
CarpetClient.CARPET_CHANNEL,
(new PacketByteBuf(Unpooled.buffer())).writeVarInt(CarpetClient.HI).writeString(CarpetSettings.carpetVersion)
));
}
}
public static void onHello(ServerPlayerEntity playerEntity, PacketByteBuf packetData)
{
carpetPlayers.add(playerEntity);
String clientVersion = packetData.readString(64);
if (clientVersion.equals(CarpetSettings.carpetVersion))
CarpetSettings.LOG.info("Player "+playerEntity.getName().getString()+" joined with a matching carpet client");
else
CarpetSettings.LOG.warn("Player "+playerEntity.getName().getString()+" joined with another carpet version: "+clientVersion);
DataBuilder data = DataBuilder.create().withTickRate();
CarpetServer.settingsManager.getRules().forEach(data::withRule);
playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetClient.CARPET_CHANNEL, data.build() ));
}
public static void updateRuleWithConnectedClients(ParsedRule<?> rule)
{
for (ServerPlayerEntity player : carpetPlayers)
{
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(
CarpetClient.CARPET_CHANNEL,
DataBuilder.create().withRule(rule).build()
));
}
}
public static void updateTickSpeedToConnectedPlayers()
{
for (ServerPlayerEntity player : carpetPlayers)
{
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(
CarpetClient.CARPET_CHANNEL,
DataBuilder.create().withTickRate().build()
));
}
}
public static void onPlayerLoggedOut(ServerPlayerEntity player)
{
if (!player.networkHandler.connection.isLocal())
carpetPlayers.remove(player);
}
public static void close()
{
carpetPlayers.clear();
}
private static class DataBuilder
{
private CompoundTag tag;
private static DataBuilder create()
{
return new DataBuilder();
}
private DataBuilder()
{
tag = new CompoundTag();
}
private DataBuilder withTickRate()
{
tag.putFloat("TickRate", TickSpeed.tickrate);
return this;
}
private DataBuilder withRule(ParsedRule<?> rule)
{
CompoundTag rules = (CompoundTag) tag.get("Rules");
if (rules == null)
{
rules = new CompoundTag();
tag.put("Rules", rules);
}
CompoundTag ruleNBT = new CompoundTag();
ruleNBT.putString("Value", rule.getAsString());
rules.put(rule.name, ruleNBT);
return this;
}
private PacketByteBuf build()
{
PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.buffer());
packetBuf.writeVarInt(CarpetClient.DATA);
packetBuf.writeCompoundTag(tag);
return packetBuf;
}
}
}