diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/DerivedWorldInfoBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/DerivedWorldInfoBridge.java new file mode 100644 index 00000000..b9dd3f14 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/DerivedWorldInfoBridge.java @@ -0,0 +1,8 @@ +package io.izzel.arclight.common.bridge.world.storage; + +import net.minecraft.world.dimension.DimensionType; + +public interface DerivedWorldInfoBridge { + + void bridge$setDimension(DimensionType dimensionType); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/SaveHandlerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/SaveHandlerBridge.java index 7d370a60..f293cd0c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/SaveHandlerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/storage/SaveHandlerBridge.java @@ -1,6 +1,7 @@ package io.izzel.arclight.common.bridge.world.storage; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.world.server.ServerWorld; import java.io.File; import java.util.UUID; @@ -9,7 +10,7 @@ public interface SaveHandlerBridge { String[] bridge$getSeenPlayers(); - UUID bridge$getUUID(); + UUID bridge$getUUID(ServerWorld world); File bridge$getPlayerDir(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftWorldMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftWorldMixin.java index 0158bad9..0b170a87 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftWorldMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftWorldMixin.java @@ -2,20 +2,31 @@ package io.izzel.arclight.common.mixin.bukkit; import io.izzel.arclight.common.bridge.bukkit.EntityTypeBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge; +import io.izzel.arclight.common.bridge.world.storage.SaveHandlerBridge; +import net.minecraft.world.server.ServerWorld; import org.bukkit.Location; import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +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 org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.io.File; +import java.util.UUID; import java.util.function.Function; @Mixin(value = CraftWorld.class, remap = false) public class CraftWorldMixin { + // @formatter:off + @Shadow @Final private ServerWorld world; + // @formatter:on + @Inject(method = "spawnEntity", cancellable = true, at = @At("HEAD")) private void arclight$useFactory(Location loc, EntityType entityType, CallbackInfoReturnable cir) { Function factory = ((EntityTypeBridge) (Object) entityType).bridge$entityFactory(); @@ -23,4 +34,22 @@ public class CraftWorldMixin { cir.setReturnValue(((EntityBridge) factory.apply(loc)).bridge$getBukkitEntity()); } } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public UUID getUID() { + return ((SaveHandlerBridge) this.world.getSaveHandler()).bridge$getUUID(this.world); + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public File getWorldFolder() { + return this.world.dimension.getType().getDirectory(this.world.getSaveHandler().getWorldDirectory()); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java index a76ffff6..799dcf1b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java @@ -441,8 +441,8 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Inject(method = "writeWithoutTypeId", at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 0, target = "Lnet/minecraft/nbt/CompoundNBT;putUniqueId(Ljava/lang/String;Ljava/util/UUID;)V")) public void arclight$writeWithoutTypeId$CraftBukkitNBT(CompoundNBT compound, CallbackInfoReturnable cir) { - compound.putLong("WorldUUIDLeast", ((SaveHandlerBridge) (((ServerWorld) this.world).getSaveHandler())).bridge$getUUID().getLeastSignificantBits()); - compound.putLong("WorldUUIDMost", ((SaveHandlerBridge) (((ServerWorld) this.world).getSaveHandler())).bridge$getUUID().getMostSignificantBits()); + compound.putLong("WorldUUIDLeast", ((SaveHandlerBridge) (((ServerWorld) this.world).getSaveHandler())).bridge$getUUID(((ServerWorld) this.world)).getLeastSignificantBits()); + compound.putLong("WorldUUIDMost", ((SaveHandlerBridge) (((ServerWorld) this.world).getSaveHandler())).bridge$getUUID(((ServerWorld) this.world)).getMostSignificantBits()); compound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); compound.putInt("Spigot.ticksLived", this.ticksExisted); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java index f3f6868c..1b2b9f13 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java @@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world; import io.izzel.arclight.api.ArclightVersion; import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge; +import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge; import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -73,7 +74,10 @@ public abstract class WorldMixin implements WorldBridge { @Inject(method = "(Lnet/minecraft/world/storage/WorldInfo;Lnet/minecraft/world/dimension/DimensionType;Ljava/util/function/BiFunction;Lnet/minecraft/profiler/IProfiler;Z)V", at = @At("RETURN")) private void arclight$init(WorldInfo info, DimensionType dimType, BiFunction provider, IProfiler profilerIn, boolean remote, CallbackInfo ci) { - spigotConfig = new SpigotWorldConfig(worldInfo.getWorldName()); + if (info instanceof DerivedWorldInfoBridge) { + ((DerivedWorldInfoBridge) info).bridge$setDimension(dimType); + } + spigotConfig = new SpigotWorldConfig(info.getWorldName()); ((WorldBorderBridge) this.worldBorder).bridge$setWorld((ServerWorld) (Object) this); this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/DerivedWorldInfoMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/DerivedWorldInfoMixin.java new file mode 100644 index 00000000..462eeaf2 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/DerivedWorldInfoMixin.java @@ -0,0 +1,38 @@ +package io.izzel.arclight.common.mixin.core.world.storage; + +import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.storage.DerivedWorldInfo; +import net.minecraft.world.storage.WorldInfo; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(DerivedWorldInfo.class) +public class DerivedWorldInfoMixin implements DerivedWorldInfoBridge { + + // @formatter:off + @Shadow @Final private WorldInfo delegate; + // @formatter:on + + private DimensionType type; + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public String getWorldName() { + if (type == null || type.getId() == 0 || type.directory.isEmpty()) { + return this.delegate.getWorldName(); + } else { + return this.delegate.getWorldName() + "/" + type.directory; + } + } + + @Override + public void bridge$setDimension(DimensionType dimensionType) { + this.type = dimensionType; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/SaveHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/SaveHandlerMixin.java index 6f887880..dca76c8f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/SaveHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/SaveHandlerMixin.java @@ -2,10 +2,13 @@ package io.izzel.arclight.common.mixin.core.world.storage; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.world.storage.SaveHandlerBridge; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.SaveHandler; import org.apache.logging.log4j.Logger; import org.bukkit.craftbukkit.v.entity.CraftPlayer; @@ -33,7 +36,7 @@ public class SaveHandlerMixin implements SaveHandlerBridge { @Shadow @Final private File worldDirectory; // @formatter:on - private UUID uuid; + private final Int2ObjectMap uuidMap = new Int2ObjectOpenHashMap<>(); @Inject(method = "readPlayerData", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundNBT;contains(Ljava/lang/String;I)Z")) public void arclight$lastSeenTime(PlayerEntity player, CallbackInfoReturnable cir) { @@ -64,11 +67,20 @@ public class SaveHandlerMixin implements SaveHandlerBridge { } public UUID getUUID() { + return getUUID(null); + } + + public UUID getUUID(ServerWorld world) { + int dimId = world == null ? 0 : world.dimension.getType().getId(); + UUID uuid = uuidMap.get(dimId); if (uuid != null) return uuid; - File file1 = new File(this.worldDirectory, "uid.dat"); + File folder = world == null ? this.worldDirectory : world.dimension.getType().getDirectory(this.worldDirectory); + File file1 = new File(folder, "uid.dat"); if (file1.exists()) { try (DataInputStream dis = new DataInputStream(new FileInputStream(file1))) { - return uuid = new UUID(dis.readLong(), dis.readLong()); + uuid = new UUID(dis.readLong(), dis.readLong()); + uuidMap.put(dimId, uuid); + return uuid; } catch (IOException ex) { LOGGER.warn("Failed to read " + file1 + ", generating new random UUID", ex); } @@ -80,6 +92,7 @@ public class SaveHandlerMixin implements SaveHandlerBridge { } catch (IOException ex) { LOGGER.warn("Failed to write " + file1, ex); } + uuidMap.put(dimId, uuid); return uuid; } @@ -105,8 +118,8 @@ public class SaveHandlerMixin implements SaveHandlerBridge { } @Override - public UUID bridge$getUUID() { - return getUUID(); + public UUID bridge$getUUID(ServerWorld world) { + return getUUID(world); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java index cc6d9834..1d772133 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java @@ -2,14 +2,12 @@ package io.izzel.arclight.common.mod; import io.izzel.arclight.common.mod.server.event.ArclightEventDispatcherRegistry; import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger; -import net.minecraftforge.fml.CrashReportExtender; import net.minecraftforge.fml.ExtensionPoint; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.network.FMLNetworkConstants; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.Logger; -import org.bukkit.craftbukkit.v.CraftCrashReport; @Mod("arclight") public class ArclightMod { @@ -19,7 +17,6 @@ public class ArclightMod { public ArclightMod() { LOGGER.info("mod-load"); ArclightEventDispatcherRegistry.registerAllEventDispatchers(); - CrashReportExtender.registerCrashCallable("Arclight", () -> new CraftCrashReport().call().toString()); ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true)); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java index f8fb1ad1..6cb88f14 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java @@ -16,11 +16,13 @@ import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.potion.Effect; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.CrashReportExtender; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.IForgeRegistry; import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.v.CraftCrashReport; import org.bukkit.craftbukkit.v.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.v.util.CraftMagicNumbers; import org.bukkit.enchantments.Enchantment; @@ -47,6 +49,7 @@ public class BukkitRegistry { private static final Map ENTITY_NAME_MAP = getStatic(EntityType.class, "NAME_MAP"); public static void registerAll() { + CrashReportExtender.registerCrashCallable("Arclight", () -> new CraftCrashReport().call().toString()); loadMaterials(); loadPotions(); loadEnchantments(); diff --git a/arclight-common/src/main/resources/mixins.arclight.core.json b/arclight-common/src/main/resources/mixins.arclight.core.json index c5a7d20b..8ed23c18 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.json @@ -359,6 +359,7 @@ "world.spawner.PatrolSpawnerMixin", "world.spawner.PhantomSpawnerMixin", "world.spawner.WanderingTraderSpawnerMixin", + "world.storage.DerivedWorldInfoMixin", "world.storage.MapData_MapInfoMixin", "world.storage.MapDataMixin", "world.storage.SaveHandlerMixin",