1
0
Fork 0
mirror of https://github.com/PaperMC/Paper.git synced 2025-02-17 18:47:40 +01:00

Let's hope this is fine

This commit is contained in:
Nassim Jahnke 2023-06-07 20:03:53 +02:00
parent 27998753e9
commit 890a93c65e
4 changed files with 875 additions and 147 deletions

View file

@ -2578,6 +2578,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
// CraftBukkit end
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
- public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string
+ public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer) { // CraftBukkit - return string // Paper - return Component
ServerLevel worldserver = entityplayer.serverLevel();
entityplayer.awardStat(Stats.LEAVE_GAME);
@@ -0,0 +0,0 @@ public abstract class PlayerList {
entityplayer.closeContainer();
}
@ -2795,6 +2804,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit
}
}
@@ -0,0 +0,0 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
// CraftBukkit start
Player player1 = ((ServerPlayer) player).getBukkitEntity();
- String[] lines = new String[4];
+ // Paper start
+ List<net.kyori.adventure.text.Component> lines = new java.util.ArrayList<>();
for (int j = 0; j < messages.size(); ++j) {
- lines[j] = CraftChatMessage.fromComponent(text.getMessage(j, player.isTextFilteringEnabled()));
+ lines.add(io.papermc.paper.adventure.PaperAdventure.asAdventure(text.getMessage(j, player.isTextFilteringEnabled())));
}
SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player1, lines);
player.level().getCraftServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
- Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines());
- for (int j = 0; j < components.length; j++) {
- text = text.setMessage(j, components[j]);
+ // Paper start
+ for (int j = 0; j < 4; j++) {
+ text = text.setMessage(j, io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(j)));
}
+ // Paper end
}
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java

View file

@ -408,8 +408,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ 3209,
+ 3214,
+ 3319,
+ 3322
+ // All up to 1.19.4
+ 3322,
+ 3438,
+ 3439,
+ 3440,
+ 3441,
+ 3447,
+ 3448,
+ 3450,
+ 3451,
+ 3459
+ // All up to 1.20-rc1
+ };
+ Arrays.sort(converterVersions);
+
@ -440,7 +449,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // final release of major version
+ registerBreakpoint(MCVersions.V1_18_2, Integer.MAX_VALUE);
+
+
+ // final release of major version
+ registerBreakpoint(MCVersions.V1_19_4, Integer.MAX_VALUE);
+ }
+
+ static {
@ -1031,6 +1041,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static final int V1_19_4_RC2 = 3335;
+ public static final int V1_19_4_RC3 = 3336;
+ public static final int V1_19_4 = 3337;
+ public static final int V23W12A = 3442;
+ public static final int V23W13A = 3443;
+ public static final int V23W14A = 3445;
+ public static final int V23W16A = 3449;
+ public static final int V23W17A = 3452;
+ public static final int V23W19A = 3453;
+ public static final int V1_20_PRE1 = 3454;
+ public static final int V1_20_PRE2 = 3455;
+ public static final int V1_20_PRE3 = 3456;
+ public static final int V1_20_PRE4 = 3457;
+ public static final int V1_20_PRE5 = 3458;
+ public static final int V1_20_PRE6 = 3460;
+ public static final int V1_20_PRE7 = 3461;
+ public static final int V1_20_RC1 = 3462;
+
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/advancements/ConverterAbstractAdvancementsRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/advancements/ConverterAbstractAdvancementsRename.java
@ -2239,7 +2263,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ public static void register(final int version, final int subVersion, final Function<String, String> renamer) {
+ MCTypeRegistry.ENTITY.addStructureConverter(new DataConverter<>(version) {
+ MCTypeRegistry.ENTITY.addStructureConverter(new DataConverter<>(version, subVersion) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ final String id = data.getString("id");
@ -5307,6 +5331,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // assumes no two or more entries are renamed to a single value, otherwise result will be only one of them will win
+ // and there is no defined winner in such a case
+ public static void renameKeys(final MapType<String> data, final Function<String, String> renamer) {
+ if (data == null) {
+ return;
+ }
+
+ List<String> newKeys = null;
+ List<Object> newValues = null;
+ boolean needsRename = false;
@ -5348,6 +5376,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ // Clobbers anything in toKey if fromKey exists
+ public static void renameSingle(final MapType<String> data, final String fromKey, final String toKey) {
+ if (data == null) {
+ return;
+ }
+
+ final Object value = data.getGeneric(fromKey);
+ if (value != null) {
+ data.remove(fromKey);
@ -5355,6 +5387,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+
+ public static void renameString(final MapType<String> data, final String key, final Function<String, String> renamer) {
+ if (data == null) {
+ return;
+ }
+
+ final String value = data.getString(key);
+ if (value == null) {
+ return;
+ }
+
+ final String renamed = renamer.apply(value);
+ if (renamed == null) {
+ return;
+ }
+
+ data.setString(key, renamed);
+ }
+
+ private RenameHelper() {}
+
+}
@ -6638,6 +6688,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static final MCValueType BIOME = new MCValueType("Biome");
+ public static final MCDataType WORLD_GEN_SETTINGS = new MCDataType("WorldGenSettings");
+ public static final MCValueType GAME_EVENT_NAME = new MCValueType("GameEventName");
+ public static final MCValueType MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST = new MCValueType("MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST");
+
+ static {
+ try {
@ -6846,6 +6897,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ V3326.register();
+ V3327.register();
+ V3328.register();
+ // V1.20
+ V3438.register();
+ V3439.register();
+ V3440.register();
+ V3441.register();
+ V3447.register();
+ V3448.register();
+ V3450.register();
+ V3451.register();
+ V3459.register();
+ }
+
+ private MCTypeRegistry() {}
@ -6968,13 +7029,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ @Override
+ public MapType<String> preHook(final MapType<String> data, final long fromVersion, final long toVersion) {
+ final String id = data.getString(this.path);
+ if (id != null) {
+ final String replace = NamespaceUtil.correctNamespaceOrNull(id);
+ if (replace != null) {
+ data.setString(this.path, replace);
+ }
+ }
+ NamespaceUtil.enforceForPath(data, this.path);
+ return null;
+ }
+
@ -15963,7 +16018,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ case "minecraft:multi_noise": {
+ // preset is absent, no type for namespaced string
+ WalkerUtils.convert(MCTypeRegistry.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, biomeSource, "preset", fromVersion, toVersion);
+
+ // Vanilla's schema is _still_ wrong. It should be DSL.fields("biomes", DSL.list(DSL.fields("biome")))
+ // But it just contains the list part. That obviously can never be the case, because
@ -15975,6 +16030,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ WalkerUtils.convert(MCTypeRegistry.BIOME, biomes.getMap(i), "biome", fromVersion, toVersion);
+ }
+ }
+
+ break;
+ }
+
@ -16088,6 +16144,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ offsetHeightmaps(level);
+ // Difference from DFU: Still convert the Lights data. Just because it's being removed in a later version doesn't mean
+ // that it should be removed here.
+ // Generally, converters act only on the current version to bring it to the next. This principle allows the converter
+ // for the next version to assume that it acts on its current version, not some in-between of the current version
+ // and some future version that did not exist at the time it was written. This allows converters to be written and tested
+ // only with knowledge of the current version and the next version.
+ addEmptyListPadding(level, "Lights");
+ addEmptyListPadding(level, "LiquidsToBeTicked");
+ addEmptyListPadding(level, "PostProcessing");
@ -17454,69 +17516,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.converters.chunk.ConverterAddBlendingData;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.types.MapType;
+import ca.spottedleaf.dataconverter.types.Types;
+import ca.spottedleaf.dataconverter.util.NamespaceUtil;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class V3088 {
+
+ // this class originally targeted 3079 but was changed to target a later version without changing the converter, zero clue why
+ // this class then targeted 3088 but was changed to target 3441
+ // to maintain integrity of the data version, I chose to extract the converter to a separate class and use it in both versions
+ // the reason it is important to never change old converters once released is that it creates _two_ versions under the same id.
+ // Consider the case where a user force upgrades their world, but does not load the chunk. Then, consider the case where
+ // the user does not force upgrade their world. Then, Mojang comes along and makes a decision like this and now both
+ // players load the chunk - they went through a different conversion process, which ultimately creates two versions.
+ // Unfortunately this fix doesn't exactly resolve it, as anyone running Mojang's converters will now be different
+ // from DataConverter's. It's broadly a dumb situation all around that could be avoided if Mojang wasn't being careless here.
+ protected static final int VERSION = MCVersions.V22W14A;
+
+ private static final Set<String> STATUSES_TO_SKIP_BLENDING = new HashSet<>(
+ Arrays.asList(
+ "minecraft:empty",
+ "minecraft:structure_starts",
+ "minecraft:structure_references",
+ "minecraft:biomes"
+ )
+ );
+
+ public static void register() {
+ MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) {
+
+ private static MapType<String> createBlendingData(final int height, final int minY) {
+ final MapType<String> ret = Types.NBT.createEmptyMap();
+
+ ret.setInt("min_section", minY >> 4);
+ ret.setInt("max_section", (minY + height) >> 4);
+
+ return ret;
+ }
+
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ data.remove("blending_data");
+ final MapType<String> context = data.getMap("__context");
+ if (!"minecraft:overworld".equals(context == null ? null : context.getString("dimension"))) {
+ return null;
+ }
+
+ final String status = NamespaceUtil.correctNamespace(data.getString("Status"));
+ if (status == null) {
+ return null;
+ }
+
+ final MapType<String> belowZeroRetrogen = data.getMap("below_zero_retrogen");
+
+ if (!STATUSES_TO_SKIP_BLENDING.contains(status)) {
+ data.setMap("blending_data", createBlendingData(384, -64));
+ } else if (belowZeroRetrogen != null) {
+ final String realStatus = NamespaceUtil.correctNamespace(belowZeroRetrogen.getString("target_status", "empty"));
+ if (!STATUSES_TO_SKIP_BLENDING.contains(realStatus)) {
+ data.setMap("blending_data", createBlendingData(256, 0));
+ }
+ }
+
+ return null;
+ }
+ });
+ MCTypeRegistry.CHUNK.addStructureConverter(new ConverterAddBlendingData(VERSION));
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3090.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3090.java
@ -18556,6 +18574,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:bee_nest", "minecraft:beehive");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:beehive", "minecraft:beehive");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:sculk_sensor", "minecraft:sculk_sensor");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:decorated_pot", "minecraft:decorated_pot");
+
+ // These are missing from Vanilla (TODO check on update)
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:enchanting_table", "minecraft:enchanting_table");
@ -18579,10 +18598,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:crimson_hanging_sign", "minecraft:sign");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:warped_hanging_sign", "minecraft:sign");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:piglin_head", "minecraft:skull");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:suspicious_sand", "minecraft:suspicious_sand");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:decorated_pot", "minecraft:decorated_pot");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:suspicious_sand", "minecraft:brushable_block"); // note: this was renamed in the past, see special case in the itemstack walker
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:cherry_sign", "minecraft:sign");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:cherry_hanging_sign", "minecraft:sign");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:suspicious_gravel", "minecraft:brushable_block");
+ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:calibrated_sculk_sensor", "minecraft:calibrated_sculk_sensor");
+ }
+
+ // This class is responsible for also integrity checking the item id to tile id map here, we just use the item registry to figure it out
@ -18752,7 +18772,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ MapType<String> blockEntityTag = tag.getMap("BlockEntityTag");
+ if (blockEntityTag != null) {
+ final String itemId = data.getString("id");
+ final String entityId = ITEM_ID_TO_TILE_ENTITY_ID.get(itemId);
+ final String entityId;
+ if ("minecraft:suspicious_sand".equals(itemId) && fromVersion < V3438.VERSION) {
+ // renamed after this version, and since the id is a mapping to just string we need to special case this
+ entityId = "minecraft:suspicious_sand";
+ } else {
+ entityId = ITEM_ID_TO_TILE_ENTITY_ID.get(itemId);
+ }
+ final boolean removeId;
+ if (entityId == null) {
+ if (!"minecraft:air".equals(itemId)) {
@ -23077,12 +23103,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@
+package ca.spottedleaf.dataconverter.util;
+
+import ca.spottedleaf.dataconverter.types.MapType;
+import net.minecraft.resources.ResourceLocation;
+
+public final class NamespaceUtil {
+
+ private NamespaceUtil() {}
+
+ public static void enforceForPath(final MapType<String> data, final String path) {
+ if (data == null) {
+ return;
+ }
+
+ final String id = data.getString(path);
+ if (id != null) {
+ final String replace = NamespaceUtil.correctNamespaceOrNull(id);
+ if (replace != null) {
+ data.setString(path, replace);
+ }
+ }
+ }
+
+ public static String correctNamespace(final String value) {
+ if (value == null) {
+ return null;
@ -23099,12 +23140,648 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return correct.equals(value) ? null : correct;
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/converters/chunk/ConverterAddBlendingData.java b/src/main/java/ca/spottedleaf/minecraft/converters/chunk/ConverterAddBlendingData.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/converters/chunk/ConverterAddBlendingData.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.converters.chunk;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.types.MapType;
+import ca.spottedleaf.dataconverter.types.Types;
+import ca.spottedleaf.dataconverter.util.NamespaceUtil;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class ConverterAddBlendingData extends DataConverter<MapType<String>, MapType<String>> {
+
+ private static final Set<String> STATUSES_TO_SKIP_BLENDING = new HashSet<>(
+ Arrays.asList(
+ "minecraft:empty",
+ "minecraft:structure_starts",
+ "minecraft:structure_references",
+ "minecraft:biomes"
+ )
+ );
+
+ public ConverterAddBlendingData(final int toVersion) {
+ super(toVersion);
+ }
+
+ public ConverterAddBlendingData(final int toVersion, final int versionStep) {
+ super(toVersion, versionStep);
+ }
+
+ private static MapType<String> createBlendingData(final int height, final int minY) {
+ final MapType<String> ret = Types.NBT.createEmptyMap();
+
+ ret.setInt("min_section", minY >> 4);
+ ret.setInt("max_section", (minY + height) >> 4);
+
+ return ret;
+ }
+
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ data.remove("blending_data");
+ final MapType<String> context = data.getMap("__context");
+ if (!"minecraft:overworld".equals(context == null ? null : context.getString("dimension"))) {
+ return null;
+ }
+
+ final String status = NamespaceUtil.correctNamespace(data.getString("Status"));
+ if (status == null) {
+ return null;
+ }
+
+ final MapType<String> belowZeroRetrogen = data.getMap("below_zero_retrogen");
+
+ if (!STATUSES_TO_SKIP_BLENDING.contains(status)) {
+ data.setMap("blending_data", createBlendingData(384, -64));
+ } else if (belowZeroRetrogen != null) {
+ final String realStatus = NamespaceUtil.correctNamespace(belowZeroRetrogen.getString("target_status", "empty"));
+ if (!STATUSES_TO_SKIP_BLENDING.contains(realStatus)) {
+ data.setMap("blending_data", createBlendingData(256, 0));
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/converters/chunk/ConverterRenameStatus.java b/src/main/java/ca/spottedleaf/minecraft/converters/chunk/ConverterRenameStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/converters/chunk/ConverterRenameStatus.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.converters.chunk;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper;
+import ca.spottedleaf.dataconverter.types.MapType;
+import ca.spottedleaf.dataconverter.util.NamespaceUtil;
+import java.util.function.Function;
+
+public final class ConverterRenameStatus extends DataConverter<MapType<String>, MapType<String>> {
+
+ private final Function<String, String> renamer;
+
+ public ConverterRenameStatus(final int toVersion, final Function<String, String> renamer) {
+ this(toVersion, 0, renamer);
+ }
+
+ public ConverterRenameStatus(final int toVersion, final int versionStep, final Function<String, String> renamer) {
+ super(toVersion, versionStep);
+ this.renamer = renamer;
+ }
+
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ // Note: DFU technically enforces namespace due to how they wrote their converter, so we will do the same.
+ NamespaceUtil.enforceForPath(data, "Status");
+ RenameHelper.renameString(data, "Status", this.renamer);
+
+ NamespaceUtil.enforceForPath(data.getMap("below_zero_retrogen"), "target_status");
+ RenameHelper.renameString(data.getMap("below_zero_retrogen"), "target_status", this.renamer);
+ return null;
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/converters/leveldat/ConverterRemoveFeatureFlag.java b/src/main/java/ca/spottedleaf/minecraft/converters/leveldat/ConverterRemoveFeatureFlag.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/converters/leveldat/ConverterRemoveFeatureFlag.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.converters.leveldat;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.types.ListType;
+import ca.spottedleaf.dataconverter.types.MapType;
+import ca.spottedleaf.dataconverter.types.ObjectType;
+import java.util.Set;
+
+public final class ConverterRemoveFeatureFlag extends DataConverter<MapType<String>, MapType<String>> {
+
+ private final Set<String> flags;
+
+ public ConverterRemoveFeatureFlag(final int toVersion, final Set<String> flags) {
+ this(toVersion, 0, flags);
+ }
+
+ public ConverterRemoveFeatureFlag(final int toVersion, final int versionStep, final Set<String> flags) {
+ super(toVersion, versionStep);
+ this.flags = flags;
+ }
+
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ final ListType enabledFeatures = data.getList("enabled_features", ObjectType.STRING);
+ if (enabledFeatures == null) {
+ return null;
+ }
+
+ ListType removedFeatures = null;
+
+ for (int i = 0; i < enabledFeatures.size(); ++i) {
+ final String flag = enabledFeatures.getString(i);
+ if (!this.flags.contains(flag)) {
+ continue;
+ }
+ enabledFeatures.remove(i--);
+
+ if (removedFeatures == null) {
+ removedFeatures = data.getOrCreateList("removed_features", ObjectType.STRING);
+ }
+ removedFeatures.addString(flag);
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/converters/tileentity/ConverterAbstractTileEntityRename.java b/src/main/java/ca/spottedleaf/minecraft/converters/tileentity/ConverterAbstractTileEntityRename.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/converters/tileentity/ConverterAbstractTileEntityRename.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.converters.tileentity;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.types.MapType;
+import java.util.function.Function;
+
+public final class ConverterAbstractTileEntityRename {
+
+ public static void register(final int version, final Function<String, String> renamer) {
+ register(version, 0, renamer);
+ }
+
+ public static void register(final int version, final int subVersion, final Function<String, String> renamer) {
+ MCTypeRegistry.TILE_ENTITY.addStructureConverter(new DataConverter<>(version, subVersion) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ final String id = data.getString("id");
+ if (id == null) {
+ return null;
+ }
+
+ final String converted = renamer.apply(id);
+
+ if (converted != null) {
+ data.setString("id", converted);
+ }
+
+ return null;
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3438.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3438.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3438.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper;
+import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename;
+import ca.spottedleaf.minecraft.converters.tileentity.ConverterAbstractTileEntityRename;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.types.MapType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class V3438 {
+
+ public static final int VERSION = MCVersions.V1_19_4 + 101;
+
+ public static void register() {
+ // brushable block rename
+ MCTypeRegistry.TILE_ENTITY.copyWalkers(VERSION,"minecraft:suspicious_sand", "minecraft:brushable_block");
+
+ ConverterAbstractTileEntityRename.register(VERSION, new HashMap<>(Map.of(
+ "minecraft:suspicious_sand", "minecraft:brushable_block"
+ ))::get);
+
+
+ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:brushable_block", new DataConverter<>(VERSION) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ RenameHelper.renameSingle(data, "loot_table", "LootTable");
+ RenameHelper.renameSingle(data, "loot_table_seed", "LootTableSeed");
+ return null;
+ }
+ });
+
+ ConverterAbstractItemRename.register(VERSION, new HashMap<>(
+ Map.of(
+ "minecraft:pottery_shard_archer", "minecraft:archer_pottery_shard",
+ "minecraft:pottery_shard_prize", "minecraft:prize_pottery_shard",
+ "minecraft:pottery_shard_arms_up", "minecraft:arms_up_pottery_shard",
+ "minecraft:pottery_shard_skull", "minecraft:skull_pottery_shard"
+ )
+ )::get);
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3439.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3439.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3439.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.types.ListType;
+import ca.spottedleaf.dataconverter.types.MapType;
+import net.minecraft.network.chat.CommonComponents;
+import net.minecraft.network.chat.Component;
+
+public final class V3439 {
+
+ private static final int VERSION = MCVersions.V1_19_4 + 102;
+
+ public static void register() {
+ final DataConverter<MapType<String>, MapType<String>> signTileUpdater = new DataConverter<>(VERSION) {
+ private static final String BLANK_TEXT_LINE = Component.Serializer.toJson(CommonComponents.EMPTY);
+ private static final String DEFAULT_COLOR = "black";
+
+ private static ListType migrateToList(final MapType<String> root, final String prefix) {
+ if (root == null) {
+ return null;
+ }
+
+ final ListType ret = root.getTypeUtil().createEmptyList();
+
+ ret.addString(root.getString(prefix.concat("1"), BLANK_TEXT_LINE));
+ ret.addString(root.getString(prefix.concat("2"), BLANK_TEXT_LINE));
+ ret.addString(root.getString(prefix.concat("3"), BLANK_TEXT_LINE));
+ ret.addString(root.getString(prefix.concat("4"), BLANK_TEXT_LINE));
+
+ return ret;
+ }
+
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ final MapType<String> frontText = data.getTypeUtil().createEmptyMap();
+ data.setMap("front_text", frontText);
+
+ frontText.setList("messages", migrateToList(data, "Text"));
+ frontText.setList("filtered_messages", migrateToList(data, "FilteredText"));
+ frontText.setString("color", data.getString("Color", DEFAULT_COLOR));
+ frontText.setBoolean("has_glowing_text", data.getBoolean("GlowingText", false));
+
+ final MapType<String> backText = data.getTypeUtil().createEmptyMap();
+ data.setMap("back_text", backText);
+
+ final ListType blankMessages = data.getTypeUtil().createEmptyList();
+ for (int i = 0; i < 4; ++i) {
+ blankMessages.addString(BLANK_TEXT_LINE);
+ }
+
+ backText.setList("messages", blankMessages);
+ backText.setList("filtered_messages", blankMessages.copy()); // need to copy so that the value isn't mapped to twice, so that updates to one do not reflect in the other
+ backText.setString("color", DEFAULT_COLOR);
+ backText.setBoolean("has_glowing_text", false);
+
+ return null;
+ }
+ };
+
+ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:sign", signTileUpdater);
+ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:hanging_sign", signTileUpdater);
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3440.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3440.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3440.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.converters.helpers.ConverterAbstractStringValueTypeRename;
+import ca.spottedleaf.minecraft.converters.leveldat.ConverterRemoveFeatureFlag;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.util.NamespaceUtil;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public final class V3440 {
+
+ private static final int VERSION = MCVersions.V1_19_4 + 103;
+
+ public static void register() {
+ // Note: MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST is namespaced string
+ ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, (final String in) -> {
+ return "minecraft:overworld_update_1_20".equals(NamespaceUtil.correctNamespace(in)) ? "minecraft:overworld" : null;
+ });
+ MCTypeRegistry.LEVEL.addStructureConverter(new ConverterRemoveFeatureFlag(VERSION, new HashSet<>(
+ Arrays.asList(
+ "minecraft:update_1_20"
+ )
+ )));
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3441.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3441.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3441.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.minecraft.converters.chunk.ConverterAddBlendingData;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+
+public final class V3441 {
+
+ private static final int VERSION = MCVersions.V1_19_4 + 104;
+
+ public static void register() {
+ // See V3088 for why this converter is duplicated here and in V3088
+ MCTypeRegistry.CHUNK.addStructureConverter(new ConverterAddBlendingData(VERSION));
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3447.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3447.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3447.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class V3447 {
+
+ private static final int VERSION = MCVersions.V23W14A + 2;
+
+ public static void register() {
+ final String[] targets = new String[] {
+ "minecraft:angler_pottery_shard",
+ "minecraft:archer_pottery_shard",
+ "minecraft:arms_up_pottery_shard",
+ "minecraft:blade_pottery_shard",
+ "minecraft:brewer_pottery_shard",
+ "minecraft:burn_pottery_shard",
+ "minecraft:danger_pottery_shard",
+ "minecraft:explorer_pottery_shard",
+ "minecraft:friend_pottery_shard",
+ "minecraft:heart_pottery_shard",
+ "minecraft:heartbreak_pottery_shard",
+ "minecraft:howl_pottery_shard",
+ "minecraft:miner_pottery_shard",
+ "minecraft:mourner_pottery_shard",
+ "minecraft:plenty_pottery_shard",
+ "minecraft:prize_pottery_shard",
+ "minecraft:sheaf_pottery_shard",
+ "minecraft:shelter_pottery_shard",
+ "minecraft:skull_pottery_shard",
+ "minecraft:snort_pottery_shard"
+ };
+ // shard->sherd
+ final Map<String, String> rename = new HashMap<>(targets.length);
+
+ for (final String target : targets) {
+ final String replace = target.replace("_pottery_shard", "_pottery_sherd");
+ if (rename.put(target, replace) != null) {
+ throw new IllegalArgumentException("Duplicate target " + target);
+ }
+ }
+
+ ConverterAbstractItemRename.register(VERSION, rename::get);
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3448.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3448.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3448.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerListPaths;
+import ca.spottedleaf.dataconverter.types.MapType;
+
+public final class V3448 {
+
+ private static final int VERSION = MCVersions.V23W14A + 3;
+
+ public static void register() {
+ MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:decorated_pot", new DataWalkerListPaths<>(MCTypeRegistry.ITEM_NAME, "sherds"));
+ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:decorated_pot", new DataConverter<>(VERSION) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ RenameHelper.renameSingle(data, "shards", "sherds");
+ return null;
+ }
+ });
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3450.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3450.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3450.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.minecraft.converters.chunk.ConverterRenameStatus;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class V3450 {
+
+ private static final int VERSION = MCVersions.V23W16A + 1;
+
+ public static void register() {
+ MCTypeRegistry.CHUNK.addStructureConverter(new ConverterRenameStatus(VERSION, new HashMap<>(
+ Map.of(
+ "minecraft:liquid_carvers", "minecraft:carvers",
+ "minecraft:heightmaps", "minecraft:spawn"
+ )
+ )::get));
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3451.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3451.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3451.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.types.ListType;
+import ca.spottedleaf.dataconverter.types.MapType;
+import ca.spottedleaf.dataconverter.types.ObjectType;
+
+public final class V3451 {
+
+ private static final int VERSION = MCVersions.V23W16A + 2;
+
+ public static void register() {
+ MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ data.remove("isLightOn");
+
+ final ListType sections = data.getList("sections", ObjectType.MAP);
+ if (sections == null) {
+ return null;
+ }
+
+ for (int i = 0, len = sections.size(); i < len; ++i) {
+ final MapType<String> section = sections.getMap(i);
+
+ section.remove("BlockLight");
+ section.remove("SkyLight");
+ }
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/minecraft/versions/V3459.java b/src/main/java/ca/spottedleaf/minecraft/versions/V3459.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/minecraft/versions/V3459.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
+import ca.spottedleaf.dataconverter.types.MapType;
+
+public final class V3459 {
+
+ private static final int VERSION = MCVersions.V1_20_PRE5 + 1;
+
+ public static void register() {
+ MCTypeRegistry.LEVEL.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
+ if (data.hasKey("DragonFight")) {
+ return null;
+ }
+
+ final MapType<String> dimensionData = data.getMap("DimensionData");
+ if (dimensionData == null) {
+ return null;
+ }
+
+ final MapType<String> endData = dimensionData.getMap("1");
+ if (endData != null) {
+ data.setMap("DragonFight", endData.getMap("DragonFight", endData.getTypeUtil().createEmptyMap()));
+ }
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/mixin/PrintTheFuckingErrorJesusChristMixin.java b/src/main/java/ca/spottedleaf/mixin/PrintTheFuckingErrorJesusChristMixin.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/mixin/PrintTheFuckingErrorJesusChristMixin.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.mixin;
+
+import com.mojang.datafixers.DataFixer;
+import com.mojang.datafixers.util.Either;
+import net.minecraft.ReportedException;
+import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkMap;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.storage.ChunkStorage;
+import org.slf4j.Logger;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Overwrite;
+import org.spongepowered.asm.mixin.Shadow;
+import java.io.IOException;
+import java.nio.file.Path;
+
+@Mixin(ChunkMap.class)
+public abstract class PrintTheFuckingErrorJesusChristMixin extends ChunkStorage implements ChunkHolder.PlayerProvider {
+
+ @Shadow
+ protected abstract void markPositionReplaceable(ChunkPos chunkPos);
+
+ @Shadow
+ @Final
+ private static Logger LOGGER;
+
+ @Shadow
+ protected abstract ChunkAccess createEmptyChunk(ChunkPos chunkPos);
+
+ public PrintTheFuckingErrorJesusChristMixin(Path path, DataFixer dataFixer, boolean bl) {
+ super(path, dataFixer, bl);
+ }
+
+ /**
+ * @reason Print the fucking exception jesus christ how hard is it:
+ * 1. handle or
+ * 2. print or
+ * 3. rethrow
+ * @author Spottedleaf
+ */
+ @Overwrite
+ private Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> handleChunkLoadFailure(Throwable throwable, ChunkPos chunkPos) {
+ if (throwable instanceof ReportedException reportedException) {
+ Throwable throwable2 = reportedException.getCause();
+ if (!(throwable2 instanceof IOException)) {
+ this.markPositionReplaceable(chunkPos);
+ throw reportedException;
+ }
+
+ LOGGER.error("Couldn't load chunk {}", chunkPos, throwable2);
+ } else if (throwable instanceof IOException) {
+ LOGGER.error("Couldn't load chunk {}", chunkPos, throwable);
+ }
+
+ LOGGER.error("Couldn't load chunk {} (Vanilla swallowed exception)", chunkPos, throwable);
+
+ return Either.left(this.createEmptyChunk(chunkPos));
+ }
+}
diff --git a/src/main/java/net/minecraft/data/structures/StructureUpdater.java b/src/main/java/net/minecraft/data/structures/StructureUpdater.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/data/structures/StructureUpdater.java
+++ b/src/main/java/net/minecraft/data/structures/StructureUpdater.java
@@ -0,0 +0,0 @@ public class StructureUpdater implements SnbtToNbt.Filter {
LOGGER.warn("SNBT Too old, do not forget to update: {} < {}: {}", i, 3318, name);
LOGGER.warn("SNBT Too old, do not forget to update: {} < {}: {}", i, 3437, name);
}
- CompoundTag compoundTag = DataFixTypes.STRUCTURE.updateToCurrentVersion(DataFixers.getDataFixer(), nbt, i);

View file

@ -218,58 +218,49 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.performLightDecrease(lightAccess);
+ }
+
+ protected Iterator<BlockPos> getSources(final LightChunkGetter lightAccess, final ChunkAccess chunk) {
+ if (chunk instanceof ImposterProtoChunk || chunk instanceof LevelChunk) {
+ // implementation on Chunk is pretty awful, so write our own here. The big optimisation is
+ // skipping empty sections, and the far more optimised reading of types.
+ List<BlockPos> sources = new ArrayList<>();
+ protected List<BlockPos> getSources(final LightChunkGetter lightAccess, final ChunkAccess chunk) {
+ final List<BlockPos> sources = new ArrayList<>();
+
+ int offX = chunk.getPos().x << 4;
+ int offZ = chunk.getPos().z << 4;
+ final int offX = chunk.getPos().x << 4;
+ final int offZ = chunk.getPos().z << 4;
+
+ final LevelChunkSection[] sections = chunk.getSections();
+ for (int sectionY = this.minSection; sectionY <= this.maxSection; ++sectionY) {
+ final LevelChunkSection section = sections[sectionY - this.minSection];
+ if (section == null || section.hasOnlyAir()) {
+ // no sources in empty sections
+ continue;
+ }
+ final PalettedContainer<BlockState> states = section.states;
+ final int offY = sectionY << 4;
+
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
+ final BlockState state = states.get(index);
+ if (state.getLightEmission() <= 0) {
+ continue;
+ }
+
+ // index = x | (z << 4) | (y << 8)
+ sources.add(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15)));
+ }
+ final LevelChunkSection[] sections = chunk.getSections();
+ for (int sectionY = this.minSection; sectionY <= this.maxSection; ++sectionY) {
+ final LevelChunkSection section = sections[sectionY - this.minSection];
+ if (section == null || section.hasOnlyAir()) {
+ // no sources in empty sections
+ continue;
+ }
+ if (!section.maybeHas((final BlockState state) -> {
+ return state.getLightEmission() > 0;
+ })) {
+ // no light sources in palette
+ continue;
+ }
+ final PalettedContainer<BlockState> states = section.states;
+ final int offY = sectionY << 4;
+
+ return sources.iterator();
+ } else {
+ // world gen and lighting run in parallel, and if lighting keeps up it can be lighting chunks that are
+ // being generated. In the nether, lava will add a lot of sources. This resulted in quite a few CME crashes.
+ // So all we do spinloop until we can collect a list of sources, and even if it is out of date we will pick up
+ // the missing sources from checkBlock.
+ for (;;) {
+ try {
+ return chunk.getLights().collect(Collectors.toList()).iterator();
+ } catch (final Exception cme) {
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
+ final BlockState state = states.get(index);
+ if (state.getLightEmission() <= 0) {
+ continue;
+ }
+
+ // index = x | (z << 4) | (y << 8)
+ sources.add(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15)));
+ }
+ }
+
+ return sources;
+ }
+
+ @Override
+ public void lightChunk(final LightChunkGetter lightAccess, final ChunkAccess chunk, final boolean needsEdgeChecks) {
+ // setup sources
+ final int emittedMask = this.emittedLightMask;
+ for (final Iterator<BlockPos> positions = this.getSources(lightAccess, chunk); positions.hasNext();) {
+ final BlockPos pos = positions.next();
+ final List<BlockPos> positions = this.getSources(lightAccess, chunk);
+ for (int i = 0, len = positions.size(); i < len; ++i) {
+ final BlockPos pos = positions.get(i);
+ final BlockState blockState = this.getBlockState(pos.getX(), pos.getY(), pos.getZ());
+ final int emittedLight = blockState.getLightEmission() & emittedMask;
+
@ -1537,7 +1528,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.nms = Direction.fromNormal(x, y, z);
+ this.nms = Direction.fromDelta(x, y, z);
+ this.everythingButThisDirection = (long)(ALL_DIRECTIONS_BITSET ^ (1 << this.ordinal()));
+ // positive is always even, negative is always odd. Flip the 1 bit to get the negative direction.
+ this.everythingButTheOppositeDirection = (long)(ALL_DIRECTIONS_BITSET ^ (1 << (this.ordinal() ^ 1)));
@ -3134,8 +3125,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ @Override
+ public void onBlockEmissionIncrease(final BlockPos blockPos, final int i) {
+ // skylight doesn't care
+ public void propagateLightSources(final ChunkPos chunkPos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
@ -3145,12 +3136,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ @Override
+ public int runUpdates(final int i, final boolean bl, final boolean bl2) {
+ public int runLightUpdates() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableLightSources(final ChunkPos chunkPos, final boolean bl) {
+ public void setLightEnabled(final ChunkPos chunkPos, final boolean bl) {
+ throw new UnsupportedOperationException();
+ }
+
@ -3191,8 +3182,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ @Override
+ public void onBlockEmissionIncrease(final BlockPos blockPos, final int i) {
+ this.checkBlock(blockPos);
+ public void propagateLightSources(final ChunkPos chunkPos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
@ -3202,12 +3193,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ @Override
+ public int runUpdates(final int i, final boolean bl, final boolean bl2) {
+ public int runLightUpdates() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableLightSources(final ChunkPos chunkPos, final boolean bl) {
+ public void setLightEnabled(final ChunkPos chunkPos, final boolean bl) {
+ throw new UnsupportedOperationException();
+ }
+
@ -3234,6 +3225,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ };
+ }
+
+ public boolean hasSkyLight() {
+ return this.hasSkyLight;
+ }
+
+ public boolean hasBlockLight() {
+ return this.hasBlockLight;
+ }
+
+ protected int getSkyLightValue(final BlockPos blockPos, final ChunkAccess chunk) {
+ if (!this.hasSkyLight) {
+ return 0;
@ -4103,7 +4102,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ private static final Logger LOGGER = LogUtils.getLogger();
+
+ private static final int STARLIGHT_LIGHT_VERSION = 8;
+ private static final int STARLIGHT_LIGHT_VERSION = 9;
+
+ public static int getLightVersion() {
+ return STARLIGHT_LIGHT_VERSION;
@ -4522,10 +4521,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+// Paper end
+
public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCloseable {
public static final int DEFAULT_BATCH_SIZE = 1000;
private static final Logger LOGGER = LogUtils.getLogger();
private final ProcessorMailbox<Runnable> taskMailbox;
@@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
private volatile int taskPerBatch = 5;
private final int taskPerBatch = 1000;
private final AtomicBoolean scheduled = new AtomicBoolean();
+ // Paper start - replace light engine impl
@ -4550,8 +4549,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start - replace light engine impl
+ protected final ChunkAccess getChunk(final int chunkX, final int chunkZ) {
+ return ((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().getChunkAtImmediately(chunkX, chunkZ);
}
+ }
+
+ protected long relightCounter;
+
+ public int relight(java.util.Set<ChunkPos> chunks_param,
@ -4674,18 +4673,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (sky == 15) return 15;
+ final int block = this.theLightEngine.getBlockReader().getLightValue(pos);
+ return Math.max(sky, block);
+ }
}
+ // Paper end - replace light engine imp
+
@Override
public void close() {
}
@@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void checkBlock(BlockPos pos) {
- BlockPos blockPos = pos.immutable();
- this.addTask(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ThreadedLevelLightEngine.TaskType.POST_UPDATE, Util.name(() -> {
- this.addTask(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
- super.checkBlock(blockPos);
- }, () -> {
- return "checkBlock " + blockPos;
@ -4722,15 +4720,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
@Override
public void enableLightSources(ChunkPos pos, boolean retainData) {
public void propagateLightSources(ChunkPos chunkPos) {
+ if (true) return; // Paper - replace light engine impl
this.addTask(pos.x, pos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
super.enableLightSources(pos, retainData);
this.addTask(chunkPos.x, chunkPos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
super.propagateLightSources(chunkPos);
}, () -> {
@@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void queueSectionData(LightLayer lightType, SectionPos pos, @Nullable DataLayer nibbles, boolean nonEdge) {
public void setLightEnabled(ChunkPos pos, boolean retainData) {
+ if (true) return; // Paper - replace light engine impl
this.addTask(pos.x, pos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
super.setLightEnabled(pos, retainData);
}, () -> {
@@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void queueSectionData(LightLayer lightType, SectionPos pos, @Nullable DataLayer nibbles) {
+ if (true) return; // Paper - replace light engine impl
this.addTask(pos.x(), pos.z(), () -> {
return 0;
@ -4746,6 +4752,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
}
public CompletableFuture<ChunkAccess> initializeLight(ChunkAccess chunk, boolean bl) {
+ if (true) return CompletableFuture.completedFuture(chunk); // Paper - replace light engine impl
ChunkPos chunkPos = chunk.getPos();
this.addTask(chunkPos.x, chunkPos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
LevelChunkSection[] levelChunkSections = chunk.getSections();
@@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
}
public CompletableFuture<ChunkAccess> lightChunk(ChunkAccess chunk, boolean excludeBlocks) {
+ // Paper start - replace light engine impl
+ if (true) {
@ -4794,7 +4808,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
objectListIterator.back(j);
- super.runUpdates(Integer.MAX_VALUE, true, true);
- super.runLightUpdates();
+ this.theLightEngine.propagateChanges(); // Paper - rewrite light engine
for(int var5 = 0; objectListIterator.hasNext() && var5 < i; ++var5) {
@ -4816,13 +4830,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
this.emissiveRendering = blockbase_info.emissiveRendering;
this.offsetFunction = blockbase_info.offsetFunction;
this.spawnParticlesOnBreak = blockbase_info.spawnParticlesOnBreak;
this.instrument = blockbase_info.instrument;
this.replaceable = blockbase_info.replaceable;
+ this.conditionallyFullOpaque = this.isOpaque() & this.isTransparentOnSomeFaces(); // Paper
}
// Paper start
private boolean calculateSolid() {
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.shapeExceedsCube;
}
@ -4848,8 +4862,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.shapeExceedsCube = this.cache == null || this.cache.largeCollisionShape; // Paper - moved from actual method to here
+ this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque() ? -1 : this.cache.lightBlock; // Paper - starlight - cache opacity for light
this.legacySolid = this.calculateSolid();
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@ -4900,7 +4914,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - rewrite light engine
public ChunkAccess(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biome, long inhabitedTime, @Nullable LevelChunkSection[] sectionArrayInitializer, @Nullable BlendingData blendingData) {
public ChunkAccess(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] sectionArray, @Nullable BlendingData blendingData) {
this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field lookups
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -4974,8 +4988,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -0,0 +0,0 @@ public class ImposterProtoChunk extends ProtoChunk {
private final LevelChunk wrapped;
private final boolean allowWrites;
this.allowWrites = propagateToWrapped;
}
+ // Paper start - rewrite light engine
+ @Override
@ -5019,9 +5033,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - rewrite light engine
+
public ImposterProtoChunk(LevelChunk wrapped, boolean bl) {
super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.levelHeightAccessor, wrapped.getLevel().registryAccess().registryOrThrow(Registries.BIOME), wrapped.getBlendingData());
this.wrapped = wrapped;
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@ -5035,8 +5049,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.setSkyNibbles(ca.spottedleaf.starlight.common.light.StarLightEngine.getFilledEmptyLight(world));
+ // Paper end - rewrite light engine
this.tickersInLevel = Maps.newHashMap();
this.clientLightReady = false;
this.level = (ServerLevel) world; // CraftBukkit - type
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap();
@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess {
public LevelChunk(ServerLevel world, ProtoChunk protoChunk, @Nullable LevelChunk.PostLoadProcessor entityLoader) {
@ -5089,7 +5103,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static final String SKY_LIGHT_TAG = "SkyLight";
+ // Paper start - replace light engine impl
+ private static final int STARLIGHT_LIGHT_VERSION = 8;
+ private static final int STARLIGHT_LIGHT_VERSION = 9;
+
+ private static final String BLOCKLIGHT_STATE_TAG = "starlight.blocklight_state";
+ private static final String SKYLIGHT_STATE_TAG = "starlight.skylight_state";
@ -5110,7 +5124,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
LevelChunkSection[] achunksection = new LevelChunkSection[i];
boolean flag1 = world.dimensionType().hasSkyLight();
ServerChunkCache chunkproviderserver = world.getChunkSource();
LevelLightEngine lightengine = chunkproviderserver.getLightEngine();
LevelLightEngine levellightengine = chunkproviderserver.getLightEngine();
+ // Paper start
+ ca.spottedleaf.starlight.common.light.SWMRNibbleArray[] blockNibbles = ca.spottedleaf.starlight.common.light.StarLightEngine.getFilledEmptyLight(world);
+ ca.spottedleaf.starlight.common.light.SWMRNibbleArray[] skyNibbles = ca.spottedleaf.starlight.common.light.StarLightEngine.getFilledEmptyLight(world);
@ -5136,7 +5150,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (flag3 || flag4) {
- if (!flag2) {
- lightengine.retainData(chunkPos, true);
- levellightengine.retainData(chunkPos, true);
- flag2 = true;
- }
-
@ -5146,7 +5160,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ int y = sectionData.getByte("Y");
+ // Paper end - rewrite the light engine
if (flag3) {
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")), true);
- levellightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")));
+ // Paper start - rewrite the light engine
+ // this is where our diff is
+ blockNibbles[y - minSection] = new ca.spottedleaf.starlight.common.light.SWMRNibbleArray(sectionData.getByteArray("BlockLight").clone(), sectionData.getInt(BLOCKLIGHT_STATE_TAG)); // clone for data safety
@ -5156,7 +5170,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
if (flag4) {
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")), true);
- levellightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")));
+ // Paper start - rewrite the light engine
+ // we store under the same key so mod programs editing nbt
+ // can still read the data, hopefully.