carpet client synchronizations and protocols
This commit is contained in:
1 parent
2522884da3
commit
e540f9e238
19 files changed
+406
-173
No files matched your search
@@ -6,7 +6,7 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import carpet.commands.*;
|
||||
import carpet.helpers.ServerNetworkHandler;
|
||||
import carpet.network.ServerNetworkHandler;
|
||||
import carpet.helpers.TickSpeed;
|
||||
import carpet.logging.LoggerRegistry;
|
||||
import carpet.script.CarpetScriptServer;
|
||||
@@ -18,7 +18,6 @@ import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class CarpetServer // static for now - easier to handle all around the code, its one anyways
|
||||
{
|
||||
@@ -28,7 +27,6 @@ public class CarpetServer // static for now - easier to handle all around the co
|
||||
public static CarpetScriptServer scriptServer;
|
||||
public static SettingsManager settingsManager;
|
||||
public static final List<CarpetExtension> extensions = new ArrayList<>();
|
||||
public static final Identifier CARPET_CHANNEL = new Identifier("carpet:info");
|
||||
|
||||
// Separate from onServerLoaded, because a server can be loaded multiple times in singleplayer
|
||||
public static void manageExtension(CarpetExtension extension)
|
||||
@@ -48,9 +46,6 @@ public class CarpetServer // static for now - easier to handle all around the co
|
||||
settingsManager = new SettingsManager(CarpetSettings.carpetVersion, "carpet", "Carpet Mod");
|
||||
settingsManager.parseSettingsClass(CarpetSettings.class);
|
||||
extensions.forEach(CarpetExtension::onGameStarted);
|
||||
CarpetServer.settingsManager.addRuleObserver((source, parsedRule, s) -> {
|
||||
ServerNetworkHandler.sendUpdateToClient(parsedRule.name, parsedRule.getAsString(), source);
|
||||
});
|
||||
}
|
||||
|
||||
public static void onServerLoaded(MinecraftServer server)
|
||||
@@ -66,6 +61,7 @@ public class CarpetServer // static for now - easier to handle all around the co
|
||||
scriptServer.loadAllWorldScripts();
|
||||
MobAI.resetTrackers();
|
||||
LoggerRegistry.initLoggers();
|
||||
//TickSpeed.reset();
|
||||
}
|
||||
|
||||
public static void tick(MinecraftServer server)
|
||||
@@ -108,31 +104,41 @@ public class CarpetServer // static for now - easier to handle all around the co
|
||||
|
||||
public static void onPlayerLoggedIn(ServerPlayerEntity player)
|
||||
{
|
||||
ServerNetworkHandler.onPlayerJoin(player);
|
||||
LoggerRegistry.playerConnected(player);
|
||||
extensions.forEach(e -> e.onPlayerLoggedIn(player));
|
||||
ServerNetworkHandler.onPlayerJoin(player);
|
||||
|
||||
}
|
||||
|
||||
public static void onPlayerLoggedOut(ServerPlayerEntity player)
|
||||
{
|
||||
ServerNetworkHandler.onPlayerLoggedOut(player);
|
||||
LoggerRegistry.playerDisconnected(player);
|
||||
extensions.forEach(e -> e.onPlayerLoggedOut(player));
|
||||
}
|
||||
|
||||
public static void onServerClosed(MinecraftServer server)
|
||||
{
|
||||
ServerNetworkHandler.close();
|
||||
currentCommandDispatcher = null;
|
||||
if (scriptServer != null) scriptServer.onClose();
|
||||
settingsManager.detachServer();
|
||||
|
||||
LoggerRegistry.stopLoggers();
|
||||
TickSpeed.reset();
|
||||
extensions.forEach(e -> e.onServerClosed(server));
|
||||
minecraft_server = null;
|
||||
disconnect();
|
||||
}
|
||||
|
||||
public static void registerExtensionLoggers()
|
||||
{
|
||||
extensions.forEach(CarpetExtension::registerLoggers);
|
||||
}
|
||||
|
||||
public static void disconnect()
|
||||
{
|
||||
// this for whatever reason gets called multiple times even when joining;
|
||||
TickSpeed.reset();
|
||||
settingsManager.detachServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class CarpetSettings
|
||||
|
||||
private static class LanguageValidator extends Validator<String> {
|
||||
@Override public String validate(ServerCommandSource source, ParsedRule<String> currentRule, String newValue, String string) {
|
||||
if (currentRule.get().equals(newValue))
|
||||
if (currentRule.get().equals(newValue) || source == null)
|
||||
{
|
||||
return newValue;
|
||||
}
|
||||
@@ -487,7 +487,7 @@ public class CarpetSettings
|
||||
{
|
||||
@Override public Integer validate(ServerCommandSource source, ParsedRule<Integer> currentRule, Integer newValue, String string)
|
||||
{
|
||||
if (currentRule.get().equals(newValue))
|
||||
if (currentRule.get().equals(newValue) || source == null)
|
||||
{
|
||||
return newValue;
|
||||
}
|
||||
@@ -538,6 +538,7 @@ public class CarpetSettings
|
||||
}
|
||||
}
|
||||
@Override public Integer validate(ServerCommandSource source, ParsedRule<Integer> currentRule, Integer newValue, String string) {
|
||||
if (source == null) return newValue;
|
||||
if (newValue < 0 || newValue > 32)
|
||||
{
|
||||
Messenger.m(source, "r spawn chunk size has to be between 0 and 32");
|
||||
|
||||
@@ -67,7 +67,7 @@ public class TickCommand
|
||||
|
||||
private static int setTps(ServerCommandSource source, float tps)
|
||||
{
|
||||
TickSpeed.tickrate(tps);
|
||||
TickSpeed.tickrate(tps, true);
|
||||
queryTps(source);
|
||||
return (int)tps;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package carpet.fakes;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
public interface CustomPayloadC2SPacketInterface
|
||||
{
|
||||
Identifier getPacketChannel();
|
||||
PacketByteBuf getPacketData();
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package carpet.helpers;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.settings.ParsedRule;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
public class ClientNetworkHandler
|
||||
{
|
||||
public static void handleData(Identifier channel, PacketByteBuf data)
|
||||
{
|
||||
if (CarpetServer.CARPET_CHANNEL.equals(channel) && data != null)
|
||||
{
|
||||
int id = data.readVarInt();
|
||||
|
||||
if (id == 1)
|
||||
setOnJoinInfo(data);
|
||||
else if (id == 2)
|
||||
updateRule(data);
|
||||
else if (id == 3)
|
||||
updateTickRateClient(data);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setOnJoinInfo(PacketByteBuf data)
|
||||
{
|
||||
CompoundTag compound = data.readCompoundTag();
|
||||
if (compound == null) return;
|
||||
|
||||
TickSpeed.tickrate(compound.getFloat("Tickrate"));
|
||||
|
||||
ListTag rulesList = compound.getList("rules", 10);
|
||||
for (Tag tag : rulesList)
|
||||
{
|
||||
CompoundTag ruleNBT = (CompoundTag) tag;
|
||||
String rule = ruleNBT.getString("rule");
|
||||
String value = ruleNBT.getString("value");
|
||||
CarpetServer.settingsManager.getRule(rule).set(null, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateRule(PacketByteBuf data)
|
||||
{
|
||||
String rule = data.readString();
|
||||
String newValue = data.readString();
|
||||
CarpetServer.settingsManager.getRule(rule).set(null, newValue);
|
||||
}
|
||||
|
||||
private static void updateTickRateClient(PacketByteBuf data)
|
||||
{
|
||||
float rate = data.readFloat();
|
||||
TickSpeed.tickrate(rate);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package carpet.helpers;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.settings.ParsedRule;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
public class ServerNetworkHandler
|
||||
{
|
||||
public static void onPlayerJoin(ServerPlayerEntity playerEntity)
|
||||
{
|
||||
CompoundTag data = new CompoundTag();
|
||||
|
||||
data.putFloat("Tickrate", TickSpeed.tickrate);
|
||||
|
||||
ListTag rulesList = new ListTag();
|
||||
for (ParsedRule<?> rule : CarpetServer.settingsManager.getRules())
|
||||
{
|
||||
CompoundTag ruleNBT = new CompoundTag();
|
||||
|
||||
ruleNBT.putString("rule" ,rule.name);
|
||||
ruleNBT.putString("value", rule.getAsString());
|
||||
ruleNBT.putString("default", rule.defaultAsString);
|
||||
rulesList.add(ruleNBT);
|
||||
}
|
||||
data.put("rules", rulesList);
|
||||
PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.buffer());
|
||||
packetBuf.writeVarInt(1);
|
||||
packetBuf.writeCompoundTag(data);
|
||||
playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, packetBuf));
|
||||
}
|
||||
|
||||
public static void sendUpdateToClient(String rule, String newValue, ServerCommandSource source)
|
||||
{
|
||||
PacketByteBuf data = new PacketByteBuf(Unpooled.buffer());
|
||||
|
||||
data.writeVarInt(2);
|
||||
data.writeString(rule);
|
||||
data.writeString(newValue);
|
||||
for (ServerPlayerEntity player : source.getMinecraftServer().getPlayerManager().getPlayerList())
|
||||
{
|
||||
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, data));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendTickRateToPlayers(float rate)
|
||||
{
|
||||
PacketByteBuf data = new PacketByteBuf(Unpooled.buffer());
|
||||
data.writeVarInt(3);
|
||||
data.writeFloat(rate);
|
||||
if (CarpetServer.minecraft_server != null)
|
||||
{
|
||||
for (ServerPlayerEntity player : CarpetServer.minecraft_server.getPlayerManager().getPlayerList())
|
||||
{
|
||||
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.network.ServerNetworkHandler;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -177,7 +178,7 @@ public class TickSpeed
|
||||
}
|
||||
}
|
||||
|
||||
public static void tickrate(float rate)
|
||||
public static void tickrate(float rate, boolean update)
|
||||
{
|
||||
tickrate = rate;
|
||||
long mspt = (long)(1000.0 / tickrate);
|
||||
@@ -189,7 +190,7 @@ public class TickSpeed
|
||||
|
||||
TickSpeed.mspt = (float)mspt;
|
||||
|
||||
notifyTickrateListeners("carpet");
|
||||
if (update) notifyTickrateListeners("carpet");
|
||||
}
|
||||
|
||||
private static void tickrateChanged(String modId, float rate)
|
||||
@@ -221,7 +222,7 @@ public class TickSpeed
|
||||
}
|
||||
}
|
||||
}
|
||||
ServerNetworkHandler.sendTickRateToPlayers(tickrate);
|
||||
ServerNetworkHandler.updateTickSpeedToConnectedPlayers();
|
||||
}
|
||||
|
||||
public static BiConsumer<String, Float> addTickrateListener(String modId, BiConsumer<String, Float> tickrateListener)
|
||||
|
||||
@@ -1,44 +1,43 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.helpers.ClientNetworkHandler;
|
||||
import carpet.network.CarpetClient;
|
||||
import carpet.network.ClientNetworkHandler;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ClientPlayNetworkHandler.class)
|
||||
public abstract class ClientPlayNetworkHandlerMixin
|
||||
{
|
||||
@Inject(method = "onCustomPayload", at = @At(value = "CONSTANT", args = "stringValue=Unknown custom packed identifier: {}"), cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT, require = 0)
|
||||
private void onCustomPayloadNotFound(CustomPayloadS2CPacket packet, CallbackInfo ci, Identifier id, PacketByteBuf buf)
|
||||
{
|
||||
if (CarpetServer.CARPET_CHANNEL.equals(id))
|
||||
{
|
||||
if (buf.refCnt() > 0)
|
||||
{
|
||||
buf.release();
|
||||
}
|
||||
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow private MinecraftClient client;
|
||||
|
||||
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
private void onOnCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci)
|
||||
{
|
||||
Identifier channel = packet.getChannel();
|
||||
PacketByteBuf buf = packet.getData();
|
||||
ClientNetworkHandler.handleData(channel, buf);
|
||||
ci.cancel();
|
||||
if (CarpetClient.CARPET_CHANNEL.equals(packet.getChannel()))
|
||||
{
|
||||
ClientNetworkHandler.handleData(packet.getData(), client.player);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onGameJoin", at = @At("RETURN"))
|
||||
private void onGameJoined(GameJoinS2CPacket packet, CallbackInfo info)
|
||||
{
|
||||
CarpetClient.gameJoined(client.player);
|
||||
}
|
||||
|
||||
@Inject(method = "onDisconnected", at = @At("HEAD"))
|
||||
private void onCMDisconnected(Text reason, CallbackInfo ci)
|
||||
{
|
||||
CarpetClient.disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.network.CarpetClient;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -13,8 +14,10 @@ public class ClientPlayerEntity_clientCommandMixin
|
||||
@Inject(method = "sendChatMessage", at = @At("HEAD"))
|
||||
private void inspectMessage(String string, CallbackInfo ci)
|
||||
{
|
||||
ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this;
|
||||
if (CarpetServer.minecraft_server == null)
|
||||
if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet())
|
||||
{
|
||||
ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this;
|
||||
CarpetServer.settingsManager.inspectClientsideCommand(playerSource.getCommandSource(), string);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.fakes.CustomPayloadC2SPacketInterface;
|
||||
import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(CustomPayloadC2SPacket.class)
|
||||
public class CustomPayloadC2SPacketMixin implements CustomPayloadC2SPacketInterface
|
||||
{
|
||||
@Shadow
|
||||
private Identifier channel;
|
||||
@Shadow
|
||||
private PacketByteBuf data;
|
||||
|
||||
@Override
|
||||
public Identifier getPacketChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketByteBuf getPacketData() {
|
||||
return new PacketByteBuf(this.data.copy());
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.network.CarpetClient;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -18,4 +20,10 @@ public class MinecraftClientMixin
|
||||
//CM start game hook
|
||||
CarpetServer.onGameStarted();
|
||||
}
|
||||
|
||||
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("HEAD"))
|
||||
private void onCloseGame(Screen screen, CallbackInfo ci)
|
||||
{
|
||||
CarpetClient.disconnect();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.fakes.CustomPayloadC2SPacketInterface;
|
||||
import carpet.network.CarpetClient;
|
||||
import carpet.network.ServerNetworkHandler;
|
||||
import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
public class ServerPlayNetworkHandlerMixin
|
||||
{
|
||||
@Shadow public ServerPlayerEntity player;
|
||||
|
||||
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
private void onCustomCarpetPayload(CustomPayloadC2SPacket packet, CallbackInfo ci)
|
||||
{
|
||||
Identifier channel = ((CustomPayloadC2SPacketInterface) packet).getPacketChannel();
|
||||
if (CarpetClient.CARPET_CHANNEL.equals(channel))
|
||||
{
|
||||
ServerNetworkHandler.handleData(((CustomPayloadC2SPacketInterface) packet).getPacketData(), player);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package carpet.settings;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.network.ServerNetworkHandler;
|
||||
import carpet.utils.Translations;
|
||||
import carpet.utils.Messenger;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -80,7 +81,7 @@ public class SettingsManager
|
||||
|
||||
public void detachServer()
|
||||
{
|
||||
for (ParsedRule<?> rule : rules.values()) rule.resetToDefault(server.getCommandSource());
|
||||
for (ParsedRule<?> rule : rules.values()) rule.resetToDefault(null);
|
||||
server = null;
|
||||
}
|
||||
|
||||
@@ -103,6 +104,7 @@ public class SettingsManager
|
||||
void notifyRuleChanged(ServerCommandSource source, ParsedRule<?> rule, String userTypedValue)
|
||||
{
|
||||
observers.forEach(observer -> observer.accept(source, rule, userTypedValue));
|
||||
ServerNetworkHandler.updateRuleWithConnectedClients(rule);
|
||||
}
|
||||
|
||||
public Iterable<String> getCategories()
|
||||
@@ -584,8 +586,6 @@ public class SettingsManager
|
||||
rules.get(setting).set(source, strOption);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ public abstract class Validator<T>
|
||||
@Override
|
||||
public T validate(ServerCommandSource source, ParsedRule<T> currentRule, T newValue, String string)
|
||||
{
|
||||
if (CarpetServer.settingsManager != null)
|
||||
if (CarpetServer.settingsManager != null && source != null)
|
||||
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,8 @@ public class Messenger
|
||||
//message source
|
||||
public static void m(ServerCommandSource source, Object ... fields)
|
||||
{
|
||||
source.sendFeedback(Messenger.c(fields),source.getMinecraftServer() != null && source.getMinecraftServer().getWorld(DimensionType.OVERWORLD) != null);
|
||||
if (source != null)
|
||||
source.sendFeedback(Messenger.c(fields),source.getMinecraftServer() != null && source.getMinecraftServer().getWorld(DimensionType.OVERWORLD) != null);
|
||||
}
|
||||
public static void m(PlayerEntity player, Object ... fields)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user