367 lines
15 KiB
Java
367 lines
15 KiB
Java
package net.minecraft.world.level;
|
|
|
|
import com.mojang.brigadier.arguments.BoolArgumentType;
|
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
|
import javax.annotation.Nullable;
|
|
import com.mojang.brigadier.context.CommandContext;
|
|
import net.minecraft.commands.Commands;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
|
import java.util.function.BiConsumer;
|
|
import com.mojang.brigadier.arguments.ArgumentType;
|
|
import java.util.function.Supplier;
|
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
|
import com.google.common.collect.Maps;
|
|
import java.util.Comparator;
|
|
import org.apache.logging.log4j.LogManager;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
|
import java.util.Iterator;
|
|
import net.minecraft.network.protocol.Packet;
|
|
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import java.util.stream.Collector;
|
|
import java.util.function.Function;
|
|
import com.google.common.collect.ImmutableMap;
|
|
import java.util.Map;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
public class GameRules {
|
|
private static final Logger LOGGER;
|
|
private static final Map<Key<?>, Type<?>> GAME_RULE_TYPES;
|
|
public static final Key<BooleanValue> RULE_DOFIRETICK;
|
|
public static final Key<BooleanValue> RULE_MOBGRIEFING;
|
|
public static final Key<BooleanValue> RULE_KEEPINVENTORY;
|
|
public static final Key<BooleanValue> RULE_DOMOBSPAWNING;
|
|
public static final Key<BooleanValue> RULE_DOMOBLOOT;
|
|
public static final Key<BooleanValue> RULE_DOBLOCKDROPS;
|
|
public static final Key<BooleanValue> RULE_DOENTITYDROPS;
|
|
public static final Key<BooleanValue> RULE_COMMANDBLOCKOUTPUT;
|
|
public static final Key<BooleanValue> RULE_NATURAL_REGENERATION;
|
|
public static final Key<BooleanValue> RULE_DAYLIGHT;
|
|
public static final Key<BooleanValue> RULE_LOGADMINCOMMANDS;
|
|
public static final Key<BooleanValue> RULE_SHOWDEATHMESSAGES;
|
|
public static final Key<IntegerValue> RULE_RANDOMTICKING;
|
|
public static final Key<BooleanValue> RULE_SENDCOMMANDFEEDBACK;
|
|
public static final Key<BooleanValue> RULE_REDUCEDDEBUGINFO;
|
|
public static final Key<BooleanValue> RULE_SPECTATORSGENERATECHUNKS;
|
|
public static final Key<IntegerValue> RULE_SPAWN_RADIUS;
|
|
public static final Key<BooleanValue> RULE_DISABLE_ELYTRA_MOVEMENT_CHECK;
|
|
public static final Key<IntegerValue> RULE_MAX_ENTITY_CRAMMING;
|
|
public static final Key<BooleanValue> RULE_WEATHER_CYCLE;
|
|
public static final Key<BooleanValue> RULE_LIMITED_CRAFTING;
|
|
public static final Key<IntegerValue> RULE_MAX_COMMAND_CHAIN_LENGTH;
|
|
public static final Key<BooleanValue> RULE_ANNOUNCE_ADVANCEMENTS;
|
|
public static final Key<BooleanValue> RULE_DISABLE_RAIDS;
|
|
public static final Key<BooleanValue> RULE_DOINSOMNIA;
|
|
public static final Key<BooleanValue> RULE_DO_IMMEDIATE_RESPAWN;
|
|
public static final Key<BooleanValue> RULE_DROWNING_DAMAGE;
|
|
public static final Key<BooleanValue> RULE_FALL_DAMAGE;
|
|
public static final Key<BooleanValue> RULE_FIRE_DAMAGE;
|
|
private final Map<Key<?>, Value<?>> rules;
|
|
|
|
private static <T extends Value<T>> Key<T> register(final String string, final Type<T> e) {
|
|
final Key<T> d3 = new Key<T>(string);
|
|
final Type<?> e2 = GameRules.GAME_RULE_TYPES.put(d3, e);
|
|
if (e2 != null) {
|
|
throw new IllegalStateException("Duplicate game rule registration for " + string);
|
|
}
|
|
return d3;
|
|
}
|
|
|
|
public GameRules() {
|
|
this.rules = GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().createRule()));
|
|
}
|
|
|
|
public <T extends Value<T>> T getRule(final Key<T> d) {
|
|
return (T)this.rules.get(d);
|
|
}
|
|
|
|
public CompoundTag createTag() {
|
|
final CompoundTag jt2 = new CompoundTag();
|
|
this.rules.forEach((d, f) -> jt2.putString(d.id, f.serialize()));
|
|
return jt2;
|
|
}
|
|
|
|
public void loadFromTag(final CompoundTag jt) {
|
|
this.rules.forEach((d, f) -> {
|
|
if (jt.contains(d.id)) {
|
|
f.deserialize(jt.getString(d.id));
|
|
}
|
|
});
|
|
}
|
|
|
|
public static void visitGameRuleTypes(final GameRuleTypeVisitor b) {
|
|
GameRules.GAME_RULE_TYPES.forEach((d, e) -> GameRules.<Value>cap(b, d, e));
|
|
}
|
|
|
|
private static <T extends Value<T>> void cap(final GameRuleTypeVisitor b, final Key<?> d, final Type<?> e) {
|
|
final Key<T> d2 = (Key<T>)d;
|
|
final Type<T> e2 = (Type<T>)e;
|
|
b.<T>visit(d2, e2);
|
|
}
|
|
|
|
public boolean getBoolean(final Key<BooleanValue> d) {
|
|
return this.<BooleanValue>getRule(d).get();
|
|
}
|
|
|
|
public int getInt(final Key<IntegerValue> d) {
|
|
return this.<IntegerValue>getRule(d).get();
|
|
}
|
|
|
|
static {
|
|
LOGGER = LogManager.getLogger();
|
|
GAME_RULE_TYPES = Maps.newTreeMap(Comparator.<Object, Comparable>comparing(d -> d.id));
|
|
RULE_DOFIRETICK = GameRules.<BooleanValue>register("doFireTick", create(true));
|
|
RULE_MOBGRIEFING = GameRules.<BooleanValue>register("mobGriefing", create(true));
|
|
RULE_KEEPINVENTORY = GameRules.<BooleanValue>register("keepInventory", create(false));
|
|
RULE_DOMOBSPAWNING = GameRules.<BooleanValue>register("doMobSpawning", create(true));
|
|
RULE_DOMOBLOOT = GameRules.<BooleanValue>register("doMobLoot", create(true));
|
|
RULE_DOBLOCKDROPS = GameRules.<BooleanValue>register("doTileDrops", create(true));
|
|
RULE_DOENTITYDROPS = GameRules.<BooleanValue>register("doEntityDrops", create(true));
|
|
RULE_COMMANDBLOCKOUTPUT = GameRules.<BooleanValue>register("commandBlockOutput", create(true));
|
|
RULE_NATURAL_REGENERATION = GameRules.<BooleanValue>register("naturalRegeneration", create(true));
|
|
RULE_DAYLIGHT = GameRules.<BooleanValue>register("doDaylightCycle", create(true));
|
|
RULE_LOGADMINCOMMANDS = GameRules.<BooleanValue>register("logAdminCommands", create(true));
|
|
RULE_SHOWDEATHMESSAGES = GameRules.<BooleanValue>register("showDeathMessages", create(true));
|
|
RULE_RANDOMTICKING = GameRules.<IntegerValue>register("randomTickSpeed", create(3));
|
|
RULE_SENDCOMMANDFEEDBACK = GameRules.<BooleanValue>register("sendCommandFeedback", create(true));
|
|
final int byte3;
|
|
final Iterator<ServerPlayer> iterator;
|
|
ServerPlayer xe5;
|
|
RULE_REDUCEDDEBUGINFO = GameRules.<BooleanValue>register("reducedDebugInfo", create(false, (minecraftServer, a) -> {
|
|
byte3 = (a.get() ? 22 : 23);
|
|
minecraftServer.getPlayerList().getPlayers().iterator();
|
|
while (iterator.hasNext()) {
|
|
xe5 = iterator.next();
|
|
xe5.connection.send(new ClientboundEntityEventPacket(xe5, (byte)byte3));
|
|
}
|
|
return;
|
|
}));
|
|
RULE_SPECTATORSGENERATECHUNKS = GameRules.<BooleanValue>register("spectatorsGenerateChunks", create(true));
|
|
RULE_SPAWN_RADIUS = GameRules.<IntegerValue>register("spawnRadius", create(10));
|
|
RULE_DISABLE_ELYTRA_MOVEMENT_CHECK = GameRules.<BooleanValue>register("disableElytraMovementCheck", create(false));
|
|
RULE_MAX_ENTITY_CRAMMING = GameRules.<IntegerValue>register("maxEntityCramming", create(24));
|
|
RULE_WEATHER_CYCLE = GameRules.<BooleanValue>register("doWeatherCycle", create(true));
|
|
RULE_LIMITED_CRAFTING = GameRules.<BooleanValue>register("doLimitedCrafting", create(false));
|
|
RULE_MAX_COMMAND_CHAIN_LENGTH = GameRules.<IntegerValue>register("maxCommandChainLength", create(65536));
|
|
RULE_ANNOUNCE_ADVANCEMENTS = GameRules.<BooleanValue>register("announceAdvancements", create(true));
|
|
RULE_DISABLE_RAIDS = GameRules.<BooleanValue>register("disableRaids", create(false));
|
|
RULE_DOINSOMNIA = GameRules.<BooleanValue>register("doInsomnia", create(true));
|
|
final Iterator<ServerPlayer> iterator2;
|
|
ServerPlayer xe6;
|
|
ServerGamePacketListenerImpl connection;
|
|
final ClientboundGameEventPacket lt;
|
|
RULE_DO_IMMEDIATE_RESPAWN = GameRules.<BooleanValue>register("doImmediateRespawn", create(false, (minecraftServer, a) -> {
|
|
minecraftServer.getPlayerList().getPlayers().iterator();
|
|
while (iterator2.hasNext()) {
|
|
xe6 = iterator2.next();
|
|
connection = xe6.connection;
|
|
new ClientboundGameEventPacket(11, a.get() ? 1.0f : 0.0f);
|
|
connection.send(lt);
|
|
}
|
|
return;
|
|
}));
|
|
RULE_DROWNING_DAMAGE = GameRules.<BooleanValue>register("drowningDamage", create(true));
|
|
RULE_FALL_DAMAGE = GameRules.<BooleanValue>register("fallDamage", create(true));
|
|
RULE_FIRE_DAMAGE = GameRules.<BooleanValue>register("fireDamage", create(true));
|
|
}
|
|
|
|
public static final class Key<T extends Value<T>> {
|
|
private final String id;
|
|
|
|
public Key(final String string) {
|
|
this.id = string;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return this.id;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(final Object object) {
|
|
return this == object || (object instanceof Key && ((Key)object).id.equals(this.id));
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return this.id.hashCode();
|
|
}
|
|
|
|
public String getId() {
|
|
return this.id;
|
|
}
|
|
}
|
|
|
|
public static class Type<T extends Value<T>> {
|
|
private final Supplier<ArgumentType<?>> argument;
|
|
private final Function<Type<T>, T> constructor;
|
|
private final BiConsumer<MinecraftServer, T> callback;
|
|
|
|
private Type(final Supplier<ArgumentType<?>> supplier, final Function<Type<T>, T> function, final BiConsumer<MinecraftServer, T> biConsumer) {
|
|
this.argument = supplier;
|
|
this.constructor = function;
|
|
this.callback = biConsumer;
|
|
}
|
|
|
|
public RequiredArgumentBuilder<CommandSourceStack, ?> createArgument(final String string) {
|
|
return Commands.argument(string, this.argument.get());
|
|
}
|
|
|
|
public T createRule() {
|
|
return this.constructor.apply(this);
|
|
}
|
|
}
|
|
|
|
public abstract static class Value<T extends Value<T>> {
|
|
private final Type<T> type;
|
|
|
|
public Value(final Type<T> e) {
|
|
this.type = e;
|
|
}
|
|
|
|
protected abstract void updateFromArgument(final CommandContext<CommandSourceStack> commandContext, final String string);
|
|
|
|
public void setFromArgument(final CommandContext<CommandSourceStack> commandContext, final String string) {
|
|
this.updateFromArgument(commandContext, string);
|
|
this.onChanged(((CommandSourceStack)commandContext.getSource()).getServer());
|
|
}
|
|
|
|
protected void onChanged(@Nullable final MinecraftServer minecraftServer) {
|
|
if (minecraftServer != null) {
|
|
((Type<Value>)this.type).callback.accept(minecraftServer, this.getSelf());
|
|
}
|
|
}
|
|
|
|
protected abstract void deserialize(final String string);
|
|
|
|
protected abstract String serialize();
|
|
|
|
@Override
|
|
public String toString() {
|
|
return this.serialize();
|
|
}
|
|
|
|
public abstract int getCommandResult();
|
|
|
|
protected abstract T getSelf();
|
|
}
|
|
|
|
public static class IntegerValue extends Value<IntegerValue> {
|
|
private int value;
|
|
|
|
private static Type<IntegerValue> create(final int integer, final BiConsumer<MinecraftServer, IntegerValue> biConsumer) {
|
|
return new Type<IntegerValue>((Supplier)IntegerArgumentType::integer, e -> new IntegerValue(e, integer), (BiConsumer)biConsumer);
|
|
}
|
|
|
|
private static Type<IntegerValue> create(final int integer) {
|
|
return create(integer, (minecraftServer, c) -> {});
|
|
}
|
|
|
|
public IntegerValue(final Type<IntegerValue> e, final int integer) {
|
|
super(e);
|
|
this.value = integer;
|
|
}
|
|
|
|
@Override
|
|
protected void updateFromArgument(final CommandContext<CommandSourceStack> commandContext, final String string) {
|
|
this.value = IntegerArgumentType.getInteger((CommandContext)commandContext, string);
|
|
}
|
|
|
|
public int get() {
|
|
return this.value;
|
|
}
|
|
|
|
@Override
|
|
protected String serialize() {
|
|
return Integer.toString(this.value);
|
|
}
|
|
|
|
@Override
|
|
protected void deserialize(final String string) {
|
|
this.value = safeParse(string);
|
|
}
|
|
|
|
private static int safeParse(final String string) {
|
|
if (!string.isEmpty()) {
|
|
try {
|
|
return Integer.parseInt(string);
|
|
}
|
|
catch (NumberFormatException numberFormatException2) {
|
|
GameRules.LOGGER.warn("Failed to parse integer {}", string);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public int getCommandResult() {
|
|
return this.value;
|
|
}
|
|
|
|
@Override
|
|
protected IntegerValue getSelf() {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
public static class BooleanValue extends Value<BooleanValue> {
|
|
private boolean value;
|
|
|
|
private static Type<BooleanValue> create(final boolean boolean1, final BiConsumer<MinecraftServer, BooleanValue> biConsumer) {
|
|
return new Type<BooleanValue>((Supplier)BoolArgumentType::bool, e -> new BooleanValue(e, boolean1), (BiConsumer)biConsumer);
|
|
}
|
|
|
|
private static Type<BooleanValue> create(final boolean boolean1) {
|
|
return create(boolean1, (minecraftServer, a) -> {});
|
|
}
|
|
|
|
public BooleanValue(final Type<BooleanValue> e, final boolean boolean2) {
|
|
super(e);
|
|
this.value = boolean2;
|
|
}
|
|
|
|
@Override
|
|
protected void updateFromArgument(final CommandContext<CommandSourceStack> commandContext, final String string) {
|
|
this.value = BoolArgumentType.getBool((CommandContext)commandContext, string);
|
|
}
|
|
|
|
public boolean get() {
|
|
return this.value;
|
|
}
|
|
|
|
public void set(final boolean boolean1, @Nullable final MinecraftServer minecraftServer) {
|
|
this.value = boolean1;
|
|
this.onChanged(minecraftServer);
|
|
}
|
|
|
|
@Override
|
|
protected String serialize() {
|
|
return Boolean.toString(this.value);
|
|
}
|
|
|
|
@Override
|
|
protected void deserialize(final String string) {
|
|
this.value = Boolean.parseBoolean(string);
|
|
}
|
|
|
|
@Override
|
|
public int getCommandResult() {
|
|
return this.value ? 1 : 0;
|
|
}
|
|
|
|
@Override
|
|
protected BooleanValue getSelf() {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public interface GameRuleTypeVisitor {
|
|
<T extends Value<T>> void visit(final Key<T> d, final Type<T> e);
|
|
}
|
|
}
|