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

+15 -9
View File
@@ -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();
}
}
+3 -2
View File
@@ -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));
}
}
}
}
+4 -3
View File
@@ -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);
}
}
}
}
}
+1 -1
View File
@@ -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;
}
+2 -1
View File
@@ -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)
{