681 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			681 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.world.level;
 | |
| 
 | |
| import com.google.common.collect.ImmutableMap;
 | |
| import com.google.common.collect.Maps;
 | |
| import com.mojang.brigadier.StringReader;
 | |
| import com.mojang.brigadier.arguments.ArgumentType;
 | |
| import com.mojang.brigadier.arguments.BoolArgumentType;
 | |
| import com.mojang.brigadier.arguments.IntegerArgumentType;
 | |
| import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 | |
| import com.mojang.brigadier.context.CommandContext;
 | |
| import com.mojang.brigadier.exceptions.CommandSyntaxException;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import com.mojang.serialization.Codec;
 | |
| import com.mojang.serialization.DataResult;
 | |
| import com.mojang.serialization.DynamicLike;
 | |
| import java.util.Comparator;
 | |
| import java.util.Map;
 | |
| import java.util.Map.Entry;
 | |
| import java.util.function.BiConsumer;
 | |
| import java.util.function.Function;
 | |
| import java.util.function.Supplier;
 | |
| import java.util.stream.Stream;
 | |
| import net.minecraft.commands.CommandSourceStack;
 | |
| import net.minecraft.commands.Commands;
 | |
| import net.minecraft.nbt.CompoundTag;
 | |
| import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
 | |
| import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
 | |
| import net.minecraft.server.MinecraftServer;
 | |
| import net.minecraft.server.level.ServerLevel;
 | |
| import net.minecraft.server.level.ServerPlayer;
 | |
| import net.minecraft.server.waypoints.ServerWaypointManager;
 | |
| import net.minecraft.world.flag.FeatureFlagSet;
 | |
| import net.minecraft.world.flag.FeatureFlags;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| public class GameRules {
 | |
| 	public static final int DEFAULT_RANDOM_TICK_SPEED = 3;
 | |
| 	static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	private static final Map<GameRules.Key<?>, GameRules.Type<?>> GAME_RULE_TYPES = Maps.newTreeMap(Comparator.comparing(key -> key.id));
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DOFIRETICK = register(
 | |
| 		"doFireTick", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_ALLOWFIRETICKAWAYFROMPLAYERS = register(
 | |
| 		"allowFireTicksAwayFromPlayer", GameRules.Category.UPDATES, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_MOBGRIEFING = register(
 | |
| 		"mobGriefing", GameRules.Category.MOBS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_KEEPINVENTORY = register(
 | |
| 		"keepInventory", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DOMOBSPAWNING = register(
 | |
| 		"doMobSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DOMOBLOOT = register("doMobLoot", GameRules.Category.DROPS, GameRules.BooleanValue.create(true));
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_PROJECTILESCANBREAKBLOCKS = register(
 | |
| 		"projectilesCanBreakBlocks", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DOBLOCKDROPS = register(
 | |
| 		"doTileDrops", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DOENTITYDROPS = register(
 | |
| 		"doEntityDrops", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_COMMANDBLOCKOUTPUT = register(
 | |
| 		"commandBlockOutput", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_NATURAL_REGENERATION = register(
 | |
| 		"naturalRegeneration", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DAYLIGHT = register(
 | |
| 		"doDaylightCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_LOGADMINCOMMANDS = register(
 | |
| 		"logAdminCommands", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_SHOWDEATHMESSAGES = register(
 | |
| 		"showDeathMessages", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_RANDOMTICKING = register(
 | |
| 		"randomTickSpeed", GameRules.Category.UPDATES, GameRules.IntegerValue.create(3)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_SENDCOMMANDFEEDBACK = register(
 | |
| 		"sendCommandFeedback", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_REDUCEDDEBUGINFO = register(
 | |
| 		"reducedDebugInfo", GameRules.Category.MISC, GameRules.BooleanValue.create(false, (minecraftServer, booleanValue) -> {
 | |
| 			byte b = (byte)(booleanValue.get() ? 22 : 23);
 | |
| 
 | |
| 			for (ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) {
 | |
| 				serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, b));
 | |
| 			}
 | |
| 		})
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_SPECTATORSGENERATECHUNKS = register(
 | |
| 		"spectatorsGenerateChunks", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_SPAWN_RADIUS = register(
 | |
| 		"spawnRadius", GameRules.Category.PLAYER, GameRules.IntegerValue.create(10)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DISABLE_PLAYER_MOVEMENT_CHECK = register(
 | |
| 		"disablePlayerMovementCheck", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DISABLE_ELYTRA_MOVEMENT_CHECK = register(
 | |
| 		"disableElytraMovementCheck", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_MAX_ENTITY_CRAMMING = register(
 | |
| 		"maxEntityCramming", GameRules.Category.MOBS, GameRules.IntegerValue.create(24)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_WEATHER_CYCLE = register(
 | |
| 		"doWeatherCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_LIMITED_CRAFTING = register(
 | |
| 		"doLimitedCrafting", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftServer, booleanValue) -> {
 | |
| 			for (ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) {
 | |
| 				serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LIMITED_CRAFTING, booleanValue.get() ? 1.0F : 0.0F));
 | |
| 			}
 | |
| 		})
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_MAX_COMMAND_CHAIN_LENGTH = register(
 | |
| 		"maxCommandChainLength", GameRules.Category.MISC, GameRules.IntegerValue.create(65536)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_MAX_COMMAND_FORK_COUNT = register(
 | |
| 		"maxCommandForkCount", GameRules.Category.MISC, GameRules.IntegerValue.create(65536)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_COMMAND_MODIFICATION_BLOCK_LIMIT = register(
 | |
| 		"commandModificationBlockLimit", GameRules.Category.MISC, GameRules.IntegerValue.create(32768)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_ANNOUNCE_ADVANCEMENTS = register(
 | |
| 		"announceAdvancements", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DISABLE_RAIDS = register(
 | |
| 		"disableRaids", GameRules.Category.MOBS, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DOINSOMNIA = register(
 | |
| 		"doInsomnia", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_IMMEDIATE_RESPAWN = register(
 | |
| 		"doImmediateRespawn", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftServer, booleanValue) -> {
 | |
| 			for (ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) {
 | |
| 				serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, booleanValue.get() ? 1.0F : 0.0F));
 | |
| 			}
 | |
| 		})
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY = register(
 | |
| 		"playersNetherPortalDefaultDelay", GameRules.Category.PLAYER, GameRules.IntegerValue.create(80)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY = register(
 | |
| 		"playersNetherPortalCreativeDelay", GameRules.Category.PLAYER, GameRules.IntegerValue.create(0)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DROWNING_DAMAGE = register(
 | |
| 		"drowningDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_FALL_DAMAGE = register(
 | |
| 		"fallDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_FIRE_DAMAGE = register(
 | |
| 		"fireDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_FREEZE_DAMAGE = register(
 | |
| 		"freezeDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_PATROL_SPAWNING = register(
 | |
| 		"doPatrolSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_TRADER_SPAWNING = register(
 | |
| 		"doTraderSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_WARDEN_SPAWNING = register(
 | |
| 		"doWardenSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_FORGIVE_DEAD_PLAYERS = register(
 | |
| 		"forgiveDeadPlayers", GameRules.Category.MOBS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_UNIVERSAL_ANGER = register(
 | |
| 		"universalAnger", GameRules.Category.MOBS, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_PLAYERS_SLEEPING_PERCENTAGE = register(
 | |
| 		"playersSleepingPercentage", GameRules.Category.PLAYER, GameRules.IntegerValue.create(100)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_BLOCK_EXPLOSION_DROP_DECAY = register(
 | |
| 		"blockExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_MOB_EXPLOSION_DROP_DECAY = register(
 | |
| 		"mobExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_TNT_EXPLOSION_DROP_DECAY = register(
 | |
| 		"tntExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_SNOW_ACCUMULATION_HEIGHT = register(
 | |
| 		"snowAccumulationHeight", GameRules.Category.UPDATES, GameRules.IntegerValue.create(1)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_WATER_SOURCE_CONVERSION = register(
 | |
| 		"waterSourceConversion", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_LAVA_SOURCE_CONVERSION = register(
 | |
| 		"lavaSourceConversion", GameRules.Category.UPDATES, GameRules.BooleanValue.create(false)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_GLOBAL_SOUND_EVENTS = register(
 | |
| 		"globalSoundEvents", GameRules.Category.MISC, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_VINES_SPREAD = register(
 | |
| 		"doVinesSpread", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_ENDER_PEARLS_VANISH_ON_DEATH = register(
 | |
| 		"enderPearlsVanishOnDeath", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_MINECART_MAX_SPEED = register(
 | |
| 		"minecartMaxSpeed",
 | |
| 		GameRules.Category.MISC,
 | |
| 		GameRules.IntegerValue.create(8, 1, 1000, FeatureFlagSet.of(FeatureFlags.MINECART_IMPROVEMENTS), (minecraftServer, integerValue) -> {})
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.IntegerValue> RULE_SPAWN_CHUNK_RADIUS = register(
 | |
| 		"spawnChunkRadius", GameRules.Category.MISC, GameRules.IntegerValue.create(2, 0, 32, FeatureFlagSet.of(), (minecraftServer, integerValue) -> {
 | |
| 			ServerLevel serverLevel = minecraftServer.overworld();
 | |
| 			serverLevel.setDefaultSpawnPos(serverLevel.getSharedSpawnPos(), serverLevel.getSharedSpawnAngle());
 | |
| 		})
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_TNT_EXPLODES = register(
 | |
| 		"tntExplodes", GameRules.Category.MISC, GameRules.BooleanValue.create(true)
 | |
| 	);
 | |
| 	public static final GameRules.Key<GameRules.BooleanValue> RULE_LOCATOR_BAR = register(
 | |
| 		"locatorBar",
 | |
| 		GameRules.Category.PLAYER,
 | |
| 		GameRules.BooleanValue.create(true, (minecraftServer, booleanValue) -> minecraftServer.getAllLevels().forEach(serverLevel -> {
 | |
| 			ServerWaypointManager serverWaypointManager = serverLevel.getWaypointManager();
 | |
| 			if (booleanValue.get()) {
 | |
| 				serverLevel.players().forEach(serverWaypointManager::updatePlayer);
 | |
| 			} else {
 | |
| 				serverWaypointManager.breakAllConnections();
 | |
| 			}
 | |
| 		}))
 | |
| 	);
 | |
| 	private final Map<GameRules.Key<?>, GameRules.Value<?>> rules;
 | |
| 	private final FeatureFlagSet enabledFeatures;
 | |
| 
 | |
| 	public static <T extends GameRules.Value<T>> GameRules.Type<T> getType(GameRules.Key<T> key) {
 | |
| 		return (GameRules.Type<T>)GAME_RULE_TYPES.get(key);
 | |
| 	}
 | |
| 
 | |
| 	public static <T extends GameRules.Value<T>> Codec<GameRules.Key<T>> keyCodec(Class<T> clazz) {
 | |
| 		return Codec.STRING
 | |
| 			.comapFlatMap(
 | |
| 				string -> (DataResult)GAME_RULE_TYPES.entrySet()
 | |
| 					.stream()
 | |
| 					.filter(entry -> ((GameRules.Type)entry.getValue()).valueClass == clazz)
 | |
| 					.map(Entry::getKey)
 | |
| 					.filter(key -> key.getId().equals(string))
 | |
| 					.map(key -> key)
 | |
| 					.findFirst()
 | |
| 					.map(DataResult::success)
 | |
| 					.orElseGet(() -> DataResult.error(() -> "Invalid game rule ID for type: " + string)),
 | |
| 				GameRules.Key::getId
 | |
| 			);
 | |
| 	}
 | |
| 
 | |
| 	private static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
 | |
| 		GameRules.Key<T> key = new GameRules.Key<>(name, category);
 | |
| 		GameRules.Type<?> type2 = (GameRules.Type<?>)GAME_RULE_TYPES.put(key, type);
 | |
| 		if (type2 != null) {
 | |
| 			throw new IllegalStateException("Duplicate game rule registration for " + name);
 | |
| 		} else {
 | |
| 			return key;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public GameRules(FeatureFlagSet enabledFeatures, DynamicLike<?> tag) {
 | |
| 		this(enabledFeatures);
 | |
| 		this.loadFromTag(tag);
 | |
| 	}
 | |
| 
 | |
| 	public GameRules(FeatureFlagSet enabledFeatures) {
 | |
| 		this(
 | |
| 			(Map<GameRules.Key<?>, GameRules.Value<?>>)availableRules(enabledFeatures)
 | |
| 				.collect(ImmutableMap.toImmutableMap(Entry::getKey, entry -> ((GameRules.Type)entry.getValue()).createRule())),
 | |
| 			enabledFeatures
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	private static Stream<Entry<GameRules.Key<?>, GameRules.Type<?>>> availableRules(FeatureFlagSet enabledFeatures) {
 | |
| 		return GAME_RULE_TYPES.entrySet().stream().filter(entry -> ((GameRules.Type)entry.getValue()).requiredFeatures.isSubsetOf(enabledFeatures));
 | |
| 	}
 | |
| 
 | |
| 	private GameRules(Map<GameRules.Key<?>, GameRules.Value<?>> rules, FeatureFlagSet enabledFeatures) {
 | |
| 		this.rules = rules;
 | |
| 		this.enabledFeatures = enabledFeatures;
 | |
| 	}
 | |
| 
 | |
| 	public <T extends GameRules.Value<T>> T getRule(GameRules.Key<T> key) {
 | |
| 		T value = (T)this.rules.get(key);
 | |
| 		if (value == null) {
 | |
| 			throw new IllegalArgumentException("Tried to access invalid game rule");
 | |
| 		} else {
 | |
| 			return value;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Return the defined game rules as NBT.
 | |
| 	 */
 | |
| 	public CompoundTag createTag() {
 | |
| 		CompoundTag compoundTag = new CompoundTag();
 | |
| 		this.rules.forEach((key, value) -> compoundTag.putString(key.id, value.serialize()));
 | |
| 		return compoundTag;
 | |
| 	}
 | |
| 
 | |
| 	private void loadFromTag(DynamicLike<?> dynamic) {
 | |
| 		this.rules.forEach((key, value) -> dynamic.get(key.id).asString().ifSuccess(value::deserialize));
 | |
| 	}
 | |
| 
 | |
| 	public GameRules copy(FeatureFlagSet enabledFeatures) {
 | |
| 		return new GameRules(
 | |
| 			(Map<GameRules.Key<?>, GameRules.Value<?>>)availableRules(enabledFeatures)
 | |
| 				.collect(
 | |
| 					ImmutableMap.toImmutableMap(
 | |
| 						Entry::getKey,
 | |
| 						entry -> this.rules.containsKey(entry.getKey())
 | |
| 							? ((GameRules.Value)this.rules.get(entry.getKey())).copy()
 | |
| 							: ((GameRules.Type)entry.getValue()).createRule()
 | |
| 					)
 | |
| 				),
 | |
| 			enabledFeatures
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	public void visitGameRuleTypes(GameRules.GameRuleTypeVisitor visitor) {
 | |
| 		GAME_RULE_TYPES.forEach((key, type) -> this.callVisitorCap(visitor, key, type));
 | |
| 	}
 | |
| 
 | |
| 	private <T extends GameRules.Value<T>> void callVisitorCap(GameRules.GameRuleTypeVisitor visitor, GameRules.Key<?> key, GameRules.Type<?> type) {
 | |
| 		if (type.requiredFeatures.isSubsetOf(this.enabledFeatures)) {
 | |
| 			visitor.visit(key, type);
 | |
| 			type.callVisitor(visitor, key);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void assignFrom(GameRules rules, @Nullable MinecraftServer server) {
 | |
| 		rules.rules.keySet().forEach(key -> this.assignCap(key, rules, server));
 | |
| 	}
 | |
| 
 | |
| 	private <T extends GameRules.Value<T>> void assignCap(GameRules.Key<T> key, GameRules rules, @Nullable MinecraftServer server) {
 | |
| 		T value = rules.getRule(key);
 | |
| 		this.<T>getRule(key).setFrom(value, server);
 | |
| 	}
 | |
| 
 | |
| 	public boolean getBoolean(GameRules.Key<GameRules.BooleanValue> key) {
 | |
| 		return this.getRule(key).get();
 | |
| 	}
 | |
| 
 | |
| 	public int getInt(GameRules.Key<GameRules.IntegerValue> key) {
 | |
| 		return this.getRule(key).get();
 | |
| 	}
 | |
| 
 | |
| 	public static class BooleanValue extends GameRules.Value<GameRules.BooleanValue> {
 | |
| 		private boolean value;
 | |
| 
 | |
| 		private static GameRules.Type<GameRules.BooleanValue> create(
 | |
| 			boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changeListener, FeatureFlagSet requiredFeatures
 | |
| 		) {
 | |
| 			return new GameRules.Type<>(
 | |
| 				BoolArgumentType::bool,
 | |
| 				type -> new GameRules.BooleanValue(type, defaultValue),
 | |
| 				changeListener,
 | |
| 				GameRules.GameRuleTypeVisitor::visitBoolean,
 | |
| 				GameRules.BooleanValue.class,
 | |
| 				requiredFeatures
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		static GameRules.Type<GameRules.BooleanValue> create(boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changeListener) {
 | |
| 			return new GameRules.Type<>(
 | |
| 				BoolArgumentType::bool,
 | |
| 				type -> new GameRules.BooleanValue(type, defaultValue),
 | |
| 				changeListener,
 | |
| 				GameRules.GameRuleTypeVisitor::visitBoolean,
 | |
| 				GameRules.BooleanValue.class,
 | |
| 				FeatureFlagSet.of()
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		static GameRules.Type<GameRules.BooleanValue> create(boolean defaultValue) {
 | |
| 			return create(defaultValue, (minecraftServer, booleanValue) -> {});
 | |
| 		}
 | |
| 
 | |
| 		public BooleanValue(GameRules.Type<GameRules.BooleanValue> type, boolean value) {
 | |
| 			super(type);
 | |
| 			this.value = value;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		protected void updateFromArgument(CommandContext<CommandSourceStack> context, String paramName) {
 | |
| 			this.value = BoolArgumentType.getBool(context, paramName);
 | |
| 		}
 | |
| 
 | |
| 		public boolean get() {
 | |
| 			return this.value;
 | |
| 		}
 | |
| 
 | |
| 		public void set(boolean value, @Nullable MinecraftServer server) {
 | |
| 			this.value = value;
 | |
| 			this.onChanged(server);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public String serialize() {
 | |
| 			return Boolean.toString(this.value);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		protected void deserialize(String value) {
 | |
| 			this.value = Boolean.parseBoolean(value);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public int getCommandResult() {
 | |
| 			return this.value ? 1 : 0;
 | |
| 		}
 | |
| 
 | |
| 		protected GameRules.BooleanValue getSelf() {
 | |
| 			return this;
 | |
| 		}
 | |
| 
 | |
| 		protected GameRules.BooleanValue copy() {
 | |
| 			return new GameRules.BooleanValue(this.type, this.value);
 | |
| 		}
 | |
| 
 | |
| 		public void setFrom(GameRules.BooleanValue value, @Nullable MinecraftServer server) {
 | |
| 			this.value = value.value;
 | |
| 			this.onChanged(server);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static enum Category {
 | |
| 		PLAYER("gamerule.category.player"),
 | |
| 		MOBS("gamerule.category.mobs"),
 | |
| 		SPAWNING("gamerule.category.spawning"),
 | |
| 		DROPS("gamerule.category.drops"),
 | |
| 		UPDATES("gamerule.category.updates"),
 | |
| 		CHAT("gamerule.category.chat"),
 | |
| 		MISC("gamerule.category.misc");
 | |
| 
 | |
| 		private final String descriptionId;
 | |
| 
 | |
| 		private Category(final String descriptionId) {
 | |
| 			this.descriptionId = descriptionId;
 | |
| 		}
 | |
| 
 | |
| 		public String getDescriptionId() {
 | |
| 			return this.descriptionId;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public interface GameRuleTypeVisitor {
 | |
| 		default <T extends GameRules.Value<T>> void visit(GameRules.Key<T> key, GameRules.Type<T> type) {
 | |
| 		}
 | |
| 
 | |
| 		default void visitBoolean(GameRules.Key<GameRules.BooleanValue> key, GameRules.Type<GameRules.BooleanValue> type) {
 | |
| 		}
 | |
| 
 | |
| 		default void visitInteger(GameRules.Key<GameRules.IntegerValue> key, GameRules.Type<GameRules.IntegerValue> type) {
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static class IntegerValue extends GameRules.Value<GameRules.IntegerValue> {
 | |
| 		private int value;
 | |
| 
 | |
| 		private static GameRules.Type<GameRules.IntegerValue> create(int defaultValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changeListener) {
 | |
| 			return new GameRules.Type<>(
 | |
| 				IntegerArgumentType::integer,
 | |
| 				type -> new GameRules.IntegerValue(type, defaultValue),
 | |
| 				changeListener,
 | |
| 				GameRules.GameRuleTypeVisitor::visitInteger,
 | |
| 				GameRules.IntegerValue.class,
 | |
| 				FeatureFlagSet.of()
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		static GameRules.Type<GameRules.IntegerValue> create(
 | |
| 			int defaultValue, int min, int max, FeatureFlagSet requiredFeatures, BiConsumer<MinecraftServer, GameRules.IntegerValue> changeListener
 | |
| 		) {
 | |
| 			return new GameRules.Type<>(
 | |
| 				() -> IntegerArgumentType.integer(min, max),
 | |
| 				type -> new GameRules.IntegerValue(type, defaultValue),
 | |
| 				changeListener,
 | |
| 				GameRules.GameRuleTypeVisitor::visitInteger,
 | |
| 				GameRules.IntegerValue.class,
 | |
| 				requiredFeatures
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		static GameRules.Type<GameRules.IntegerValue> create(int defaultValue) {
 | |
| 			return create(defaultValue, (minecraftServer, integerValue) -> {});
 | |
| 		}
 | |
| 
 | |
| 		public IntegerValue(GameRules.Type<GameRules.IntegerValue> type, int value) {
 | |
| 			super(type);
 | |
| 			this.value = value;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		protected void updateFromArgument(CommandContext<CommandSourceStack> context, String paramName) {
 | |
| 			this.value = IntegerArgumentType.getInteger(context, paramName);
 | |
| 		}
 | |
| 
 | |
| 		public int get() {
 | |
| 			return this.value;
 | |
| 		}
 | |
| 
 | |
| 		public void set(int value, @Nullable MinecraftServer server) {
 | |
| 			this.value = value;
 | |
| 			this.onChanged(server);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public String serialize() {
 | |
| 			return Integer.toString(this.value);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		protected void deserialize(String value) {
 | |
| 			this.value = safeParse(value);
 | |
| 		}
 | |
| 
 | |
| 		public boolean tryDeserialize(String name) {
 | |
| 			try {
 | |
| 				StringReader stringReader = new StringReader(name);
 | |
| 				this.value = (Integer)((ArgumentType)this.type.argument.get()).parse(stringReader);
 | |
| 				return !stringReader.canRead();
 | |
| 			} catch (CommandSyntaxException var3) {
 | |
| 				return false;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private static int safeParse(String strValue) {
 | |
| 			if (!strValue.isEmpty()) {
 | |
| 				try {
 | |
| 					return Integer.parseInt(strValue);
 | |
| 				} catch (NumberFormatException var2) {
 | |
| 					GameRules.LOGGER.warn("Failed to parse integer {}", strValue);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return 0;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public int getCommandResult() {
 | |
| 			return this.value;
 | |
| 		}
 | |
| 
 | |
| 		protected GameRules.IntegerValue getSelf() {
 | |
| 			return this;
 | |
| 		}
 | |
| 
 | |
| 		protected GameRules.IntegerValue copy() {
 | |
| 			return new GameRules.IntegerValue(this.type, this.value);
 | |
| 		}
 | |
| 
 | |
| 		public void setFrom(GameRules.IntegerValue value, @Nullable MinecraftServer server) {
 | |
| 			this.value = value.value;
 | |
| 			this.onChanged(server);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static final class Key<T extends GameRules.Value<T>> {
 | |
| 		final String id;
 | |
| 		private final GameRules.Category category;
 | |
| 
 | |
| 		public Key(String id, GameRules.Category category) {
 | |
| 			this.id = id;
 | |
| 			this.category = category;
 | |
| 		}
 | |
| 
 | |
| 		public String toString() {
 | |
| 			return this.id;
 | |
| 		}
 | |
| 
 | |
| 		public boolean equals(Object object) {
 | |
| 			return this == object ? true : object instanceof GameRules.Key && ((GameRules.Key)object).id.equals(this.id);
 | |
| 		}
 | |
| 
 | |
| 		public int hashCode() {
 | |
| 			return this.id.hashCode();
 | |
| 		}
 | |
| 
 | |
| 		public String getId() {
 | |
| 			return this.id;
 | |
| 		}
 | |
| 
 | |
| 		public String getDescriptionId() {
 | |
| 			return "gamerule." + this.id;
 | |
| 		}
 | |
| 
 | |
| 		public GameRules.Category getCategory() {
 | |
| 			return this.category;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static class Type<T extends GameRules.Value<T>> {
 | |
| 		final Supplier<ArgumentType<?>> argument;
 | |
| 		private final Function<GameRules.Type<T>, T> constructor;
 | |
| 		final BiConsumer<MinecraftServer, T> callback;
 | |
| 		private final GameRules.VisitorCaller<T> visitorCaller;
 | |
| 		final Class<T> valueClass;
 | |
| 		final FeatureFlagSet requiredFeatures;
 | |
| 
 | |
| 		Type(
 | |
| 			Supplier<ArgumentType<?>> argument,
 | |
| 			Function<GameRules.Type<T>, T> constructor,
 | |
| 			BiConsumer<MinecraftServer, T> callback,
 | |
| 			GameRules.VisitorCaller<T> visitorCaller,
 | |
| 			Class<T> valueClass,
 | |
| 			FeatureFlagSet requiredFeatures
 | |
| 		) {
 | |
| 			this.argument = argument;
 | |
| 			this.constructor = constructor;
 | |
| 			this.callback = callback;
 | |
| 			this.visitorCaller = visitorCaller;
 | |
| 			this.valueClass = valueClass;
 | |
| 			this.requiredFeatures = requiredFeatures;
 | |
| 		}
 | |
| 
 | |
| 		public RequiredArgumentBuilder<CommandSourceStack, ?> createArgument(String name) {
 | |
| 			return Commands.argument(name, (ArgumentType<T>)this.argument.get());
 | |
| 		}
 | |
| 
 | |
| 		public T createRule() {
 | |
| 			return (T)this.constructor.apply(this);
 | |
| 		}
 | |
| 
 | |
| 		public void callVisitor(GameRules.GameRuleTypeVisitor visitor, GameRules.Key<T> key) {
 | |
| 			this.visitorCaller.call(visitor, key, this);
 | |
| 		}
 | |
| 
 | |
| 		public FeatureFlagSet requiredFeatures() {
 | |
| 			return this.requiredFeatures;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public abstract static class Value<T extends GameRules.Value<T>> {
 | |
| 		protected final GameRules.Type<T> type;
 | |
| 
 | |
| 		public Value(GameRules.Type<T> type) {
 | |
| 			this.type = type;
 | |
| 		}
 | |
| 
 | |
| 		protected abstract void updateFromArgument(CommandContext<CommandSourceStack> context, String paramName);
 | |
| 
 | |
| 		public void setFromArgument(CommandContext<CommandSourceStack> context, String paramName) {
 | |
| 			this.updateFromArgument(context, paramName);
 | |
| 			this.onChanged(context.getSource().getServer());
 | |
| 		}
 | |
| 
 | |
| 		protected void onChanged(@Nullable MinecraftServer server) {
 | |
| 			if (server != null) {
 | |
| 				this.type.callback.accept(server, this.getSelf());
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		protected abstract void deserialize(String value);
 | |
| 
 | |
| 		public abstract String serialize();
 | |
| 
 | |
| 		public String toString() {
 | |
| 			return this.serialize();
 | |
| 		}
 | |
| 
 | |
| 		public abstract int getCommandResult();
 | |
| 
 | |
| 		protected abstract T getSelf();
 | |
| 
 | |
| 		protected abstract T copy();
 | |
| 
 | |
| 		public abstract void setFrom(T value, @Nullable MinecraftServer server);
 | |
| 	}
 | |
| 
 | |
| 	interface VisitorCaller<T extends GameRules.Value<T>> {
 | |
| 		void call(GameRules.GameRuleTypeVisitor gameRuleTypeVisitor, GameRules.Key<T> key, GameRules.Type<T> type);
 | |
| 	}
 | |
| }
 |