diff --git a/src/com/hypixel/hytale/LateMain.java b/src/com/hypixel/hytale/LateMain.java index d2e60391..087a7462 100644 --- a/src/com/hypixel/hytale/LateMain.java +++ b/src/com/hypixel/hytale/LateMain.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.logger.sentry.SkipSentryException; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.HytaleServerConfig; import com.hypixel.hytale.server.core.Options; +import com.hypixel.hytale.server.core.console.ConsoleModule; import io.sentry.Sentry; import java.util.Map.Entry; import java.util.logging.Level; @@ -16,6 +17,7 @@ public class LateMain { try { if (!Options.parse(args)) { HytaleLogger.init(); + ConsoleModule.initializeTerminal(); HytaleFileHandler.INSTANCE.enable(); HytaleLogger.replaceStd(); HytaleLoggerBackend.LOG_LEVEL_LOADER = name -> { diff --git a/src/com/hypixel/hytale/builtin/adventure/camera/CameraPlugin.java b/src/com/hypixel/hytale/builtin/adventure/camera/CameraPlugin.java index 8adb4fc6..f5523935 100644 --- a/src/com/hypixel/hytale/builtin/adventure/camera/CameraPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/camera/CameraPlugin.java @@ -10,13 +10,17 @@ import com.hypixel.hytale.builtin.adventure.camera.asset.viewbobbing.ViewBobbing import com.hypixel.hytale.builtin.adventure.camera.command.CameraEffectCommand; import com.hypixel.hytale.builtin.adventure.camera.interaction.CameraShakeInteraction; import com.hypixel.hytale.builtin.adventure.camera.system.CameraEffectSystem; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.protocol.MovementType; import com.hypixel.hytale.server.core.asset.HytaleAssetStore; import com.hypixel.hytale.server.core.asset.type.camera.CameraEffect; +import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; public class CameraPlugin extends JavaPlugin { @@ -55,6 +59,8 @@ public class CameraPlugin extends JavaPlugin { .build() ); this.getCommandRegistry().registerCommand(new CameraEffectCommand()); - this.getEntityStoreRegistry().registerSystem(new CameraEffectSystem()); + ComponentType playerRefComponentType = PlayerRef.getComponentType(); + ComponentType entityStatMapComponentType = EntityStatMap.getComponentType(); + this.getEntityStoreRegistry().registerSystem(new CameraEffectSystem(playerRefComponentType, entityStatMapComponentType)); } } diff --git a/src/com/hypixel/hytale/builtin/adventure/camera/system/CameraEffectSystem.java b/src/com/hypixel/hytale/builtin/adventure/camera/system/CameraEffectSystem.java index 56811f1a..92480723 100644 --- a/src/com/hypixel/hytale/builtin/adventure/camera/system/CameraEffectSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/camera/system/CameraEffectSystem.java @@ -23,10 +23,19 @@ import javax.annotation.Nullable; public class CameraEffectSystem extends DamageEventSystem { @Nonnull - private static final ComponentType PLAYER_REF_COMPONENT_TYPE = PlayerRef.getComponentType(); - private static final ComponentType ENTITY_STAT_MAP_COMPONENT_TYPE = EntityStatMap.getComponentType(); + private final ComponentType playerRefComponentType; @Nonnull - private static final Query QUERY = Query.and(PLAYER_REF_COMPONENT_TYPE, ENTITY_STAT_MAP_COMPONENT_TYPE); + private final ComponentType entityStatMapComponentType; + @Nonnull + private final Query query; + + public CameraEffectSystem( + @Nonnull ComponentType playerRefComponentType, @Nonnull ComponentType entityStatMapComponentType + ) { + this.playerRefComponentType = playerRefComponentType; + this.entityStatMapComponentType = entityStatMapComponentType; + this.query = Query.and(playerRefComponentType, entityStatMapComponentType); + } @Nullable @Override @@ -37,7 +46,7 @@ public class CameraEffectSystem extends DamageEventSystem { @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } public void handle( @@ -47,7 +56,7 @@ public class CameraEffectSystem extends DamageEventSystem { @Nonnull CommandBuffer commandBuffer, @Nonnull Damage damage ) { - EntityStatMap entityStatMapComponent = archetypeChunk.getComponent(index, ENTITY_STAT_MAP_COMPONENT_TYPE); + EntityStatMap entityStatMapComponent = archetypeChunk.getComponent(index, this.entityStatMapComponentType); assert entityStatMapComponent != null; @@ -55,7 +64,7 @@ public class CameraEffectSystem extends DamageEventSystem { if (healthStat != null) { float health = healthStat.getMax() - healthStat.getMin(); if (!(health <= 0.0F)) { - PlayerRef playerRefComponent = archetypeChunk.getComponent(index, PLAYER_REF_COMPONENT_TYPE); + PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType); assert playerRefComponent != null; diff --git a/src/com/hypixel/hytale/builtin/adventure/farming/FarmingPlugin.java b/src/com/hypixel/hytale/builtin/adventure/farming/FarmingPlugin.java index 34d66899..bb9deae9 100644 --- a/src/com/hypixel/hytale/builtin/adventure/farming/FarmingPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/farming/FarmingPlugin.java @@ -32,11 +32,15 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Farmin import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset; import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList; import com.hypixel.hytale.server.core.asset.type.weather.config.Weather; +import com.hypixel.hytale.server.core.entity.UUIDComponent; +import com.hypixel.hytale.server.core.modules.block.BlockModule; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry; import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk; +import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection; +import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.events.ChunkPreLoadProcessEvent; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; @@ -105,13 +109,25 @@ public class FarmingPlugin extends JavaPlugin { this.farmingBlockStateComponentType = chunkStoreRegistry.registerComponent(FarmingBlockState.class, "Farming", FarmingBlockState.CODEC); this.coopBlockStateComponentType = chunkStoreRegistry.registerComponent(CoopBlock.class, "Coop", CoopBlock.CODEC); this.coopResidentComponentType = entityStoreRegistry.registerComponent(CoopResidentComponent.class, "CoopResident", CoopResidentComponent.CODEC); - chunkStoreRegistry.registerSystem(new FarmingSystems.OnSoilAdded()); - chunkStoreRegistry.registerSystem(new FarmingSystems.OnFarmBlockAdded()); - chunkStoreRegistry.registerSystem(new FarmingSystems.Ticking()); + ComponentType blockStateInfoComponentType = BlockModule.BlockStateInfo.getComponentType(); + ComponentType blockSectionComponentType = BlockSection.getComponentType(); + ComponentType chunkSectionComponentType = ChunkSection.getComponentType(); + ComponentType uuidComponentType = UUIDComponent.getComponentType(); + chunkStoreRegistry.registerSystem(new FarmingSystems.OnSoilAdded(blockStateInfoComponentType, this.tiledSoilBlockComponentType)); + chunkStoreRegistry.registerSystem(new FarmingSystems.OnFarmBlockAdded(blockStateInfoComponentType, this.farmingBlockComponentType)); + chunkStoreRegistry.registerSystem( + new FarmingSystems.Ticking( + blockSectionComponentType, + chunkSectionComponentType, + this.farmingBlockComponentType, + this.tiledSoilBlockComponentType, + this.coopBlockStateComponentType + ) + ); chunkStoreRegistry.registerSystem(new FarmingSystems.MigrateFarming()); - chunkStoreRegistry.registerSystem(new FarmingSystems.OnCoopAdded()); - entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentEntitySystem()); - entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentTicking()); + chunkStoreRegistry.registerSystem(new FarmingSystems.OnCoopAdded(blockStateInfoComponentType, this.coopBlockStateComponentType)); + entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentEntitySystem(this.coopResidentComponentType, uuidComponentType)); + entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentTicking(this.coopResidentComponentType)); this.getEventRegistry().registerGlobal(EventPriority.LAST, ChunkPreLoadProcessEvent.class, FarmingPlugin::preventSpreadOnNew); } diff --git a/src/com/hypixel/hytale/builtin/adventure/farming/FarmingSystems.java b/src/com/hypixel/hytale/builtin/adventure/farming/FarmingSystems.java index 56662f69..41adae04 100644 --- a/src/com/hypixel/hytale/builtin/adventure/farming/FarmingSystems.java +++ b/src/com/hypixel/hytale/builtin/adventure/farming/FarmingSystems.java @@ -99,11 +99,23 @@ public class FarmingSystems { } public static class CoopResidentEntitySystem extends RefSystem { - private static final ComponentType COMPONENT_TYPE_COOP_RESIDENT = CoopResidentComponent.getComponentType(); + @Nonnull + private final ComponentType coopResidentComponentType; + @Nonnull + private final ComponentType uuidComponentType; + public CoopResidentEntitySystem( + @Nonnull ComponentType coopResidentComponentType, + @Nonnull ComponentType uuidComponentType + ) { + this.coopResidentComponentType = coopResidentComponentType; + this.uuidComponentType = uuidComponentType; + } + + @Nonnull @Override public Query getQuery() { - return COMPONENT_TYPE_COOP_RESIDENT; + return this.coopResidentComponentType; } @Override @@ -117,10 +129,10 @@ public class FarmingSystems { @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { if (reason != RemoveReason.UNLOAD) { - UUIDComponent uuidComponent = commandBuffer.getComponent(ref, UUIDComponent.getComponentType()); + UUIDComponent uuidComponent = commandBuffer.getComponent(ref, this.uuidComponentType); if (uuidComponent != null) { UUID uuid = uuidComponent.getUuid(); - CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, COMPONENT_TYPE_COOP_RESIDENT); + CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, this.coopResidentComponentType); if (coopResidentComponent != null) { Vector3i coopPosition = coopResidentComponent.getCoopLocation(); World world = commandBuffer.getExternalData().getWorld(); @@ -159,11 +171,17 @@ public class FarmingSystems { } public static class CoopResidentTicking extends EntityTickingSystem { - private static final ComponentType COMPONENT_TYPE_COOP_RESIDENT = CoopResidentComponent.getComponentType(); + @Nonnull + private final ComponentType coopResidentComponentType; + public CoopResidentTicking(@Nonnull ComponentType coopResidentComponentType) { + this.coopResidentComponentType = coopResidentComponentType; + } + + @Nonnull @Override public Query getQuery() { - return COMPONENT_TYPE_COOP_RESIDENT; + return this.coopResidentComponentType; } @Override @@ -174,11 +192,12 @@ public class FarmingSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - CoopResidentComponent coopResidentComponent = archetypeChunk.getComponent(index, CoopResidentComponent.getComponentType()); - if (coopResidentComponent != null) { - if (coopResidentComponent.getMarkedForDespawn()) { - commandBuffer.removeEntity(archetypeChunk.getReferenceTo(index), RemoveReason.REMOVE); - } + CoopResidentComponent coopResidentComponent = archetypeChunk.getComponent(index, this.coopResidentComponentType); + + assert coopResidentComponent != null; + + if (coopResidentComponent.getMarkedForDespawn()) { + commandBuffer.removeEntity(archetypeChunk.getReferenceTo(index), RemoveReason.REMOVE); } } } @@ -209,17 +228,30 @@ public class FarmingSystems { public static class OnCoopAdded extends RefSystem { @Nonnull - private static final Query QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), CoopBlock.getComponentType()); + private final ComponentType blockStateInfoComponentType; + @Nonnull + private final ComponentType coopBlockComponentType; + @Nonnull + private final Query query; + + public OnCoopAdded( + @Nonnull ComponentType blockStateInfoComponentType, + @Nonnull ComponentType coopBlockComponentType + ) { + this.blockStateInfoComponentType = blockStateInfoComponentType; + this.coopBlockComponentType = coopBlockComponentType; + this.query = Query.and(blockStateInfoComponentType, coopBlockComponentType); + } @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, CoopBlock.getComponentType()); + CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, this.coopBlockComponentType); assert coopBlockComponent != null; - BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); + BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType); assert blockStateInfoComponent != null; @@ -244,11 +276,11 @@ public class FarmingSystems { @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { if (reason != RemoveReason.UNLOAD) { - CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, CoopBlock.getComponentType()); + CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, this.coopBlockComponentType); assert coopBlockComponent != null; - BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); + BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType); assert blockStateInfoComponent != null; @@ -286,26 +318,39 @@ public class FarmingSystems { } } - @Nullable + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } } public static class OnFarmBlockAdded extends RefSystem { @Nonnull - private static final Query QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), FarmingBlock.getComponentType()); + private final ComponentType blockStateInfoComponentType; + @Nonnull + private final ComponentType farmingBlockComponentType; + @Nonnull + private final Query query; + + public OnFarmBlockAdded( + @Nonnull ComponentType blockStateInfoComponentType, + @Nonnull ComponentType farmingBlockComponentType + ) { + this.blockStateInfoComponentType = blockStateInfoComponentType; + this.farmingBlockComponentType = farmingBlockComponentType; + this.query = Query.and(blockStateInfoComponentType, farmingBlockComponentType); + } @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - FarmingBlock farmingBlockComponent = commandBuffer.getComponent(ref, FarmingBlock.getComponentType()); + FarmingBlock farmingBlockComponent = commandBuffer.getComponent(ref, this.farmingBlockComponentType); assert farmingBlockComponent != null; - BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); + BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType); assert blockStateInfoComponent != null; @@ -421,26 +466,39 @@ public class FarmingSystems { ) { } - @Nullable + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } } public static class OnSoilAdded extends RefSystem { @Nonnull - private static final Query QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), TilledSoilBlock.getComponentType()); + private final ComponentType blockStateInfoComponentType; + @Nonnull + private final ComponentType tilledSoilBlockComponentType; + @Nonnull + private final Query query; + + public OnSoilAdded( + @Nonnull ComponentType blockStateInfoComponentType, + @Nonnull ComponentType tilledSoilBlockComponentType + ) { + this.blockStateInfoComponentType = blockStateInfoComponentType; + this.tilledSoilBlockComponentType = tilledSoilBlockComponentType; + this.query = Query.and(blockStateInfoComponentType, tilledSoilBlockComponentType); + } @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - TilledSoilBlock soilComponent = commandBuffer.getComponent(ref, TilledSoilBlock.getComponentType()); + TilledSoilBlock soilComponent = commandBuffer.getComponent(ref, this.tilledSoilBlockComponentType); assert soilComponent != null; - BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); + BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType); assert blockStateInfoComponent != null; @@ -478,16 +536,41 @@ public class FarmingSystems { ) { } - @Nullable + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } } public static class Ticking extends EntityTickingSystem { @Nonnull - private static final Query QUERY = Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType()); + private final ComponentType blockSectionComponentType; + @Nonnull + private final ComponentType chunkSectionComponentType; + @Nonnull + private final ComponentType farmingBlockComponentType; + @Nonnull + private final ComponentType tilledSoilBlockComponentType; + @Nonnull + private final ComponentType coopBlockComponentType; + @Nonnull + private final Query query; + + public Ticking( + @Nonnull ComponentType blockSectionComponentType, + @Nonnull ComponentType chunkSectionComponentType, + @Nonnull ComponentType farmingBlockComponentType, + @Nonnull ComponentType tilledSoilBlockComponentType, + @Nonnull ComponentType coopBlockComponentType + ) { + this.blockSectionComponentType = blockSectionComponentType; + this.chunkSectionComponentType = chunkSectionComponentType; + this.farmingBlockComponentType = farmingBlockComponentType; + this.tilledSoilBlockComponentType = tilledSoilBlockComponentType; + this.coopBlockComponentType = coopBlockComponentType; + this.query = Query.and(blockSectionComponentType, chunkSectionComponentType); + } @Override public void tick( @@ -497,12 +580,12 @@ public class FarmingSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - BlockSection blockSectionComponent = archetypeChunk.getComponent(index, BlockSection.getComponentType()); + BlockSection blockSectionComponent = archetypeChunk.getComponent(index, this.blockSectionComponentType); assert blockSectionComponent != null; if (blockSectionComponent.getTickingBlocksCountCopy() != 0) { - ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType()); + ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, this.chunkSectionComponentType); assert chunkSectionComponent != null; @@ -526,21 +609,21 @@ public class FarmingSystems { if (blockRef == null) { return BlockTickStrategy.IGNORED; } else { - FarmingBlock farmingBlockComponent = commandBuffer1.getComponent(blockRef, FarmingBlock.getComponentType()); - if (farmingBlockComponent != null) { + FarmingBlock farmingBlockComp = commandBuffer1.getComponent(blockRef, this.farmingBlockComponentType); + if (farmingBlockComp != null) { FarmingUtil.tickFarming( - commandBuffer1, blockChunk, blockSectionComponent, ref, blockRef, farmingBlockComponent, localX, localY, localZ, false + commandBuffer1, blockChunk, blockSectionComponent, ref, blockRef, farmingBlockComp, localX, localY, localZ, false ); return BlockTickStrategy.SLEEP; } else { - TilledSoilBlock tilledSoilBlockComponent = commandBuffer1.getComponent(blockRef, TilledSoilBlock.getComponentType()); - if (tilledSoilBlockComponent != null) { - tickSoil(commandBuffer1, blockRef, tilledSoilBlockComponent); + TilledSoilBlock tilledSoilBlockComp = commandBuffer1.getComponent(blockRef, this.tilledSoilBlockComponentType); + if (tilledSoilBlockComp != null) { + tickSoil(commandBuffer1, blockRef, tilledSoilBlockComp); return BlockTickStrategy.SLEEP; } else { - CoopBlock coopBlockComponent = commandBuffer1.getComponent(blockRef, CoopBlock.getComponentType()); - if (coopBlockComponent != null) { - tickCoop(commandBuffer1, blockRef, coopBlockComponent); + CoopBlock coopBlockComp = commandBuffer1.getComponent(blockRef, this.coopBlockComponentType); + if (coopBlockComp != null) { + tickCoop(commandBuffer1, blockRef, coopBlockComp); return BlockTickStrategy.SLEEP; } else { return BlockTickStrategy.IGNORED; @@ -711,10 +794,10 @@ public class FarmingSystems { } } - @Nullable + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } } } diff --git a/src/com/hypixel/hytale/builtin/adventure/farming/config/stages/PrefabFarmingStageData.java b/src/com/hypixel/hytale/builtin/adventure/farming/config/stages/PrefabFarmingStageData.java index dde600e8..a123a185 100644 --- a/src/com/hypixel/hytale/builtin/adventure/farming/config/stages/PrefabFarmingStageData.java +++ b/src/com/hypixel/hytale/builtin/adventure/farming/config/stages/PrefabFarmingStageData.java @@ -1,6 +1,5 @@ package com.hypixel.hytale.builtin.adventure.farming.config.stages; -import com.hypixel.hytale.assetstore.AssetPack; import com.hypixel.hytale.assetstore.AssetRegistry; import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap; import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlock; @@ -20,7 +19,6 @@ import com.hypixel.hytale.math.util.HashUtil; import com.hypixel.hytale.math.util.MathUtil; import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.protocol.BlockMaterial; -import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation; import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple; @@ -38,7 +36,6 @@ import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.util.PrefabUtil; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.concurrent.TimeUnit; @@ -456,14 +453,12 @@ public class PrefabFarmingStageData extends FarmingStageData { @Nonnull public Path getResolvedPath() { - for (AssetPack pack : AssetModule.get().getAssetPacks()) { - Path assetPath = pack.getRoot().resolve("Server").resolve("Prefabs").resolve(this.path); - if (Files.exists(assetPath)) { - return assetPath; - } + Path assetPath = PrefabStore.get().findAssetPrefabPath(this.path); + if (assetPath == null) { + throw new IllegalStateException("Invalid prefab path: " + this.path); + } else { + return assetPath; } - - return PrefabStore.get().getAssetPrefabsPath().resolve(this.path); } @Nonnull diff --git a/src/com/hypixel/hytale/builtin/adventure/memories/MemoriesPlugin.java b/src/com/hypixel/hytale/builtin/adventure/memories/MemoriesPlugin.java index 03c5f1c0..4ff8eecd 100644 --- a/src/com/hypixel/hytale/builtin/adventure/memories/MemoriesPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/memories/MemoriesPlugin.java @@ -40,6 +40,7 @@ import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.windows.Window; import com.hypixel.hytale.server.core.io.PacketHandler; +import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.player.PlayerSystems; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction; @@ -100,9 +101,16 @@ public class MemoriesPlugin extends JavaPlugin { OpenCustomUIInteraction.registerCustomPageSupplier(this, MemoriesUnlockedPage.class, "MemoriesUnlocked", new MemoriesUnlockedPageSuplier()); Window.CLIENT_REQUESTABLE_WINDOW_TYPES.put(WindowType.Memories, MemoriesWindow::new); this.playerMemoriesComponentType = entityStoreRegistry.registerComponent(PlayerMemories.class, "PlayerMemories", PlayerMemories.CODEC); + ComponentType playerComponentType = Player.getComponentType(); + ComponentType playerRefComponentType = PlayerRef.getComponentType(); + ComponentType transformComponentType = TransformComponent.getComponentType(); NPCMemoryProvider npcMemoryProvider = new NPCMemoryProvider(); this.registerMemoryProvider(npcMemoryProvider); - entityStoreRegistry.registerSystem(new NPCMemory.GatherMemoriesSystem(npcMemoryProvider.getCollectionRadius())); + entityStoreRegistry.registerSystem( + new NPCMemory.GatherMemoriesSystem( + transformComponentType, playerComponentType, playerRefComponentType, this.playerMemoriesComponentType, npcMemoryProvider.getCollectionRadius() + ) + ); for (MemoryProvider provider : this.providers) { BuilderCodec codec = (BuilderCodec)provider.getCodec(); @@ -110,11 +118,11 @@ public class MemoriesPlugin extends JavaPlugin { } this.getEventRegistry().register(AllNPCsLoadedEvent.class, event -> this.onAssetsLoad()); - entityStoreRegistry.registerSystem(new MemoriesPlugin.PlayerAddedSystem()); + entityStoreRegistry.registerSystem(new MemoriesPlugin.PlayerAddedSystem(playerComponentType, playerRefComponentType, this.playerMemoriesComponentType)); this.getCodecRegistry(Interaction.CODEC).register("SetMemoriesCapacity", SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction.CODEC); this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(MemoriesGameplayConfig.class, "Memories", MemoriesGameplayConfig.CODEC); this.getCodecRegistry(Interaction.CODEC).register("MemoriesCondition", MemoriesConditionInteraction.class, MemoriesConditionInteraction.CODEC); - entityStoreRegistry.registerSystem(new TempleRespawnPlayersSystem()); + entityStoreRegistry.registerSystem(new TempleRespawnPlayersSystem(playerRefComponentType, transformComponentType)); this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ForgottenTempleConfig.class, "ForgottenTemple", ForgottenTempleConfig.CODEC); } @@ -328,7 +336,24 @@ public class MemoriesPlugin extends JavaPlugin { @Nonnull private final Set> dependencies = Set.of(new SystemDependency<>(Order.AFTER, PlayerSystems.PlayerSpawnedSystem.class)); @Nonnull - private final Query query = Query.and(Player.getComponentType(), PlayerRef.getComponentType()); + private final ComponentType playerComponentType; + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final ComponentType playerMemoriesComponentType; + @Nonnull + private final Query query; + + public PlayerAddedSystem( + @Nonnull ComponentType playerComponentType, + @Nonnull ComponentType playerRefComponentType, + @Nonnull ComponentType playerMemoriesComponentType + ) { + this.playerComponentType = playerComponentType; + this.playerRefComponentType = playerRefComponentType; + this.playerMemoriesComponentType = playerMemoriesComponentType; + this.query = Query.and(playerComponentType, playerRefComponentType); + } @Nonnull @Override @@ -346,15 +371,15 @@ public class MemoriesPlugin extends JavaPlugin { public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + Player playerComponent = store.getComponent(ref, this.playerComponentType); assert playerComponent != null; - PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType()); + PlayerRef playerRefComponent = store.getComponent(ref, this.playerRefComponentType); assert playerRefComponent != null; - PlayerMemories playerMemoriesComponent = store.getComponent(ref, PlayerMemories.getComponentType()); + PlayerMemories playerMemoriesComponent = store.getComponent(ref, this.playerMemoriesComponentType); boolean isFeatureUnlockedByPlayer = playerMemoriesComponent != null; PacketHandler playerConnection = playerRefComponent.getPacketHandler(); playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(isFeatureUnlockedByPlayer)); diff --git a/src/com/hypixel/hytale/builtin/adventure/memories/memories/npc/NPCMemory.java b/src/com/hypixel/hytale/builtin/adventure/memories/memories/npc/NPCMemory.java index fa702870..08daa96f 100644 --- a/src/com/hypixel/hytale/builtin/adventure/memories/memories/npc/NPCMemory.java +++ b/src/com/hypixel/hytale/builtin/adventure/memories/memories/npc/NPCMemory.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.codec.validation.Validators; import com.hypixel.hytale.component.AddReason; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; @@ -203,12 +204,29 @@ public class NPCMemory extends Memory { public static class GatherMemoriesSystem extends EntityTickingSystem { @Nonnull - public static final Query QUERY = Query.and( - TransformComponent.getComponentType(), Player.getComponentType(), PlayerRef.getComponentType(), PlayerMemories.getComponentType() - ); + private final ComponentType transformComponentType; + @Nonnull + private final ComponentType playerComponentType; + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final ComponentType playerMemoriesComponentType; + @Nonnull + private final Query query; private final double radius; - public GatherMemoriesSystem(double radius) { + public GatherMemoriesSystem( + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType playerComponentType, + @Nonnull ComponentType playerRefComponentType, + @Nonnull ComponentType playerMemoriesComponentType, + double radius + ) { + this.transformComponentType = transformComponentType; + this.playerComponentType = playerComponentType; + this.playerRefComponentType = playerRefComponentType; + this.playerMemoriesComponentType = playerMemoriesComponentType; + this.query = Query.and(transformComponentType, playerComponentType, playerRefComponentType, playerMemoriesComponentType); this.radius = radius; } @@ -220,12 +238,12 @@ public class NPCMemory extends Memory { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Player playerComponent = archetypeChunk.getComponent(index, Player.getComponentType()); + Player playerComponent = archetypeChunk.getComponent(index, this.playerComponentType); assert playerComponent != null; if (playerComponent.getGameMode() == GameMode.Adventure) { - TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType); assert transformComponent != null; @@ -234,13 +252,13 @@ public class NPCMemory extends Memory { ObjectList> results = SpatialResource.getThreadLocalReferenceList(); npcSpatialResource.getSpatialStructure().collect(position, this.radius, results); if (!results.isEmpty()) { - PlayerRef playerRefComponent = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); + PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType); assert playerRefComponent != null; Ref ref = archetypeChunk.getReferenceTo(index); MemoriesPlugin memoriesPlugin = MemoriesPlugin.get(); - PlayerMemories playerMemoriesComponent = archetypeChunk.getComponent(index, PlayerMemories.getComponentType()); + PlayerMemories playerMemoriesComponent = archetypeChunk.getComponent(index, this.playerMemoriesComponentType); assert playerMemoriesComponent != null; @@ -351,7 +369,7 @@ public class NPCMemory extends Memory { @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } } } diff --git a/src/com/hypixel/hytale/builtin/adventure/memories/temple/TempleRespawnPlayersSystem.java b/src/com/hypixel/hytale/builtin/adventure/memories/temple/TempleRespawnPlayersSystem.java index 2f6e2b87..4ab9fc19 100644 --- a/src/com/hypixel/hytale/builtin/adventure/memories/temple/TempleRespawnPlayersSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/memories/temple/TempleRespawnPlayersSystem.java @@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.adventure.memories.temple; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; @@ -18,14 +19,22 @@ import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.spawn.ISpawnProvider; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class TempleRespawnPlayersSystem extends DelayedEntitySystem { @Nonnull - public static final Query QUERY = Query.and(PlayerRef.getComponentType(), TransformComponent.getComponentType()); + private final ComponentType playerRefComponentType; + @Nonnull + private final ComponentType transformComponentType; + @Nonnull + private final Query query; - public TempleRespawnPlayersSystem() { + public TempleRespawnPlayersSystem( + @Nonnull ComponentType playerRefComponentType, @Nonnull ComponentType transformComponentType + ) { super(1.0F); + this.playerRefComponentType = playerRefComponentType; + this.transformComponentType = transformComponentType; + this.query = Query.and(playerRefComponentType, transformComponentType); } @Override @@ -40,7 +49,7 @@ public class TempleRespawnPlayersSystem extends DelayedEntitySystem GameplayConfig gameplayConfig = world.getGameplayConfig(); ForgottenTempleConfig config = gameplayConfig.getPluginConfig().get(ForgottenTempleConfig.class); if (config != null) { - TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType); assert transformComponent != null; @@ -51,15 +60,18 @@ public class TempleRespawnPlayersSystem extends DelayedEntitySystem Transform spawnTransform = spawnProvider.getSpawnPoint(ref, commandBuffer); Teleport teleportComponent = Teleport.createForPlayer(null, spawnTransform); commandBuffer.addComponent(ref, Teleport.getComponentType(), teleportComponent); - PlayerRef playerRef = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); - SoundUtil.playSoundEvent2dToPlayer(playerRef, config.getRespawnSoundIndex(), SoundCategory.SFX); + PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType); + + assert playerRefComponent != null; + + SoundUtil.playSoundEvent2dToPlayer(playerRefComponent, config.getRespawnSoundIndex(), SoundCategory.SFX); } } } - @Nullable + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } } diff --git a/src/com/hypixel/hytale/builtin/adventure/npcobjectives/NPCObjectivesPlugin.java b/src/com/hypixel/hytale/builtin/adventure/npcobjectives/NPCObjectivesPlugin.java index 5ee7c4a3..b447c559 100644 --- a/src/com/hypixel/hytale/builtin/adventure/npcobjectives/NPCObjectivesPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/npcobjectives/NPCObjectivesPlugin.java @@ -24,6 +24,7 @@ import com.hypixel.hytale.builtin.adventure.objectives.task.ObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask; import com.hypixel.hytale.builtin.tagset.config.NPCGroup; import com.hypixel.hytale.component.ComponentRegistryProxy; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; @@ -34,8 +35,10 @@ import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.NPCPlugin; +import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.spawning.assets.spawnmarker.config.SpawnMarker; import com.hypixel.hytale.server.spawning.assets.spawns.config.BeaconNPCSpawn; +import com.hypixel.hytale.server.spawning.beacons.LegacySpawnBeaconEntity; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -91,9 +94,11 @@ public class NPCObjectivesPlugin extends JavaPlugin { KillNPCObjectiveTask.CODEC, KillNPCObjectiveTask::new ); - entityStoreRegistry.registerSystem(new SpawnBeaconCheckRemovalSystem()); this.killTrackerResourceType = entityStoreRegistry.registerResource(KillTrackerResource.class, KillTrackerResource::new); - entityStoreRegistry.registerSystem(new KillTrackerSystem()); + ComponentType legacySpawnBeaconEntityComponentType = LegacySpawnBeaconEntity.getComponentType(); + ComponentType npcEntityComponentType = NPCEntity.getComponentType(); + entityStoreRegistry.registerSystem(new SpawnBeaconCheckRemovalSystem(legacySpawnBeaconEntityComponentType)); + entityStoreRegistry.registerSystem(new KillTrackerSystem(npcEntityComponentType, this.killTrackerResourceType)); NPCPlugin.get() .registerCoreComponentType("CompleteTask", BuilderActionCompleteTask::new) .registerCoreComponentType("StartObjective", BuilderActionStartObjective::new) diff --git a/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/KillTrackerSystem.java b/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/KillTrackerSystem.java index 78f4394c..a535e2a8 100644 --- a/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/KillTrackerSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/KillTrackerSystem.java @@ -3,7 +3,9 @@ package com.hypixel.hytale.builtin.adventure.npcobjectives.systems; import com.hypixel.hytale.builtin.adventure.npcobjectives.resources.KillTrackerResource; import com.hypixel.hytale.builtin.adventure.npcobjectives.transaction.KillTaskTransaction; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.server.core.modules.entity.damage.Damage; @@ -13,23 +15,34 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.entities.NPCEntity; import java.util.List; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class KillTrackerSystem extends DeathSystems.OnDeathSystem { - @Nullable + @Nonnull + private final ComponentType npcEntityComponentType; + @Nonnull + private final ResourceType killTrackerResourceType; + + public KillTrackerSystem( + @Nonnull ComponentType npcEntityComponentType, @Nonnull ResourceType killTrackerResourceType + ) { + this.npcEntityComponentType = npcEntityComponentType; + this.killTrackerResourceType = killTrackerResourceType; + } + + @Nonnull @Override public Query getQuery() { - return NPCEntity.getComponentType(); + return this.npcEntityComponentType; } public void onComponentAdded( @Nonnull Ref ref, @Nonnull DeathComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - NPCEntity npcEntityComponent = store.getComponent(ref, NPCEntity.getComponentType()); + NPCEntity npcEntityComponent = store.getComponent(ref, this.npcEntityComponentType); assert npcEntityComponent != null; - KillTrackerResource killTrackerResource = store.getResource(KillTrackerResource.getResourceType()); + KillTrackerResource killTrackerResource = store.getResource(this.killTrackerResourceType); List killTasks = killTrackerResource.getKillTasks(); Damage deathInfo = component.getDeathInfo(); if (deathInfo != null) { diff --git a/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/SpawnBeaconCheckRemovalSystem.java b/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/SpawnBeaconCheckRemovalSystem.java index 81bec396..32f9a8de 100644 --- a/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/SpawnBeaconCheckRemovalSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/npcobjectives/systems/SpawnBeaconCheckRemovalSystem.java @@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.adventure.npcobjectives.systems; import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin; import com.hypixel.hytale.component.AddReason; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.RemoveReason; import com.hypixel.hytale.component.Store; @@ -11,18 +12,24 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.spawning.beacons.LegacySpawnBeaconEntity; import java.util.UUID; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class SpawnBeaconCheckRemovalSystem extends HolderSystem { - @Nullable + @Nonnull + private final ComponentType legacySpawnBeaconEntityComponentType; + + public SpawnBeaconCheckRemovalSystem(@Nonnull ComponentType legacySpawnBeaconEntityComponentType) { + this.legacySpawnBeaconEntityComponentType = legacySpawnBeaconEntityComponentType; + } + + @Nonnull @Override public Query getQuery() { - return LegacySpawnBeaconEntity.getComponentType(); + return this.legacySpawnBeaconEntityComponentType; } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(LegacySpawnBeaconEntity.getComponentType()); + LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(this.legacySpawnBeaconEntityComponentType); assert spawnBeaconComponent != null; diff --git a/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationHolderSystem.java b/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationHolderSystem.java index bafa1af7..99239864 100644 --- a/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationHolderSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationHolderSystem.java @@ -19,12 +19,14 @@ import javax.annotation.Nonnull; public class NPCReputationHolderSystem extends HolderSystem { @Nonnull private final ComponentType reputationGroupComponentType; + @Nonnull private final ComponentType npcEntityComponentType; @Nonnull private final Query query; public NPCReputationHolderSystem( - @Nonnull ComponentType reputationGroupComponentType, ComponentType npcEntityComponentType + @Nonnull ComponentType reputationGroupComponentType, + @Nonnull ComponentType npcEntityComponentType ) { this.reputationGroupComponentType = reputationGroupComponentType; this.npcEntityComponentType = npcEntityComponentType; diff --git a/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationPlugin.java b/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationPlugin.java index ca304025..d33d0e2b 100644 --- a/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/npcreputation/NPCReputationPlugin.java @@ -2,9 +2,13 @@ package com.hypixel.hytale.builtin.adventure.npcreputation; import com.hypixel.hytale.builtin.adventure.reputation.ReputationGroupComponent; import com.hypixel.hytale.component.ComponentRegistryProxy; +import com.hypixel.hytale.component.ComponentType; +import com.hypixel.hytale.component.ResourceType; +import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.npc.blackboard.Blackboard; import com.hypixel.hytale.server.npc.entities.NPCEntity; import javax.annotation.Nonnull; @@ -16,7 +20,11 @@ public class NPCReputationPlugin extends JavaPlugin { @Override protected void setup() { ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); - entityStoreRegistry.registerSystem(new ReputationAttitudeSystem()); - entityStoreRegistry.registerSystem(new NPCReputationHolderSystem(ReputationGroupComponent.getComponentType(), NPCEntity.getComponentType())); + ResourceType blackboardResourceType = Blackboard.getResourceType(); + ComponentType playerComponentType = Player.getComponentType(); + ComponentType reputationGroupComponentType = ReputationGroupComponent.getComponentType(); + ComponentType npcEntityComponentType = NPCEntity.getComponentType(); + entityStoreRegistry.registerSystem(new ReputationAttitudeSystem(blackboardResourceType, playerComponentType)); + entityStoreRegistry.registerSystem(new NPCReputationHolderSystem(reputationGroupComponentType, npcEntityComponentType)); } } diff --git a/src/com/hypixel/hytale/builtin/adventure/npcreputation/ReputationAttitudeSystem.java b/src/com/hypixel/hytale/builtin/adventure/npcreputation/ReputationAttitudeSystem.java index 715ebdf9..2d6ec966 100644 --- a/src/com/hypixel/hytale/builtin/adventure/npcreputation/ReputationAttitudeSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/npcreputation/ReputationAttitudeSystem.java @@ -1,6 +1,7 @@ package com.hypixel.hytale.builtin.adventure.npcreputation; import com.hypixel.hytale.builtin.adventure.reputation.ReputationPlugin; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.system.StoreSystem; @@ -12,14 +13,23 @@ import javax.annotation.Nonnull; public class ReputationAttitudeSystem extends StoreSystem { @Nonnull - private final ResourceType resourceType = Blackboard.getResourceType(); + private final ResourceType blackboardResourceType; + @Nonnull + private final ComponentType playerComponentType; + + public ReputationAttitudeSystem( + @Nonnull ResourceType blackboardResourceType, @Nonnull ComponentType playerComponentType + ) { + this.blackboardResourceType = blackboardResourceType; + this.playerComponentType = playerComponentType; + } @Override public void onSystemAddedToStore(@Nonnull Store store) { - Blackboard blackboardResource = store.getResource(this.resourceType); + Blackboard blackboardResource = store.getResource(this.blackboardResourceType); AttitudeView attitudeView = blackboardResource.getView(AttitudeView.class, 0L); attitudeView.registerProvider(100, (ref, role, targetRef, accessor) -> { - Player playerComponent = store.getComponent(targetRef, Player.getComponentType()); + Player playerComponent = store.getComponent(targetRef, this.playerComponentType); return playerComponent == null ? null : ReputationPlugin.get().getAttitude(store, targetRef, ref); }); } diff --git a/src/com/hypixel/hytale/builtin/adventure/objectives/ObjectivePlugin.java b/src/com/hypixel/hytale/builtin/adventure/objectives/ObjectivePlugin.java index 8da406a1..c99324eb 100644 --- a/src/com/hypixel/hytale/builtin/adventure/objectives/ObjectivePlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/objectives/ObjectivePlugin.java @@ -45,10 +45,12 @@ import com.hypixel.hytale.builtin.adventure.objectives.task.ReachLocationTask; import com.hypixel.hytale.builtin.adventure.objectives.task.TreasureMapObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.UseBlockObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask; +import com.hypixel.hytale.builtin.weather.components.WeatherTracker; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.common.util.ArrayUtil; +import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.ResourceType; @@ -56,6 +58,7 @@ import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.AndQuery; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.spatial.SpatialResource; +import com.hypixel.hytale.event.EventRegistry; import com.hypixel.hytale.function.function.TriFunction; import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.protocol.packets.assets.TrackOrUpdateObjective; @@ -71,7 +74,6 @@ import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList; import com.hypixel.hytale.server.core.asset.type.model.config.Model; import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset; import com.hypixel.hytale.server.core.asset.type.weather.config.Weather; -import com.hypixel.hytale.server.core.entity.LivingEntity; import com.hypixel.hytale.server.core.entity.UUIDComponent; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData; @@ -83,9 +85,11 @@ import com.hypixel.hytale.server.core.modules.entity.EntityModule; import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; +import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import com.hypixel.hytale.server.core.prefab.PrefabCopyableComponent; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.datastore.DataStoreProvider; @@ -123,6 +127,7 @@ public class ObjectivePlugin extends JavaPlugin { private ComponentType objectiveHistoryComponentType; private ComponentType reachLocationMarkerComponentType; private ComponentType objectiveLocationMarkerComponentType; + @Nullable private ObjectiveDataStore objectiveDataStore; public static ObjectivePlugin get() { @@ -141,6 +146,7 @@ public class ObjectivePlugin extends JavaPlugin { return this.objectiveLocationMarkerModel; } + @Nullable public ObjectiveDataStore getObjectiveDataStore() { return this.objectiveDataStore; } @@ -148,6 +154,8 @@ public class ObjectivePlugin extends JavaPlugin { @Override protected void setup() { instance = this; + EventRegistry eventRegistry = this.getEventRegistry(); + ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); AssetRegistry.register( ((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder( ObjectiveAsset.class, new DefaultAssetMap() @@ -189,10 +197,10 @@ public class ObjectivePlugin extends JavaPlugin { .build() ); this.objectiveDataStore = new ObjectiveDataStore(this.config.get().getDataStoreProvider().create(Objective.CODEC)); - this.reachLocationMarkerComponentType = this.getEntityStoreRegistry() - .registerComponent(ReachLocationMarker.class, "ReachLocationMarker", ReachLocationMarker.CODEC); - this.objectiveLocationMarkerComponentType = this.getEntityStoreRegistry() - .registerComponent(ObjectiveLocationMarker.class, "ObjectiveLocation", ObjectiveLocationMarker.CODEC); + this.reachLocationMarkerComponentType = entityStoreRegistry.registerComponent(ReachLocationMarker.class, "ReachLocationMarker", ReachLocationMarker.CODEC); + this.objectiveLocationMarkerComponentType = entityStoreRegistry.registerComponent( + ObjectiveLocationMarker.class, "ObjectiveLocation", ObjectiveLocationMarker.CODEC + ); this.registerTask( "Craft", CraftObjectiveTaskAsset.class, CraftObjectiveTaskAsset.CODEC, CraftObjectiveTask.class, CraftObjectiveTask.CODEC, CraftObjectiveTask::new ); @@ -235,46 +243,64 @@ public class ObjectivePlugin extends JavaPlugin { this.registerCompletion( "ClearObjectiveItems", ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset.CODEC, ClearObjectiveItemsCompletion::new ); - this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveLineAsset.class, this::onObjectiveLineAssetLoaded); - this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveAsset.class, this::onObjectiveAssetLoaded); - this.getEventRegistry().register(PlayerDisconnectEvent.class, this::onPlayerDisconnect); - this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveLocationMarkerAsset.class, ObjectivePlugin::onObjectiveLocationMarkerChange); - this.getEventRegistry().register(LoadedAssetsEvent.class, ModelAsset.class, this::onModelAssetChange); - this.getEventRegistry().registerGlobal(LivingEntityInventoryChangeEvent.class, this::onLivingEntityInventoryChange); - this.getEventRegistry().registerGlobal(AddWorldEvent.class, this::onWorldAdded); + eventRegistry.register(LoadedAssetsEvent.class, ObjectiveLineAsset.class, this::onObjectiveLineAssetLoaded); + eventRegistry.register(LoadedAssetsEvent.class, ObjectiveAsset.class, this::onObjectiveAssetLoaded); + eventRegistry.register(PlayerDisconnectEvent.class, this::onPlayerDisconnect); + eventRegistry.register(LoadedAssetsEvent.class, ObjectiveLocationMarkerAsset.class, ObjectivePlugin::onObjectiveLocationMarkerChange); + eventRegistry.register(LoadedAssetsEvent.class, ModelAsset.class, this::onModelAssetChange); + eventRegistry.registerGlobal(LivingEntityInventoryChangeEvent.class, this::onLivingEntityInventoryChange); + eventRegistry.registerGlobal(AddWorldEvent.class, this::onWorldAdded); this.getCommandRegistry().registerCommand(new ObjectiveCommand()); EntityModule entityModule = EntityModule.get(); ComponentType playerRefComponentType = PlayerRef.getComponentType(); ResourceType, EntityStore>> playerSpatialComponent = entityModule.getPlayerSpatialResourceType(); - this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.EntityAdded(this.reachLocationMarkerComponentType)); - this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.EnsureNetworkSendable()); - this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.Ticking(this.reachLocationMarkerComponentType, playerSpatialComponent)); - this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.EnsureNetworkSendableSystem()); - this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.InitSystem(this.objectiveLocationMarkerComponentType)); - this.getEntityStoreRegistry() - .registerSystem( - new ObjectiveLocationMarkerSystems.TickingSystem(this.objectiveLocationMarkerComponentType, playerRefComponentType, playerSpatialComponent) - ); + ComponentType networkIdComponentType = NetworkId.getComponentType(); + ComponentType transformComponentType = TransformComponent.getComponentType(); + ComponentType uuidComponentType = UUIDComponent.getComponentType(); + ComponentType weatherTrackerComponentType = WeatherTracker.getComponentType(); + ComponentType modelComponentType = ModelComponent.getComponentType(); + ComponentType prefabCopyableComponentType = PrefabCopyableComponent.getComponentType(); + entityStoreRegistry.registerSystem(new ReachLocationMarkerSystems.EntityAdded(this.reachLocationMarkerComponentType, transformComponentType)); + entityStoreRegistry.registerSystem(new ReachLocationMarkerSystems.EnsureNetworkSendable(this.reachLocationMarkerComponentType, networkIdComponentType)); + entityStoreRegistry.registerSystem( + new ReachLocationMarkerSystems.Ticking(this.reachLocationMarkerComponentType, playerSpatialComponent, transformComponentType, uuidComponentType) + ); + entityStoreRegistry.registerSystem( + new ObjectiveLocationMarkerSystems.EnsureNetworkSendableSystem(this.objectiveLocationMarkerComponentType, networkIdComponentType) + ); + entityStoreRegistry.registerSystem( + new ObjectiveLocationMarkerSystems.InitSystem( + this.objectiveLocationMarkerComponentType, modelComponentType, transformComponentType, prefabCopyableComponentType + ) + ); + entityStoreRegistry.registerSystem( + new ObjectiveLocationMarkerSystems.TickingSystem( + this.objectiveLocationMarkerComponentType, + playerRefComponentType, + playerSpatialComponent, + transformComponentType, + weatherTrackerComponentType, + uuidComponentType + ) + ); CommonObjectiveHistoryData.CODEC.register("Objective", ObjectiveHistoryData.class, ObjectiveHistoryData.CODEC); CommonObjectiveHistoryData.CODEC.register("ObjectiveLine", ObjectiveLineHistoryData.class, ObjectiveLineHistoryData.CODEC); ObjectiveRewardHistoryData.CODEC.register("Item", ItemObjectiveRewardHistoryData.class, ItemObjectiveRewardHistoryData.CODEC); - this.objectiveHistoryComponentType = this.getEntityStoreRegistry() - .registerComponent(ObjectiveHistoryComponent.class, "ObjectiveHistory", ObjectiveHistoryComponent.CODEC); - this.getEntityStoreRegistry().registerSystem(new ObjectivePlayerSetupSystem(this.objectiveHistoryComponentType, Player.getComponentType())); - this.getEntityStoreRegistry().registerSystem(new ObjectiveItemEntityRemovalSystem()); + this.objectiveHistoryComponentType = entityStoreRegistry.registerComponent( + ObjectiveHistoryComponent.class, "ObjectiveHistory", ObjectiveHistoryComponent.CODEC + ); + entityStoreRegistry.registerSystem(new ObjectivePlayerSetupSystem(this.objectiveHistoryComponentType, Player.getComponentType())); + entityStoreRegistry.registerSystem(new ObjectiveItemEntityRemovalSystem()); this.getCodecRegistry(Interaction.CODEC).register("StartObjective", StartObjectiveInteraction.class, StartObjectiveInteraction.CODEC); this.getCodecRegistry(Interaction.CODEC).register("CanBreakRespawnPoint", CanBreakRespawnPointInteraction.class, CanBreakRespawnPointInteraction.CODEC); BlockStateModule.get().registerBlockState(TreasureChestState.class, "TreasureChest", TreasureChestState.CODEC); this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ObjectiveGameplayConfig.class, "Objective", ObjectiveGameplayConfig.CODEC); - this.getEntityStoreRegistry() - .registerSystem( - new EntityModule.TangibleMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true - ); - this.getEntityStoreRegistry() - .registerSystem( - new EntityModule.HiddenFromPlayerMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), - true - ); + entityStoreRegistry.registerSystem( + new EntityModule.TangibleMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true + ); + entityStoreRegistry.registerSystem( + new EntityModule.HiddenFromPlayerMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true + ); } @Override @@ -284,13 +310,17 @@ public class ObjectivePlugin extends JavaPlugin { throw new IllegalStateException(String.format("Default objective location marker model '%s' not found", "Objective_Location_Marker")); } else { this.objectiveLocationMarkerModel = Model.createUnitScaleModel(modelAsset); - HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> this.objectiveDataStore.saveToDiskAllObjectives(), 5L, 5L, TimeUnit.MINUTES); + if (this.objectiveDataStore != null) { + HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> this.objectiveDataStore.saveToDiskAllObjectives(), 5L, 5L, TimeUnit.MINUTES); + } } } @Override protected void shutdown() { - this.objectiveDataStore.saveToDiskAllObjectives(); + if (this.objectiveDataStore != null) { + this.objectiveDataStore.saveToDiskAllObjectives(); + } } public ComponentType getReachLocationMarkerComponentType() { @@ -309,10 +339,12 @@ public class ObjectivePlugin extends JavaPlugin { Codec implementationCodec, TriFunction generator ) { - ObjectiveTaskAsset.CODEC.register(id, assetClass, assetCodec); - ObjectiveTask.CODEC.register(id, implementationClass, implementationCodec); - this.taskGenerators.put(assetClass, generator); - this.objectiveDataStore.registerTaskRef(implementationClass); + if (this.objectiveDataStore != null) { + ObjectiveTaskAsset.CODEC.register(id, assetClass, assetCodec); + ObjectiveTask.CODEC.register(id, implementationClass, implementationCodec); + this.taskGenerators.put(assetClass, generator); + this.objectiveDataStore.registerTaskRef(implementationClass); + } } public void registerCompletion( @@ -346,78 +378,90 @@ public class ObjectivePlugin extends JavaPlugin { @Nullable UUID markerUUID, @Nonnull Store store ) { - ObjectiveAsset asset = ObjectiveAsset.getAssetMap().getAsset(objectiveId); - if (asset == null) { - this.getLogger().at(Level.WARNING).log("Failed to find objective asset '%s'", objectiveId); - return null; - } else if (markerUUID == null && !asset.isValidForPlayer()) { - this.getLogger().at(Level.WARNING).log("Objective %s can't be used for Player", asset.getId()); + if (this.objectiveDataStore == null) { return null; } else { - Objective objective = new Objective(asset, objectiveUUID, playerUUIDs, worldUUID, markerUUID); - boolean setupResult = objective.setup(store); - Message assetTitleMessage = Message.translation(asset.getTitleKey()); - if (!setupResult || !this.objectiveDataStore.addObjective(objective.getObjectiveUUID(), objective)) { - this.getLogger().at(Level.WARNING).log("Failed to start objective %s", asset.getId()); - if (objective.getPlayerUUIDs() == null) { - return null; - } else { - objective.forEachParticipant(participantReference -> { - PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType()); - if (playerRefComponent != null) { - playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.failed").param("title", assetTitleMessage)); - } - }); - return null; - } - } else if (objective.getPlayerUUIDs() == null) { - return objective; + ObjectiveAsset asset = ObjectiveAsset.getAssetMap().getAsset(objectiveId); + if (asset == null) { + this.getLogger().at(Level.WARNING).log("Failed to find objective asset '%s'", objectiveId); + return null; + } else if (markerUUID == null && !asset.isValidForPlayer()) { + this.getLogger().at(Level.WARNING).log("Objective %s can't be used for Player", asset.getId()); + return null; } else { - TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(objective.toPacket()); - String objectiveAssetId = asset.getId(); - objective.forEachParticipant(participantReference -> { - Player playerComponent = store.getComponent(participantReference, Player.getComponentType()); - if (playerComponent != null) { - if (!this.canPlayerDoObjective(playerComponent, objectiveAssetId)) { - playerComponent.sendMessage(Message.translation("server.modules.objective.playerAlreadyDoingObjective").param("title", assetTitleMessage)); - } else { + Objective objective = new Objective(asset, objectiveUUID, playerUUIDs, worldUUID, markerUUID); + boolean setupResult = objective.setup(store); + Message assetTitleMessage = Message.translation(asset.getTitleKey()); + if (!setupResult || !this.objectiveDataStore.addObjective(objective.getObjectiveUUID(), objective)) { + this.getLogger().at(Level.WARNING).log("Failed to start objective %s", asset.getId()); + if (objective.getPlayerUUIDs() == null) { + return null; + } else { + objective.forEachParticipant(participantReference -> { PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType()); - - assert playerRefComponent != null; - - UUIDComponent uuidComponent = store.getComponent(participantReference, UUIDComponent.getComponentType()); - - assert uuidComponent != null; - - objective.addActivePlayerUUID(uuidComponent.getUuid()); - PlayerConfigData playerConfigData = playerComponent.getPlayerConfigData(); - HashSet activeObjectiveUUIDs = new HashSet<>(playerConfigData.getActiveObjectiveUUIDs()); - activeObjectiveUUIDs.add(objective.getObjectiveUUID()); - playerConfigData.setActiveObjectiveUUIDs(activeObjectiveUUIDs); - playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.success").param("title", assetTitleMessage)); - playerRefComponent.getPacketHandler().writeNoCache(trackObjectivePacket); - } + if (playerRefComponent != null) { + playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.failed").param("title", assetTitleMessage)); + } + }); + return null; } - }); - objective.markDirty(); - return objective; + } else if (objective.getPlayerUUIDs() == null) { + return objective; + } else { + TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(objective.toPacket()); + String objectiveAssetId = asset.getId(); + objective.forEachParticipant( + participantReference -> { + Player playerComponent = store.getComponent(participantReference, Player.getComponentType()); + if (playerComponent != null) { + if (!this.canPlayerDoObjective(playerComponent, objectiveAssetId)) { + playerComponent.sendMessage( + Message.translation("server.modules.objective.playerAlreadyDoingObjective").param("title", assetTitleMessage) + ); + } else { + PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType()); + + assert playerRefComponent != null; + + UUIDComponent uuidComponent = store.getComponent(participantReference, UUIDComponent.getComponentType()); + + assert uuidComponent != null; + + objective.addActivePlayerUUID(uuidComponent.getUuid()); + PlayerConfigData playerConfigData = playerComponent.getPlayerConfigData(); + HashSet activeObjectiveUUIDs = new HashSet<>(playerConfigData.getActiveObjectiveUUIDs()); + activeObjectiveUUIDs.add(objective.getObjectiveUUID()); + playerConfigData.setActiveObjectiveUUIDs(activeObjectiveUUIDs); + playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.success").param("title", assetTitleMessage)); + playerRefComponent.getPacketHandler().writeNoCache(trackObjectivePacket); + } + } + } + ); + objective.markDirty(); + return objective; + } } } } public boolean canPlayerDoObjective(@Nonnull Player player, @Nonnull String objectiveAssetId) { - Set activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); - if (activeObjectiveUUIDs == null) { - return true; + if (this.objectiveDataStore == null) { + return false; } else { - for (UUID objectiveUUID : activeObjectiveUUIDs) { - Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); - if (objective != null && objective.getObjectiveId().equals(objectiveAssetId)) { - return false; + Set activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); + if (activeObjectiveUUIDs == null) { + return true; + } else { + for (UUID objectiveUUID : activeObjectiveUUIDs) { + Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); + if (objective != null && objective.getObjectiveId().equals(objectiveAssetId)) { + return false; + } } - } - return true; + return true; + } } } @@ -472,56 +516,62 @@ public class ObjectivePlugin extends JavaPlugin { } public boolean canPlayerDoObjectiveLine(@Nonnull Player player, @Nonnull String objectiveLineId) { - Set activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); - if (activeObjectiveUUIDs == null) { - return true; + if (this.objectiveDataStore == null) { + return false; } else { - for (UUID objectiveUUID : activeObjectiveUUIDs) { - Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); - if (objective != null) { - ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData(); - if (objectiveLineHistoryData != null && objectiveLineId.equals(objectiveLineHistoryData.getId())) { - return false; + Set activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); + if (activeObjectiveUUIDs == null) { + return true; + } else { + for (UUID objectiveUUID : activeObjectiveUUIDs) { + Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); + if (objective != null) { + ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData(); + if (objectiveLineHistoryData != null && objectiveLineId.equals(objectiveLineHistoryData.getId())) { + return false; + } } } - } - return true; + return true; + } } } public void objectiveCompleted(@Nonnull Objective objective, @Nonnull Store store) { - for (UUID playerUUID : objective.getPlayerUUIDs()) { - this.untrackObjectiveForPlayer(objective, playerUUID); - } + if (this.objectiveDataStore != null) { + for (UUID playerUUID : objective.getPlayerUUIDs()) { + this.untrackObjectiveForPlayer(objective, playerUUID); + } - UUID objectiveUUID = objective.getObjectiveUUID(); - this.objectiveDataStore.removeObjective(objectiveUUID); - if (this.objectiveDataStore.removeFromDisk(objectiveUUID.toString())) { - ObjectiveLineAsset objectiveLineAsset = objective.getObjectiveLineAsset(); - if (objectiveLineAsset == null) { - this.storeObjectiveHistoryData(objective); - } else { - ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData(); - - assert objectiveLineHistoryData != null; - - objectiveLineHistoryData.addObjectiveHistoryData(objective.getObjectiveHistoryData()); - String nextObjectiveId = objectiveLineAsset.getNextObjectiveId(objective.getObjectiveId()); - if (nextObjectiveId != null) { - Objective newObjective = this.startObjective( - nextObjectiveId, objectiveUUID, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID(), store - ); - if (newObjective != null) { - newObjective.setObjectiveLineHistoryData(objectiveLineHistoryData); - newObjective.checkTaskSetCompletion(store); - } + UUID objectiveUUID = objective.getObjectiveUUID(); + this.objectiveDataStore.removeObjective(objectiveUUID); + if (this.objectiveDataStore.removeFromDisk(objectiveUUID.toString())) { + ObjectiveLineAsset objectiveLineAsset = objective.getObjectiveLineAsset(); + if (objectiveLineAsset == null) { + this.storeObjectiveHistoryData(objective); } else { - this.storeObjectiveLineHistoryData(objectiveLineHistoryData, objective.getPlayerUUIDs()); - String[] nextObjectiveLineIds = objectiveLineHistoryData.getNextObjectiveLineIds(); - if (nextObjectiveLineIds != null) { - for (String nextObjectiveLineId : nextObjectiveLineIds) { - this.startObjectiveLine(store, nextObjectiveLineId, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID()); + ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData(); + + assert objectiveLineHistoryData != null; + + objectiveLineHistoryData.addObjectiveHistoryData(objective.getObjectiveHistoryData()); + String nextObjectiveId = objectiveLineAsset.getNextObjectiveId(objective.getObjectiveId()); + if (nextObjectiveId != null) { + Objective newObjective = this.startObjective( + nextObjectiveId, objectiveUUID, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID(), store + ); + if (newObjective != null) { + newObjective.setObjectiveLineHistoryData(objectiveLineHistoryData); + newObjective.checkTaskSetCompletion(store); + } + } else { + this.storeObjectiveLineHistoryData(objectiveLineHistoryData, objective.getPlayerUUIDs()); + String[] nextObjectiveLineIds = objectiveLineHistoryData.getNextObjectiveLineIds(); + if (nextObjectiveLineIds != null) { + for (String nextObjectiveLineId : nextObjectiveLineIds) { + this.startObjectiveLine(store, nextObjectiveLineId, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID()); + } } } } @@ -590,118 +640,130 @@ public class ObjectivePlugin extends JavaPlugin { } public void cancelObjective(@Nonnull UUID objectiveUUID, @Nonnull Store store) { - Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); - if (objective != null) { - objective.cancel(); + if (this.objectiveDataStore != null) { + Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); + if (objective != null) { + objective.cancel(); - for (UUID playerUUID : objective.getPlayerUUIDs()) { - this.untrackObjectiveForPlayer(objective, playerUUID); + for (UUID playerUUID : objective.getPlayerUUIDs()) { + this.untrackObjectiveForPlayer(objective, playerUUID); + } + + this.objectiveDataStore.removeObjective(objectiveUUID); + this.objectiveDataStore.removeFromDisk(objectiveUUID.toString()); } - - this.objectiveDataStore.removeObjective(objectiveUUID); - this.objectiveDataStore.removeFromDisk(objectiveUUID.toString()); } } public void untrackObjectiveForPlayer(@Nonnull Objective objective, @Nonnull UUID playerUUID) { - UUID objectiveUUID = objective.getObjectiveUUID(); - ObjectiveTask[] currentTasks = objective.getCurrentTasks(); - - for (ObjectiveTask task : currentTasks) { - if (task instanceof UseEntityObjectiveTask useEntityObjectiveTask) { - this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, useEntityObjectiveTask.getAsset().getTaskId(), playerUUID); - } - } - - PlayerRef playerRef = Universe.get().getPlayer(playerUUID); - if (playerRef != null) { - Player player = playerRef.getComponent(Player.getComponentType()); - HashSet activeObjectiveUUIDs = new HashSet<>(player.getPlayerConfigData().getActiveObjectiveUUIDs()); - activeObjectiveUUIDs.remove(objectiveUUID); - player.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs); - playerRef.getPacketHandler().writeNoCache(new UntrackObjective(objectiveUUID)); - } - } - - public void addPlayerToExistingObjective(@Nonnull Store store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) { - Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); - if (objective != null) { - objective.addActivePlayerUUID(playerUUID); - ObjectiveDataStore objectiveDataStore = get().getObjectiveDataStore(); + if (this.objectiveDataStore != null) { + UUID objectiveUUID = objective.getObjectiveUUID(); ObjectiveTask[] currentTasks = objective.getCurrentTasks(); for (ObjectiveTask task : currentTasks) { - if (task instanceof UseEntityObjectiveTask) { - objectiveDataStore.addEntityTaskForPlayer(playerUUID, ((UseEntityObjectiveTask)task).getAsset().getTaskId(), objectiveUUID); + if (task instanceof UseEntityObjectiveTask useEntityObjectiveTask) { + this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, useEntityObjectiveTask.getAsset().getTaskId(), playerUUID); } } PlayerRef playerRef = Universe.get().getPlayer(playerUUID); - if (playerRef != null && playerRef.isValid()) { - Ref playerReference = playerRef.getReference(); - if (playerReference != null && playerReference.isValid()) { - Player playerComponent = store.getComponent(playerReference, Player.getComponentType()); + if (playerRef != null) { + Player player = playerRef.getComponent(Player.getComponentType()); + HashSet activeObjectiveUUIDs = new HashSet<>(player.getPlayerConfigData().getActiveObjectiveUUIDs()); + activeObjectiveUUIDs.remove(objectiveUUID); + player.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs); + playerRef.getPacketHandler().writeNoCache(new UntrackObjective(objectiveUUID)); + } + } + } - assert playerComponent != null; + public void addPlayerToExistingObjective(@Nonnull Store store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) { + if (this.objectiveDataStore != null) { + Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); + if (objective != null) { + objective.addActivePlayerUUID(playerUUID); + ObjectiveDataStore objectiveDataStore = get().getObjectiveDataStore(); + ObjectiveTask[] currentTasks = objective.getCurrentTasks(); - HashSet activeObjectiveUUIDs = new HashSet<>(playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs()); - activeObjectiveUUIDs.add(objectiveUUID); - playerComponent.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs); - playerRef.getPacketHandler().writeNoCache(new TrackOrUpdateObjective(objective.toPacket())); + for (ObjectiveTask task : currentTasks) { + if (task instanceof UseEntityObjectiveTask) { + objectiveDataStore.addEntityTaskForPlayer(playerUUID, ((UseEntityObjectiveTask)task).getAsset().getTaskId(), objectiveUUID); + } + } + + PlayerRef playerRef = Universe.get().getPlayer(playerUUID); + if (playerRef != null && playerRef.isValid()) { + Ref playerReference = playerRef.getReference(); + if (playerReference != null && playerReference.isValid()) { + Player playerComponent = store.getComponent(playerReference, Player.getComponentType()); + + assert playerComponent != null; + + HashSet activeObjectiveUUIDs = new HashSet<>(playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs()); + activeObjectiveUUIDs.add(objectiveUUID); + playerComponent.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs); + playerRef.getPacketHandler().writeNoCache(new TrackOrUpdateObjective(objective.toPacket())); + } } } } } public void removePlayerFromExistingObjective(@Nonnull Store store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) { - Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); - if (objective != null) { - objective.removeActivePlayerUUID(playerUUID); - if (objective.getActivePlayerUUIDs().isEmpty()) { - this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective); - this.objectiveDataStore.unloadObjective(objectiveUUID); - } + if (this.objectiveDataStore != null) { + Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); + if (objective != null) { + objective.removeActivePlayerUUID(playerUUID); + if (objective.getActivePlayerUUIDs().isEmpty()) { + this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective); + this.objectiveDataStore.unloadObjective(objectiveUUID); + } - this.untrackObjectiveForPlayer(objective, playerUUID); + this.untrackObjectiveForPlayer(objective, playerUUID); + } } } private void onPlayerDisconnect(@Nonnull PlayerDisconnectEvent event) { - PlayerRef playerRef = event.getPlayerRef(); - Ref ref = playerRef.getReference(); - if (ref != null) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute( - () -> { - if (ref.isValid()) { - UUID playerUUID = playerRef.getUuid(); - this.getLogger().at(Level.INFO).log("Checking objectives for disconnecting player '" + playerRef.getUsername() + "' (" + playerUUID + ")"); - Player playerComponent = store.getComponent(ref, Player.getComponentType()); - if (playerComponent != null) { - Set activeObjectiveUUIDs = playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs(); - if (activeObjectiveUUIDs == null) { - this.getLogger().at(Level.INFO).log("No active objectives found for player '" + playerRef.getUsername() + "' (" + playerUUID + ")"); - } else { - this.getLogger() - .at(Level.INFO) - .log("Processing " + activeObjectiveUUIDs.size() + " active objectives for '" + playerRef.getUsername() + "' (" + playerUUID + ")"); + if (this.objectiveDataStore != null) { + PlayerRef playerRef = event.getPlayerRef(); + Ref ref = playerRef.getReference(); + if (ref != null) { + Store store = ref.getStore(); + World world = store.getExternalData().getWorld(); + world.execute( + () -> { + if (ref.isValid()) { + UUID playerUUID = playerRef.getUuid(); + this.getLogger().at(Level.INFO).log("Checking objectives for disconnecting player '" + playerRef.getUsername() + "' (" + playerUUID + ")"); + Player playerComponent = store.getComponent(ref, Player.getComponentType()); + if (playerComponent != null) { + Set activeObjectiveUUIDs = playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs(); + if (activeObjectiveUUIDs == null) { + this.getLogger().at(Level.INFO).log("No active objectives found for player '" + playerRef.getUsername() + "' (" + playerUUID + ")"); + } else { + this.getLogger() + .at(Level.INFO) + .log( + "Processing " + activeObjectiveUUIDs.size() + " active objectives for '" + playerRef.getUsername() + "' (" + playerUUID + ")" + ); - for (UUID objectiveUUID : activeObjectiveUUIDs) { - Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); - if (objective != null) { - objective.removeActivePlayerUUID(playerUUID); - if (objective.getActivePlayerUUIDs().isEmpty()) { - this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective); - this.objectiveDataStore.unloadObjective(objectiveUUID); + for (UUID objectiveUUID : activeObjectiveUUIDs) { + Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); + if (objective != null) { + objective.removeActivePlayerUUID(playerUUID); + if (objective.getActivePlayerUUIDs().isEmpty()) { + this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective); + this.objectiveDataStore.unloadObjective(objectiveUUID); + } } } } } } } - } - ); + ); + } } } @@ -731,7 +793,11 @@ public class ObjectivePlugin extends JavaPlugin { } private void onObjectiveAssetLoaded(@Nonnull LoadedAssetsEvent> event) { - this.objectiveDataStore.getObjectiveCollection().forEach(objective -> objective.reloadObjectiveAsset(event.getLoadedAssets())); + if (this.objectiveDataStore != null) { + for (Objective objective : this.objectiveDataStore.getObjectiveCollection()) { + objective.reloadObjectiveAsset(event.getLoadedAssets()); + } + } } private static void onObjectiveLocationMarkerChange( @@ -818,43 +884,47 @@ public class ObjectivePlugin extends JavaPlugin { } private void onLivingEntityInventoryChange(@Nonnull LivingEntityInventoryChangeEvent event) { - LivingEntity entity = event.getEntity(); - if (entity instanceof Player player) { - Set activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); - if (!activeObjectiveUUIDs.isEmpty()) { - Set inventoryItemObjectiveUUIDs = null; - CombinedItemContainer inventory = entity.getInventory().getCombinedHotbarFirst(); + if (this.objectiveDataStore != null) { + if (event.getEntity() instanceof Player player) { + Set activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); + if (!activeObjectiveUUIDs.isEmpty()) { + Set inventoryItemObjectiveUUIDs = null; + CombinedItemContainer inventory = player.getInventory().getCombinedHotbarFirst(); - for (short i = 0; i < inventory.getCapacity(); i++) { - ItemStack itemStack = inventory.getItemStack(i); - if (!ItemStack.isEmpty(itemStack)) { - UUID objectiveUUID = itemStack.getFromMetadataOrNull(StartObjectiveInteraction.OBJECTIVE_UUID); - if (objectiveUUID != null) { - if (inventoryItemObjectiveUUIDs == null) { - inventoryItemObjectiveUUIDs = new HashSet<>(activeObjectiveUUIDs); + for (short i = 0; i < inventory.getCapacity(); i++) { + ItemStack itemStack = inventory.getItemStack(i); + if (!ItemStack.isEmpty(itemStack)) { + UUID objectiveUUID = itemStack.getFromMetadataOrNull(StartObjectiveInteraction.OBJECTIVE_UUID); + if (objectiveUUID != null) { + if (inventoryItemObjectiveUUIDs == null) { + inventoryItemObjectiveUUIDs = new HashSet<>(activeObjectiveUUIDs); + } + + inventoryItemObjectiveUUIDs.add(objectiveUUID); } - - inventoryItemObjectiveUUIDs.add(objectiveUUID); } } - } - for (UUID activeObjectiveUUID : activeObjectiveUUIDs) { - if (inventoryItemObjectiveUUIDs == null || !inventoryItemObjectiveUUIDs.contains(activeObjectiveUUID)) { - Objective objective = this.objectiveDataStore.getObjective(activeObjectiveUUID); - if (objective != null) { - ObjectiveAsset objectiveAsset = objective.getObjectiveAsset(); - if (objectiveAsset != null && objectiveAsset.isRemoveOnItemDrop()) { - Ref reference = entity.getReference(); - Store store = reference.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - UUIDComponent uuidComponent = store.getComponent(reference, UUIDComponent.getComponentType()); + Ref reference = player.getReference(); + if (reference != null && reference.isValid()) { + Store store = reference.getStore(); + World world = store.getExternalData().getWorld(); - assert uuidComponent != null; + for (UUID activeObjectiveUUID : activeObjectiveUUIDs) { + if (inventoryItemObjectiveUUIDs == null || !inventoryItemObjectiveUUIDs.contains(activeObjectiveUUID)) { + Objective objective = this.objectiveDataStore.getObjective(activeObjectiveUUID); + if (objective != null) { + ObjectiveAsset objectiveAsset = objective.getObjectiveAsset(); + if (objectiveAsset != null && objectiveAsset.isRemoveOnItemDrop()) { + world.execute(() -> { + UUIDComponent uuidComponent = store.getComponent(reference, UUIDComponent.getComponentType()); - get().removePlayerFromExistingObjective(store, uuidComponent.getUuid(), activeObjectiveUUID); - }); + assert uuidComponent != null; + + get().removePlayerFromExistingObjective(store, uuidComponent.getUuid(), activeObjectiveUUID); + }); + } + } } } } @@ -870,20 +940,23 @@ public class ObjectivePlugin extends JavaPlugin { @Nonnull public String getObjectiveDataDump() { StringBuilder sb = new StringBuilder("Objective Data\n"); - - for (Objective objective : this.objectiveDataStore.getObjectiveCollection()) { - sb.append("Objective ID: ") - .append(objective.getObjectiveId()) - .append("\n\t") - .append("UUID: ") - .append(objective.getObjectiveUUID()) - .append("\n\t") - .append("Players: ") - .append(Arrays.toString(objective.getPlayerUUIDs().toArray())) - .append("\n\t") - .append("Active players: ") - .append(Arrays.toString(objective.getActivePlayerUUIDs().toArray())) - .append("\n\n"); + if (this.objectiveDataStore != null) { + for (Objective objective : this.objectiveDataStore.getObjectiveCollection()) { + sb.append("Objective ID: ") + .append(objective.getObjectiveId()) + .append("\n\t") + .append("UUID: ") + .append(objective.getObjectiveUUID()) + .append("\n\t") + .append("Players: ") + .append(Arrays.toString(objective.getPlayerUUIDs().toArray())) + .append("\n\t") + .append("Active players: ") + .append(Arrays.toString(objective.getActivePlayerUUIDs().toArray())) + .append("\n\n"); + } + } else { + sb.append("Objective data store is not initialized.\n"); } return sb.toString(); diff --git a/src/com/hypixel/hytale/builtin/adventure/objectives/commands/ObjectiveCompleteCommand.java b/src/com/hypixel/hytale/builtin/adventure/objectives/commands/ObjectiveCompleteCommand.java index e48b11f7..264c24a0 100644 --- a/src/com/hypixel/hytale/builtin/adventure/objectives/commands/ObjectiveCompleteCommand.java +++ b/src/com/hypixel/hytale/builtin/adventure/objectives/commands/ObjectiveCompleteCommand.java @@ -76,7 +76,7 @@ public class ObjectiveCompleteCommand extends AbstractCommandCollection { String objectiveId = this.objectiveArg.get(context); Objective objective = ObjectiveCompleteCommand.getObjectiveFromId(ref, objectiveId, store); if (objective == null) { - context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND); + context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND.param("id", objectiveId)); } else { ObjectiveTask[] tasks = objective.getCurrentTasks(); if (tasks == null) { @@ -114,7 +114,7 @@ public class ObjectiveCompleteCommand extends AbstractCommandCollection { int taskIndex = this.taskIndexArg.get(context); Objective objective = ObjectiveCompleteCommand.getObjectiveFromId(ref, objectiveId, store); if (objective == null) { - context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND); + context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND.param("id", objectiveId)); } else { ObjectiveTask[] tasks = objective.getCurrentTasks(); if (taskIndex >= tasks.length) { @@ -146,7 +146,7 @@ public class ObjectiveCompleteCommand extends AbstractCommandCollection { String objectiveId = this.objectiveArg.get(context); Objective objective = ObjectiveCompleteCommand.getObjectiveFromId(ref, objectiveId, store); if (objective == null) { - context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND); + context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND.param("id", objectiveId)); } else { ObjectiveTask[] tasks = objective.getCurrentTasks(); if (tasks != null && tasks.length != 0) { diff --git a/src/com/hypixel/hytale/builtin/adventure/objectives/markers/objectivelocation/ObjectiveLocationMarkerSystems.java b/src/com/hypixel/hytale/builtin/adventure/objectives/markers/objectivelocation/ObjectiveLocationMarkerSystems.java index 21871252..98200424 100644 --- a/src/com/hypixel/hytale/builtin/adventure/objectives/markers/objectivelocation/ObjectiveLocationMarkerSystems.java +++ b/src/com/hypixel/hytale/builtin/adventure/objectives/markers/objectivelocation/ObjectiveLocationMarkerSystems.java @@ -57,11 +57,21 @@ import javax.annotation.Nullable; public class ObjectiveLocationMarkerSystems { public static class EnsureNetworkSendableSystem extends HolderSystem { @Nonnull - private final Query query = Query.and(ObjectiveLocationMarker.getComponentType(), Query.not(NetworkId.getComponentType())); + private final ComponentType networkIdComponentType; + @Nonnull + private final Query query; + + public EnsureNetworkSendableSystem( + @Nonnull ComponentType objectiveLocationMarkerComponentType, + @Nonnull ComponentType networkIdComponentType + ) { + this.networkIdComponentType = networkIdComponentType; + this.query = Query.and(objectiveLocationMarkerComponentType, Query.not(networkIdComponentType)); + } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId())); + holder.addComponent(this.networkIdComponentType, new NetworkId(store.getExternalData().takeNextNetworkId())); } @Override @@ -83,13 +93,21 @@ public class ObjectiveLocationMarkerSystems { @Nonnull private final ComponentType transformComponentType; @Nonnull + private final ComponentType prefabCopyableComponentType; + @Nonnull private final Query query; - public InitSystem(@Nonnull ComponentType objectiveLocationMarkerComponent) { + public InitSystem( + @Nonnull ComponentType objectiveLocationMarkerComponent, + @Nonnull ComponentType modelComponentType, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType prefabCopyableComponentType + ) { this.objectiveLocationMarkerComponent = objectiveLocationMarkerComponent; - this.modelComponentType = ModelComponent.getComponentType(); - this.transformComponentType = TransformComponent.getComponentType(); - this.query = Query.and(objectiveLocationMarkerComponent, this.modelComponentType, this.transformComponentType); + this.modelComponentType = modelComponentType; + this.transformComponentType = transformComponentType; + this.prefabCopyableComponentType = prefabCopyableComponentType; + this.query = Query.and(objectiveLocationMarkerComponent, modelComponentType, transformComponentType); } @Nonnull @@ -171,7 +189,7 @@ public class ObjectiveLocationMarkerSystems { ) ) ); - commandBuffer.ensureComponent(ref, PrefabCopyableComponent.getComponentType()); + commandBuffer.ensureComponent(ref, this.prefabCopyableComponentType); } } @@ -201,11 +219,11 @@ public class ObjectiveLocationMarkerSystems { @Nonnull private final ComponentType playerRefComponentType; @Nonnull - private final ComponentType transformComponentType = TransformComponent.getComponentType(); + private final ComponentType transformComponentType; @Nonnull - private final ComponentType weatherTrackerComponentType = WeatherTracker.getComponentType(); + private final ComponentType weatherTrackerComponentType; @Nonnull - private final ComponentType uuidComponentType = UUIDComponent.getComponentType(); + private final ComponentType uuidComponentType; @Nonnull private final ResourceType, EntityStore>> playerSpatialComponent; @Nonnull @@ -216,12 +234,18 @@ public class ObjectiveLocationMarkerSystems { public TickingSystem( @Nonnull ComponentType objectiveLocationMarkerComponentType, @Nonnull ComponentType playerRefComponentType, - @Nonnull ResourceType, EntityStore>> playerSpatialComponent + @Nonnull ResourceType, EntityStore>> playerSpatialComponent, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType weatherTrackerComponentType, + @Nonnull ComponentType uuidComponentType ) { this.objectiveLocationMarkerComponentType = objectiveLocationMarkerComponentType; this.playerRefComponentType = playerRefComponentType; + this.transformComponentType = transformComponentType; + this.weatherTrackerComponentType = weatherTrackerComponentType; + this.uuidComponentType = uuidComponentType; this.playerSpatialComponent = playerSpatialComponent; - this.query = Archetype.of(objectiveLocationMarkerComponentType, this.transformComponentType, this.uuidComponentType); + this.query = Archetype.of(objectiveLocationMarkerComponentType, transformComponentType, uuidComponentType); this.dependencies = Set.of(new SystemDependency<>(Order.AFTER, PlayerSpatialSystem.class, OrderPriority.CLOSEST)); } @@ -278,20 +302,20 @@ public class ObjectiveLocationMarkerSystems { this.setupMarker(store, objectiveLocationMarkerComponent, entityReference, position, uuid, commandBuffer); } else if (!activeObjective.isCompleted()) { SpatialResource, EntityStore> spatialResource = store.getResource(this.playerSpatialComponent); - ObjectList> playerReferences = SpatialResource.getThreadLocalReferenceList(); - objectiveLocationMarkerComponent.area.getPlayersInExitArea(spatialResource, playerReferences, position); - HashSet playersInExitArea = new HashSet<>(playerReferences.size()); - PlayerRef[] playersInEntryArea = new PlayerRef[playerReferences.size()]; + ObjectList> playerRefs = SpatialResource.getThreadLocalReferenceList(); + objectiveLocationMarkerComponent.area.getPlayersInExitArea(spatialResource, playerRefs, position); + HashSet playersInExitArea = new HashSet<>(playerRefs.size()); + PlayerRef[] playersInEntryArea = new PlayerRef[playerRefs.size()]; int playersInEntryAreaSize = 0; - for (Ref playerReference : playerReferences) { - PlayerRef playerRefComponent = commandBuffer.getComponent(playerReference, this.playerRefComponentType); + for (Ref playerRef : playerRefs) { + PlayerRef playerRefComponent = commandBuffer.getComponent(playerRef, this.playerRefComponentType); if (playerRefComponent != null) { - UUIDComponent playerUuidComponent = commandBuffer.getComponent(playerReference, this.uuidComponentType); + UUIDComponent playerUuidComponent = commandBuffer.getComponent(playerRef, this.uuidComponentType); if (playerUuidComponent != null) { - TransformComponent playerTransformComponent = commandBuffer.getComponent(playerReference, this.transformComponentType); + TransformComponent playerTransformComponent = commandBuffer.getComponent(playerRef, this.transformComponentType); if (playerTransformComponent != null) { - WeatherTracker playerWeatherTrackerComponent = commandBuffer.getComponent(playerReference, this.weatherTrackerComponentType); + WeatherTracker playerWeatherTrackerComponent = commandBuffer.getComponent(playerRef, this.weatherTrackerComponentType); if (playerWeatherTrackerComponent != null && isPlayerInSpecificEnvironment( objectiveLocationMarkerComponent, playerWeatherTrackerComponent, playerTransformComponent, commandBuffer @@ -437,13 +461,13 @@ public class ObjectiveLocationMarkerSystems { private static boolean isPlayerInSpecificEnvironment( @Nonnull ObjectiveLocationMarker entity, @Nonnull WeatherTracker weatherTracker, - @Nonnull TransformComponent transform, + @Nonnull TransformComponent transformComponent, @Nonnull ComponentAccessor componentAccessor ) { if (entity.environmentIndexes == null) { return true; } else { - weatherTracker.updateEnvironment(transform, componentAccessor); + weatherTracker.updateEnvironment(transformComponent, componentAccessor); int environmentIndex = weatherTracker.getEnvironmentId(); return Arrays.binarySearch(entity.environmentIndexes, environmentIndex) >= 0; } @@ -453,8 +477,8 @@ public class ObjectiveLocationMarkerSystems { ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore(); for (ObjectiveTask task : entity.getActiveObjective().getCurrentTasks()) { - if (task instanceof UseEntityObjectiveTask) { - String taskId = ((UseEntityObjectiveTask)task).getAsset().getTaskId(); + if (task instanceof UseEntityObjectiveTask useEntityObjectiveTask) { + String taskId = useEntityObjectiveTask.getAsset().getTaskId(); objectiveDataStore.removeEntityTaskForPlayer(entity.activeObjectiveUUID, taskId, playerUUID); } } diff --git a/src/com/hypixel/hytale/builtin/adventure/objectives/markers/reachlocation/ReachLocationMarkerSystems.java b/src/com/hypixel/hytale/builtin/adventure/objectives/markers/reachlocation/ReachLocationMarkerSystems.java index c6d8e1af..b9cf40d2 100644 --- a/src/com/hypixel/hytale/builtin/adventure/objectives/markers/reachlocation/ReachLocationMarkerSystems.java +++ b/src/com/hypixel/hytale/builtin/adventure/objectives/markers/reachlocation/ReachLocationMarkerSystems.java @@ -45,11 +45,22 @@ public class ReachLocationMarkerSystems { public static class EnsureNetworkSendable extends HolderSystem { @Nonnull - private final Query query = Query.and(ReachLocationMarker.getComponentType(), Query.not(NetworkId.getComponentType())); + private final ComponentType networkIdComponentType; + @Nonnull + private final Query query; + + public EnsureNetworkSendable( + @Nonnull ComponentType reachLocationMarkerComponentType, + @Nonnull ComponentType networkIdComponentType + ) { + this.networkIdComponentType = networkIdComponentType; + this.query = Query.and(reachLocationMarkerComponentType, Query.not(networkIdComponentType)); + } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId())); + int nextNetworkId = store.getExternalData().takeNextNetworkId(); + holder.addComponent(this.networkIdComponentType, new NetworkId(nextNetworkId)); } @Override @@ -64,16 +75,20 @@ public class ReachLocationMarkerSystems { } public static class EntityAdded extends RefSystem { + @Nonnull private final ComponentType reachLocationMarkerComponent; @Nonnull private final ComponentType transformComponentType; @Nonnull private final Query query; - public EntityAdded(ComponentType reachLocationMarkerComponent) { + public EntityAdded( + @Nonnull ComponentType reachLocationMarkerComponent, + @Nonnull ComponentType transformComponentType + ) { this.reachLocationMarkerComponent = reachLocationMarkerComponent; - this.transformComponentType = TransformComponent.getComponentType(); - this.query = Query.and(reachLocationMarkerComponent, this.transformComponentType); + this.transformComponentType = transformComponentType; + this.query = Query.and(reachLocationMarkerComponent, transformComponentType); } @Nonnull @@ -113,25 +128,30 @@ public class ReachLocationMarkerSystems { } public static class Ticking extends EntityTickingSystem { + @Nonnull private final ComponentType reachLocationMarkerComponent; @Nonnull private final ComponentType transformComponentType; + @Nonnull private final ResourceType, EntityStore>> playerSpatialComponent; @Nonnull - private final ComponentType uuidComponentType = UUIDComponent.getComponentType(); + private final ComponentType uuidComponentType; @Nonnull private final Query query; @Nonnull private final Set> dependencies; public Ticking( - ComponentType reachLocationMarkerComponent, - ResourceType, EntityStore>> playerSpatialComponent + @Nonnull ComponentType reachLocationMarkerComponent, + @Nonnull ResourceType, EntityStore>> playerSpatialComponent, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType uuidComponentType ) { this.reachLocationMarkerComponent = reachLocationMarkerComponent; - this.transformComponentType = TransformComponent.getComponentType(); + this.transformComponentType = transformComponentType; + this.uuidComponentType = uuidComponentType; this.playerSpatialComponent = playerSpatialComponent; - this.query = Query.and(reachLocationMarkerComponent, this.transformComponentType); + this.query = Query.and(reachLocationMarkerComponent, transformComponentType); this.dependencies = Set.of(new SystemDependency<>(Order.AFTER, PlayerSpatialSystem.class, OrderPriority.CLOSEST)); } diff --git a/src/com/hypixel/hytale/builtin/adventure/stash/StashGameplayConfig.java b/src/com/hypixel/hytale/builtin/adventure/stash/StashGameplayConfig.java index 0492443a..4bf9ec21 100644 --- a/src/com/hypixel/hytale/builtin/adventure/stash/StashGameplayConfig.java +++ b/src/com/hypixel/hytale/builtin/adventure/stash/StashGameplayConfig.java @@ -8,7 +8,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class StashGameplayConfig { + @Nonnull public static final String ID = "Stash"; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(StashGameplayConfig.class, StashGameplayConfig::new) .appendInherited( new KeyedCodec<>("ClearContainerDropList", Codec.BOOLEAN), diff --git a/src/com/hypixel/hytale/builtin/adventure/stash/StashPlugin.java b/src/com/hypixel/hytale/builtin/adventure/stash/StashPlugin.java index 150b2d61..aac5b86a 100644 --- a/src/com/hypixel/hytale/builtin/adventure/stash/StashPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/stash/StashPlugin.java @@ -38,6 +38,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class StashPlugin extends JavaPlugin { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); public StashPlugin(@Nonnull JavaPluginInit init) { @@ -95,18 +96,19 @@ public class StashPlugin extends JavaPlugin { } private static class StashSystem extends RefSystem { - private final ComponentType componentType; + @Nonnull + private final ComponentType itemContainerStateComponentType; @Nonnull private final Set> dependencies; - public StashSystem(ComponentType componentType) { - this.componentType = componentType; + public StashSystem(@Nonnull ComponentType itemContainerStateComponentType) { + this.itemContainerStateComponentType = itemContainerStateComponentType; this.dependencies = Set.of(new SystemDependency<>(Order.AFTER, BlockStateModule.LegacyBlockStateRefSystem.class)); } @Override public Query getQuery() { - return this.componentType; + return this.itemContainerStateComponentType; } @Override @@ -115,9 +117,13 @@ public class StashPlugin extends JavaPlugin { ) { World world = store.getExternalData().getWorld(); if (world.getWorldConfig().getGameMode() != GameMode.Creative) { + ItemContainerState itemContainerStateComponent = store.getComponent(ref, this.itemContainerStateComponentType); + + assert itemContainerStateComponent != null; + StashGameplayConfig stashGameplayConfig = StashGameplayConfig.getOrDefault(world.getGameplayConfig()); boolean clearContainerDropList = stashGameplayConfig.isClearContainerDropList(); - StashPlugin.stash(store.getComponent(ref, this.componentType), clearContainerDropList); + StashPlugin.stash(itemContainerStateComponent, clearContainerDropList); } } diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/TeleporterPlugin.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/TeleporterPlugin.java index 1c2a55db..b22712b1 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/TeleporterPlugin.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/TeleporterPlugin.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.builtin.adventure.teleporter.system.CreateWarpWhenTele import com.hypixel.hytale.builtin.teleport.TeleportPlugin; import com.hypixel.hytale.component.AddReason; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.RemoveReason; @@ -16,10 +17,17 @@ import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.RefChangeSystem; import com.hypixel.hytale.component.system.RefSystem; +import com.hypixel.hytale.server.core.modules.block.BlockModule; +import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; +import com.hypixel.hytale.server.core.modules.entity.teleport.PendingTeleport; +import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport; +import com.hypixel.hytale.server.core.modules.entity.teleport.TeleportRecord; +import com.hypixel.hytale.server.core.modules.interaction.components.PlacedByInteractionComponent; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; @@ -41,12 +49,29 @@ public class TeleporterPlugin extends JavaPlugin { @Override protected void setup() { - this.teleporterComponentType = this.getChunkStoreRegistry().registerComponent(Teleporter.class, "Teleporter", Teleporter.CODEC); - this.getChunkStoreRegistry().registerSystem(new TeleporterPlugin.TeleporterOwnedWarpRefChangeSystem()); - this.getChunkStoreRegistry().registerSystem(new TeleporterPlugin.TeleporterOwnedWarpRefSystem()); - this.getChunkStoreRegistry().registerSystem(new CreateWarpWhenTeleporterPlacedSystem()); - this.usedTeleporterComponentType = this.getEntityStoreRegistry().registerComponent(UsedTeleporter.class, UsedTeleporter::new); - this.getEntityStoreRegistry().registerSystem(new ClearUsedTeleporterSystem()); + ComponentRegistryProxy chunkStoreRegistry = this.getChunkStoreRegistry(); + ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); + this.teleporterComponentType = chunkStoreRegistry.registerComponent(Teleporter.class, "Teleporter", Teleporter.CODEC); + ComponentType placedByInteractionComponentType = PlacedByInteractionComponent.getComponentType(); + ComponentType blockStateInfoComponentType = BlockModule.BlockStateInfo.getComponentType(); + ComponentType playerRefComponentType = PlayerRef.getComponentType(); + ComponentType transformComponentType = TransformComponent.getComponentType(); + ComponentType teleportRecordComponentType = TeleportRecord.getComponentType(); + ComponentType teleportComponentType = Teleport.getComponentType(); + ComponentType pendingTeleportComponentType = PendingTeleport.getComponentType(); + chunkStoreRegistry.registerSystem(new TeleporterPlugin.TeleporterOwnedWarpRefChangeSystem(this.teleporterComponentType)); + chunkStoreRegistry.registerSystem(new TeleporterPlugin.TeleporterOwnedWarpRefSystem(this.teleporterComponentType)); + chunkStoreRegistry.registerSystem( + new CreateWarpWhenTeleporterPlacedSystem( + placedByInteractionComponentType, this.teleporterComponentType, blockStateInfoComponentType, playerRefComponentType + ) + ); + this.usedTeleporterComponentType = entityStoreRegistry.registerComponent(UsedTeleporter.class, UsedTeleporter::new); + entityStoreRegistry.registerSystem( + new ClearUsedTeleporterSystem( + this.usedTeleporterComponentType, transformComponentType, teleportRecordComponentType, teleportComponentType, pendingTeleportComponentType + ) + ); this.getCodecRegistry(Interaction.CODEC).register("Teleporter", TeleporterInteraction.class, TeleporterInteraction.CODEC); this.getCodecRegistry(OpenCustomUIInteraction.PAGE_CODEC) .register("Teleporter", TeleporterSettingsPageSupplier.class, TeleporterSettingsPageSupplier.CODEC); @@ -61,10 +86,17 @@ public class TeleporterPlugin extends JavaPlugin { } private static class TeleporterOwnedWarpRefChangeSystem extends RefChangeSystem { + @Nonnull + private final ComponentType teleporterComponentType; + + public TeleporterOwnedWarpRefChangeSystem(@Nonnull ComponentType teleporterComponentType) { + this.teleporterComponentType = teleporterComponentType; + } + @Nonnull @Override public ComponentType componentType() { - return Teleporter.getComponentType(); + return this.teleporterComponentType; } public void onComponentAdded( @@ -79,11 +111,13 @@ public class TeleporterPlugin extends JavaPlugin { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - String ownedWarp = oldComponent.getOwnedWarp(); - if (ownedWarp != null && !ownedWarp.isEmpty() && !ownedWarp.equals(newComponent.getOwnedWarp())) { - TeleportPlugin.get().getWarps().remove(ownedWarp.toLowerCase()); - TeleportPlugin.get().saveWarps(); - oldComponent.setOwnedWarp(null); + if (oldComponent != null) { + String ownedWarp = oldComponent.getOwnedWarp(); + if (ownedWarp != null && !ownedWarp.isEmpty() && !ownedWarp.equals(newComponent.getOwnedWarp())) { + TeleportPlugin.get().getWarps().remove(ownedWarp.toLowerCase()); + TeleportPlugin.get().saveWarps(); + oldComponent.setOwnedWarp(null); + } } } @@ -106,7 +140,12 @@ public class TeleporterPlugin extends JavaPlugin { } private static class TeleporterOwnedWarpRefSystem extends RefSystem { - public static final ComponentType COMPONENT_TYPE = Teleporter.getComponentType(); + @Nonnull + private final ComponentType teleporterComponentType; + + public TeleporterOwnedWarpRefSystem(@Nonnull ComponentType teleporterComponentType) { + this.teleporterComponentType = teleporterComponentType; + } @Override public void onEntityAdded( @@ -114,9 +153,13 @@ public class TeleporterPlugin extends JavaPlugin { ) { switch (reason) { case LOAD: - Teleporter component = commandBuffer.getComponent(ref, COMPONENT_TYPE); - String ownedWarp = component.getOwnedWarp(); - if (ownedWarp != null && !ownedWarp.isEmpty() && !TeleportPlugin.get().getWarps().containsKey(ownedWarp.toLowerCase())) { + Teleporter teleporterComponent = commandBuffer.getComponent(ref, this.teleporterComponentType); + if (teleporterComponent == null) { + return; + } else { + String ownedWarp = teleporterComponent.getOwnedWarp(); + if (ownedWarp != null && !ownedWarp.isEmpty() && !TeleportPlugin.get().getWarps().containsKey(ownedWarp.toLowerCase())) { + } } case SPAWN: } @@ -127,19 +170,24 @@ public class TeleporterPlugin extends JavaPlugin { @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { if (reason == RemoveReason.REMOVE) { - Teleporter component = commandBuffer.getComponent(ref, COMPONENT_TYPE); - String ownedWarp = component.getOwnedWarp(); + Teleporter teleporterComponent = commandBuffer.getComponent(ref, this.teleporterComponentType); + if (teleporterComponent == null) { + return; + } + + String ownedWarp = teleporterComponent.getOwnedWarp(); if (ownedWarp != null && !ownedWarp.isEmpty()) { TeleportPlugin.get().getWarps().remove(ownedWarp.toLowerCase()); TeleportPlugin.get().saveWarps(); - component.setOwnedWarp(null); + teleporterComponent.setOwnedWarp(null); } } } + @Nonnull @Override public Query getQuery() { - return COMPONENT_TYPE; + return this.teleporterComponentType; } } } diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/component/Teleporter.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/component/Teleporter.java index 86cc8ff1..faef1456 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/component/Teleporter.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/component/Teleporter.java @@ -22,6 +22,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class Teleporter implements Component { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(Teleporter.class, Teleporter::new) .append(new KeyedCodec<>("World", Codec.UUID_BINARY), (teleporter, uuid) -> teleporter.worldUuid = uuid, teleporter -> teleporter.worldUuid) .add() @@ -51,6 +52,7 @@ public class Teleporter implements Component { @Nullable private String warp; @Deprecated + @Nullable private String ownedWarp; private boolean isCustomName; private String warpNameWordListKey; @@ -94,11 +96,12 @@ public class Teleporter implements Component { this.warp = warp != null && !warp.isEmpty() ? warp : null; } + @Nullable public String getOwnedWarp() { return this.ownedWarp; } - public void setOwnedWarp(String ownedWarp) { + public void setOwnedWarp(@Nullable String ownedWarp) { this.ownedWarp = ownedWarp; } diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/interaction/server/TeleporterInteraction.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/interaction/server/TeleporterInteraction.java index 2b198beb..801be16b 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/interaction/server/TeleporterInteraction.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/interaction/server/TeleporterInteraction.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.component.spatial.SpatialResource; import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.protocol.InteractionState; import com.hypixel.hytale.protocol.InteractionType; import com.hypixel.hytale.protocol.WaitForDataFrom; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; @@ -23,7 +24,6 @@ import com.hypixel.hytale.server.core.modules.entity.EntityModule; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.teleport.PendingTeleport; import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport; -import com.hypixel.hytale.server.core.modules.entity.teleport.TeleportRecord; import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction; import com.hypixel.hytale.server.core.universe.world.ParticleUtil; @@ -33,7 +33,6 @@ import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import it.unimi.dsi.fastutil.objects.ObjectList; -import java.time.Duration; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -69,7 +68,6 @@ public class TeleporterInteraction extends SimpleBlockInteraction { .documentation("Upon reaching the warp destination, how far away one has to move along the Y axis in order to use another Teleporter.") .add() .build(); - private static final Duration TELEPORTER_GLOBAL_COOLDOWN = Duration.ofMillis(100L); @Nullable private String particle; private double clearoutXZ = 1.3; @@ -90,67 +88,95 @@ public class TeleporterInteraction extends SimpleBlockInteraction { @Nullable ItemStack itemInHand, @Nonnull Vector3i targetBlock, @Nonnull CooldownHandler cooldownHandler + ) { + boolean result = this.interact(world, commandBuffer, context, targetBlock); + if (!result) { + context.getState().state = InteractionState.Failed; + } + } + + private boolean interact( + @Nonnull World world, @Nonnull CommandBuffer commandBuffer, @Nonnull InteractionContext context, @Nonnull Vector3i targetBlock ) { ChunkStore chunkStore = world.getChunkStore(); long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.getX(), targetBlock.getZ()); BlockComponentChunk blockComponentChunk = chunkStore.getChunkComponent(chunkIndex, BlockComponentChunk.getComponentType()); - if (blockComponentChunk != null) { + if (blockComponentChunk == null) { + return false; + } else { int blockIndex = ChunkUtil.indexBlockInColumn(targetBlock.x, targetBlock.y, targetBlock.z); Ref blockRef = blockComponentChunk.getEntityReference(blockIndex); if (blockRef != null && blockRef.isValid()) { BlockModule.BlockStateInfo blockStateInfoComponent = blockRef.getStore().getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType()); - if (blockStateInfoComponent != null) { + if (blockStateInfoComponent == null) { + return false; + } else { Ref chunkRef = blockStateInfoComponent.getChunkRef(); - if (chunkRef.isValid()) { + if (!chunkRef.isValid()) { + return false; + } else { Teleporter teleporter = chunkStore.getStore().getComponent(blockRef, Teleporter.getComponentType()); - if (teleporter != null) { + if (teleporter == null) { + return false; + } else { Ref ref = context.getEntity(); Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType()); - if (playerComponent == null || !playerComponent.isWaitingForClientReady()) { + if (playerComponent != null && playerComponent.isWaitingForClientReady()) { + return false; + } else { Archetype archetype = commandBuffer.getArchetype(ref); - if (!archetype.contains(Teleport.getComponentType()) && !archetype.contains(PendingTeleport.getComponentType())) { - if (!archetype.contains(UsedTeleporter.getComponentType())) { - WorldChunk worldChunkComponent = chunkRef.getStore().getComponent(chunkRef, WorldChunk.getComponentType()); - if (worldChunkComponent != null) { - BlockType blockType = worldChunkComponent.getBlockType(targetBlock.x, targetBlock.y, targetBlock.z); - if (blockType != null) { - if (!teleporter.isValid()) { - String currentState = blockType.getStateForBlock(blockType); - if (!"default".equals(currentState)) { - BlockType variantBlockType = blockType.getBlockForState("default"); - if (variantBlockType != null) { - worldChunkComponent.setBlockInteractionState( - targetBlock.x, targetBlock.y, targetBlock.z, variantBlockType, "default", true - ); - } + if (archetype.contains(Teleport.getComponentType()) || archetype.contains(PendingTeleport.getComponentType())) { + return false; + } else if (archetype.contains(UsedTeleporter.getComponentType())) { + return false; + } else { + WorldChunk worldChunkComponent = chunkRef.getStore().getComponent(chunkRef, WorldChunk.getComponentType()); + if (worldChunkComponent == null) { + return false; + } else { + BlockType blockType = worldChunkComponent.getBlockType(targetBlock.x, targetBlock.y, targetBlock.z); + if (blockType == null) { + return false; + } else { + if (!teleporter.isValid()) { + String currentState = blockType.getStateForBlock(blockType); + if (!"default".equals(currentState)) { + BlockType variantBlockType = blockType.getBlockForState("default"); + if (variantBlockType != null) { + worldChunkComponent.setBlockInteractionState( + targetBlock.x, targetBlock.y, targetBlock.z, variantBlockType, "default", true + ); } } + } - TransformComponent transformComponent = commandBuffer.getComponent(ref, TransformComponent.getComponentType()); - if (transformComponent != null) { - Teleport teleportComponent = teleporter.toTeleport( - transformComponent.getPosition(), transformComponent.getRotation(), targetBlock + TransformComponent transformComponent = commandBuffer.getComponent(ref, TransformComponent.getComponentType()); + if (transformComponent == null) { + return false; + } else { + Teleport teleportComponent = teleporter.toTeleport( + transformComponent.getPosition(), transformComponent.getRotation(), targetBlock + ); + if (teleportComponent == null) { + return false; + } else { + commandBuffer.addComponent(ref, Teleport.getComponentType(), teleportComponent); + commandBuffer.addComponent( + ref, + UsedTeleporter.getComponentType(), + new UsedTeleporter(teleporter.getWorldUuid(), teleportComponent.getPosition(), this.clearoutXZ, this.clearoutY) ); - if (teleportComponent != null) { - TeleportRecord recorder = commandBuffer.getComponent(ref, TeleportRecord.getComponentType()); - if (recorder == null || recorder.hasElapsedSinceLastTeleport(TELEPORTER_GLOBAL_COOLDOWN)) { - commandBuffer.addComponent(ref, Teleport.getComponentType(), teleportComponent); - commandBuffer.addComponent( - ref, - UsedTeleporter.getComponentType(), - new UsedTeleporter(teleporter.getWorldUuid(), teleportComponent.getPosition(), this.clearoutXZ, this.clearoutY) - ); - if (this.particle != null) { - Vector3d particlePosition = transformComponent.getPosition(); - SpatialResource, EntityStore> playerSpatialResource = commandBuffer.getResource( - EntityModule.get().getPlayerSpatialResourceType() - ); - ObjectList> results = SpatialResource.getThreadLocalReferenceList(); - playerSpatialResource.getSpatialStructure().collect(particlePosition, 75.0, results); - ParticleUtil.spawnParticleEffect(this.particle, particlePosition, results, commandBuffer); - } - } + if (this.particle != null) { + Vector3d particlePosition = transformComponent.getPosition(); + SpatialResource, EntityStore> playerSpatialResource = commandBuffer.getResource( + EntityModule.get().getPlayerSpatialResourceType() + ); + ObjectList> results = SpatialResource.getThreadLocalReferenceList(); + playerSpatialResource.getSpatialStructure().collect(particlePosition, 75.0, results); + ParticleUtil.spawnParticleEffect(this.particle, particlePosition, results, commandBuffer); } + + return true; } } } @@ -160,6 +186,8 @@ public class TeleporterInteraction extends SimpleBlockInteraction { } } } + } else { + return false; } } } diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/page/TeleporterSettingsPage.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/page/TeleporterSettingsPage.java index 6fbc5caa..3199303a 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/page/TeleporterSettingsPage.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/page/TeleporterSettingsPage.java @@ -13,7 +13,6 @@ import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.vector.Transform; -import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime; import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType; import com.hypixel.hytale.protocol.packets.interface_.Page; @@ -38,6 +37,7 @@ import java.util.List; import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; public class TeleporterSettingsPage extends InteractiveCustomUIPage { @Nonnull @@ -103,16 +103,7 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage warps = new ObjectArrayList<>(); - warps.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.teleporter.noWarp"), "")); - - for (Warp warp : TeleportPlugin.get().getWarps().values()) { - if (!warp.getId().equalsIgnoreCase(teleporter.getOwnedWarp())) { - warps.add(new DropdownEntryInfo(LocalizableString.fromString(warp.getId()), warp.getId().toLowerCase())); - } - } - - commandBuilder.set("#WarpDropdown.Entries", warps); + commandBuilder.set("#WarpDropdown.Entries", getWarpsSortedById(teleporter.getOwnedWarp(), null)); commandBuilder.set("#WarpDropdown.Value", teleporter.getWarp() != null ? teleporter.getWarp() : ""); commandBuilder.set("#NewWarp.Value", teleporter.getOwnedWarp() != null ? teleporter.getOwnedWarp() : ""); eventBuilder.addEventBinding( @@ -138,16 +129,7 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage warps = new ObjectArrayList<>(); - warps.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.teleporter.noWarp"), "")); - - for (Warp warpx : TeleportPlugin.get().getWarps().values()) { - if (warpx.getWorld().equals(store.getExternalData().getWorld().getName()) && !warpx.getId().equalsIgnoreCase(teleporter.getOwnedWarp())) { - warps.add(new DropdownEntryInfo(LocalizableString.fromString(warpx.getId()), warpx.getId().toLowerCase())); - } - } - - commandBuilder.set("#WarpDropdown.Entries", warps); + commandBuilder.set("#WarpDropdown.Entries", getWarpsSortedById(teleporter.getOwnedWarp(), store.getExternalData().getWorld().getName())); commandBuilder.set("#WarpDropdown.Value", teleporter.getWarp() != null ? teleporter.getWarp() : ""); Message placeholder; if (teleporter.hasOwnedWarp() && !teleporter.isCustomName()) { @@ -169,109 +151,137 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage getWarpsSortedById(@NullableDecl String ownedWarpId, @NullableDecl String worldNameToFilter) { + List warps = new ObjectArrayList<>(); + warps.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.teleporter.noWarp"), "")); + ObjectArrayList sortedWarps = new ObjectArrayList<>(TeleportPlugin.get().getWarps().values()); + sortedWarps.sort((a, b) -> a.getId().compareToIgnoreCase(b.getId())); + + for (Warp warp : sortedWarps) { + if ((worldNameToFilter == null || warp.getWorld().equals(worldNameToFilter)) && !warp.getId().equalsIgnoreCase(ownedWarpId)) { + warps.add(new DropdownEntryInfo(LocalizableString.fromString(warp.getId()), warp.getId().toLowerCase())); + } + } + + return warps; + } + public void handleDataEvent(@Nonnull Ref ref, @Nonnull Store store, @Nonnull TeleporterSettingsPage.PageEventData data) { Player playerComponent = store.getComponent(ref, Player.getComponentType()); - - assert playerComponent != null; - - String language = this.playerRef.getLanguage(); - BlockModule.BlockStateInfo blockStateInfo = this.blockRef.getStore().getComponent(this.blockRef, BlockModule.BlockStateInfo.getComponentType()); - if (blockStateInfo == null) { - playerComponent.getPageManager().setPage(ref, store, Page.None); - } else { - Ref chunkRef = blockStateInfo.getChunkRef(); - if (!chunkRef.isValid()) { + if (playerComponent != null) { + String language = this.playerRef.getLanguage(); + BlockModule.BlockStateInfo blockStateInfo = this.blockRef.getStore().getComponent(this.blockRef, BlockModule.BlockStateInfo.getComponentType()); + if (blockStateInfo == null) { playerComponent.getPageManager().setPage(ref, store, Page.None); } else { - WorldChunk worldChunkComponent = chunkRef.getStore().getComponent(chunkRef, WorldChunk.getComponentType()); + Ref chunkRef = blockStateInfo.getChunkRef(); + if (!chunkRef.isValid()) { + playerComponent.getPageManager().setPage(ref, store, Page.None); + } else { + WorldChunk worldChunkComponent = chunkRef.getStore().getComponent(chunkRef, WorldChunk.getComponentType()); - assert worldChunkComponent != null; + assert worldChunkComponent != null; - int index = blockStateInfo.getIndex(); - int targetX = ChunkUtil.xFromBlockInColumn(index); - int targetY = ChunkUtil.yFromBlockInColumn(index); - int targetZ = ChunkUtil.zFromBlockInColumn(index); - new Vector3i(targetX, targetY, targetZ); - Teleporter teleporter = this.blockRef.getStore().getComponent(this.blockRef, Teleporter.getComponentType()); - String oldOwnedWarp = teleporter.getOwnedWarp(); - boolean customName = true; - if (data.ownedWarp == null || data.ownedWarp.isEmpty()) { - data.ownedWarp = CannedWarpNames.generateCannedWarpName(this.blockRef, language); - customName = false; - if (data.ownedWarp == null) { - UICommandBuilder commandBuilder = new UICommandBuilder(); - commandBuilder.set("#NewWarp.PlaceholderText", Message.translation("server.customUI.teleporter.warpNameRightHereHint")); - commandBuilder.set("#ErrorLabel.Text", Message.translation("server.customUI.teleporter.errorMissingWarpName")); - commandBuilder.set("#ErrorLabel.Visible", true); - this.sendUpdate(commandBuilder); - return; + int index = blockStateInfo.getIndex(); + int targetX = ChunkUtil.xFromBlockInColumn(index); + int targetY = ChunkUtil.yFromBlockInColumn(index); + int targetZ = ChunkUtil.zFromBlockInColumn(index); + Teleporter teleporterComponent = this.blockRef.getStore().getComponent(this.blockRef, Teleporter.getComponentType()); + if (teleporterComponent == null) { + playerComponent.getPageManager().setPage(ref, store, Page.None); + } else { + String oldOwnedWarp = teleporterComponent.getOwnedWarp(); + boolean customName = true; + if (data.warpName == null || data.warpName.isEmpty()) { + if (oldOwnedWarp == null) { + data.warpName = CannedWarpNames.generateCannedWarpName(this.blockRef, language); + customName = false; + } else { + data.warpName = oldOwnedWarp; + customName = teleporterComponent.isCustomName(); + } + + if (data.warpName == null) { + UICommandBuilder commandBuilder = new UICommandBuilder(); + commandBuilder.set("#NewWarp.PlaceholderText", Message.translation("server.customUI.teleporter.warpNameRightHereHint")); + commandBuilder.set("#ErrorLabel.Text", Message.translation("server.customUI.teleporter.errorMissingWarpName")); + commandBuilder.set("#ErrorLabel.Visible", true); + this.sendUpdate(commandBuilder); + return; + } + } + + if (!data.warpName.equalsIgnoreCase(oldOwnedWarp)) { + boolean alreadyExists = TeleportPlugin.get().getWarps().containsKey(data.warpName.toLowerCase()); + if (alreadyExists) { + UICommandBuilder commandBuilder = new UICommandBuilder(); + commandBuilder.set("#ErrorLabel.Text", Message.translation("server.customUI.teleporter.errorWarpAlreadyExists")); + commandBuilder.set("#ErrorLabel.Visible", true); + this.sendUpdate(commandBuilder); + return; + } + } + + if (oldOwnedWarp != null && !oldOwnedWarp.isEmpty()) { + TeleportPlugin.get().getWarps().remove(oldOwnedWarp.toLowerCase()); + } + + playerComponent.getPageManager().setPage(ref, store, Page.None); + CreateWarpWhenTeleporterPlacedSystem.createWarp(worldChunkComponent, blockStateInfo, data.warpName); + teleporterComponent.setOwnedWarp(data.warpName); + teleporterComponent.setIsCustomName(customName); + switch (this.mode) { + case FULL: + teleporterComponent.setWorldUuid(data.world != null && !data.world.isEmpty() ? UUID.fromString(data.world) : null); + Transform transform = new Transform(); + transform.getPosition().setX(data.x); + transform.getPosition().setY(data.y); + transform.getPosition().setZ(data.z); + transform.getRotation().setYaw(data.yaw); + transform.getRotation().setPitch(data.pitch); + transform.getRotation().setRoll(data.roll); + teleporterComponent.setTransform(transform); + teleporterComponent.setRelativeMask( + (byte)( + (data.xIsRelative ? 1 : 0) + | (data.yIsRelative ? 2 : 0) + | (data.zIsRelative ? 4 : 0) + | (data.yawIsRelative ? 8 : 0) + | (data.pitchIsRelative ? 16 : 0) + | (data.rollIsRelative ? 32 : 0) + | (data.isBlockRelative ? 64 : 0) + ) + ); + teleporterComponent.setWarp(data.warp != null && !data.warp.isEmpty() ? data.warp : null); + break; + case WARP: + teleporterComponent.setWorldUuid(null); + teleporterComponent.setTransform(null); + teleporterComponent.setWarp(data.warp != null && !data.warp.isEmpty() ? data.warp : null); + } + + String newState = "default"; + if (teleporterComponent.isValid()) { + newState = this.activeState != null ? this.activeState : "default"; + } + + boolean isDifferentState = false; + BlockType blockType = worldChunkComponent.getBlockType(targetX, targetY, targetZ); + if (blockType != null) { + String currentState = blockType.getStateForBlock(blockType); + isDifferentState = !newState.equals(currentState); + } + + if (isDifferentState) { + BlockType variantBlockType = blockType.getBlockForState(newState); + if (variantBlockType != null) { + worldChunkComponent.setBlockInteractionState(targetX, targetY, targetZ, variantBlockType, newState, true); + } + } + + blockStateInfo.markNeedsSaving(); } } - - if (!data.ownedWarp.equalsIgnoreCase(oldOwnedWarp)) { - boolean alreadyExists = TeleportPlugin.get().getWarps().containsKey(data.ownedWarp.toLowerCase()); - if (alreadyExists) { - UICommandBuilder commandBuilder = new UICommandBuilder(); - commandBuilder.set("#ErrorLabel.Text", Message.translation("server.customUI.teleporter.errorWarpAlreadyExists")); - commandBuilder.set("#ErrorLabel.Visible", true); - this.sendUpdate(commandBuilder); - return; - } - } - - if (oldOwnedWarp != null && !oldOwnedWarp.isEmpty()) { - TeleportPlugin.get().getWarps().remove(oldOwnedWarp.toLowerCase()); - } - - playerComponent.getPageManager().setPage(ref, store, Page.None); - CreateWarpWhenTeleporterPlacedSystem.createWarp(worldChunkComponent, blockStateInfo, data.ownedWarp); - teleporter.setOwnedWarp(data.ownedWarp); - teleporter.setIsCustomName(customName); - switch (this.mode) { - case FULL: - teleporter.setWorldUuid(data.world != null && !data.world.isEmpty() ? UUID.fromString(data.world) : null); - Transform transform = new Transform(); - transform.getPosition().setX(data.x); - transform.getPosition().setY(data.y); - transform.getPosition().setZ(data.z); - transform.getRotation().setYaw(data.yaw); - transform.getRotation().setPitch(data.pitch); - transform.getRotation().setRoll(data.roll); - teleporter.setTransform(transform); - teleporter.setRelativeMask( - (byte)( - (data.xIsRelative ? 1 : 0) - | (data.yIsRelative ? 2 : 0) - | (data.zIsRelative ? 4 : 0) - | (data.yawIsRelative ? 8 : 0) - | (data.pitchIsRelative ? 16 : 0) - | (data.rollIsRelative ? 32 : 0) - | (data.isBlockRelative ? 64 : 0) - ) - ); - teleporter.setWarp(data.warp != null && !data.warp.isEmpty() ? data.warp : null); - break; - case WARP: - teleporter.setWorldUuid(null); - teleporter.setTransform(null); - teleporter.setWarp(data.warp != null && !data.warp.isEmpty() ? data.warp : null); - } - - String newState = "default"; - if (teleporter.isValid()) { - newState = this.activeState != null ? this.activeState : "default"; - } - - BlockType blockType = worldChunkComponent.getBlockType(targetX, targetY, targetZ); - String currentState = blockType.getStateForBlock(blockType); - if (currentState == null || !currentState.equals(newState)) { - BlockType variantBlockType = blockType.getBlockForState(newState); - if (variantBlockType != null) { - worldChunkComponent.setBlockInteractionState(targetX, targetY, targetZ, variantBlockType, newState, true); - } - } - - blockStateInfo.markNeedsSaving(); } } } @@ -280,26 +290,44 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage CODEC = new EnumCodec<>(TeleporterSettingsPage.Mode.class); } public static class PageEventData { + @Nonnull public static final String KEY_BLOCK_RELATIVE = "@BlockRelative"; + @Nonnull public static final String KEY_X = "@X"; + @Nonnull public static final String KEY_Y = "@Y"; + @Nonnull public static final String KEY_Z = "@Z"; + @Nonnull public static final String KEY_X_IS_RELATIVE = "@XIsRelative"; + @Nonnull public static final String KEY_Y_IS_RELATIVE = "@YIsRelative"; + @Nonnull public static final String KEY_Z_IS_RELATIVE = "@ZIsRelative"; + @Nonnull public static final String KEY_YAW = "@Yaw"; + @Nonnull public static final String KEY_PITCH = "@Pitch"; + @Nonnull public static final String KEY_ROLL = "@Roll"; + @Nonnull public static final String KEY_YAW_IS_RELATIVE = "@YawIsRelative"; + @Nonnull public static final String KEY_PITCH_IS_RELATIVE = "@PitchIsRelative"; + @Nonnull public static final String KEY_ROLL_IS_RELATIVE = "@RollIsRelative"; + @Nonnull public static final String KEY_WORLD = "@World"; + @Nonnull public static final String KEY_WARP = "@Warp"; + @Nonnull public static final String KEY_NEW_WARP = "@NewWarp"; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( TeleporterSettingsPage.PageEventData.class, TeleporterSettingsPage.PageEventData::new ) @@ -355,7 +383,7 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage("@Warp", Codec.STRING), (pageEventData, o) -> pageEventData.warp = o, pageEventData -> pageEventData.warp) .add() - .append(new KeyedCodec<>("@NewWarp", Codec.STRING), (pageEventData, o) -> pageEventData.ownedWarp = o, pageEventData -> pageEventData.ownedWarp) + .append(new KeyedCodec<>("@NewWarp", Codec.STRING), (pageEventData, o) -> pageEventData.warpName = o, pageEventData -> pageEventData.warpName) .add() .build(); public boolean isBlockRelative; @@ -374,6 +402,6 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage CODEC = BuilderCodec.builder( TeleporterSettingsPageSupplier.class, TeleporterSettingsPageSupplier::new ) diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/system/ClearUsedTeleporterSystem.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/system/ClearUsedTeleporterSystem.java index d514097e..21841efb 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/system/ClearUsedTeleporterSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/system/ClearUsedTeleporterSystem.java @@ -1,60 +1,117 @@ package com.hypixel.hytale.builtin.adventure.teleporter.system; import com.hypixel.hytale.builtin.adventure.teleporter.interaction.server.UsedTeleporter; +import com.hypixel.hytale.component.Archetype; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.component.dependency.Dependency; +import com.hypixel.hytale.component.dependency.Order; +import com.hypixel.hytale.component.dependency.SystemDependency; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.tick.EntityTickingSystem; import com.hypixel.hytale.math.vector.Vector2d; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; +import com.hypixel.hytale.server.core.modules.entity.teleport.PendingTeleport; +import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport; +import com.hypixel.hytale.server.core.modules.entity.teleport.TeleportRecord; +import com.hypixel.hytale.server.core.modules.entity.teleport.TeleportSystems; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import java.time.Duration; +import java.util.Set; import java.util.UUID; -import javax.annotation.Nullable; -import org.checkerframework.checker.nullness.compatqual.NonNullDecl; -import org.checkerframework.checker.nullness.compatqual.NullableDecl; +import javax.annotation.Nonnull; public class ClearUsedTeleporterSystem extends EntityTickingSystem { + @Nonnull + public static final Duration TELEPORTER_GLOBAL_COOLDOWN = Duration.ofMillis(100L); + @Nonnull + private static final Set> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, TeleportSystems.PlayerMoveSystem.class)); + @Nonnull + private final ComponentType usedTeleporterComponentType; + @Nonnull + private final ComponentType transformComponentType; + @Nonnull + private final ComponentType teleportRecordComponentType; + @Nonnull + private final ComponentType teleportComponentType; + @Nonnull + private final ComponentType pendingTeleportComponentType; + + public ClearUsedTeleporterSystem( + @Nonnull ComponentType usedTeleporterComponentType, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType teleportRecordComponentType, + @Nonnull ComponentType teleportComponentType, + @Nonnull ComponentType pendingTeleportComponentType + ) { + this.usedTeleporterComponentType = usedTeleporterComponentType; + this.transformComponentType = transformComponentType; + this.teleportRecordComponentType = teleportRecordComponentType; + this.teleportComponentType = teleportComponentType; + this.pendingTeleportComponentType = pendingTeleportComponentType; + } + + @Nonnull + @Override + public Set> getDependencies() { + return DEPENDENCIES; + } + @Override public void tick( float dt, int index, - @NonNullDecl ArchetypeChunk archetypeChunk, - @NonNullDecl Store store, - @NonNullDecl CommandBuffer commandBuffer + @Nonnull ArchetypeChunk archetypeChunk, + @Nonnull Store store, + @Nonnull CommandBuffer commandBuffer ) { World world = store.getExternalData().getWorld(); - UsedTeleporter usedTeleporter = archetypeChunk.getComponent(index, UsedTeleporter.getComponentType()); - TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); - if (shouldClear(world, usedTeleporter, transformComponent)) { + if (this.shouldClear(world, index, archetypeChunk)) { Ref ref = archetypeChunk.getReferenceTo(index); - commandBuffer.removeComponent(ref, UsedTeleporter.getComponentType()); + commandBuffer.removeComponent(ref, this.usedTeleporterComponentType); } } - private static boolean shouldClear(World entityWorld, UsedTeleporter usedTeleporter, @Nullable TransformComponent transformComponent) { + private boolean shouldClear(@Nonnull World world, int index, @Nonnull ArchetypeChunk archetypeChunk) { + UsedTeleporter usedTeleporter = archetypeChunk.getComponent(index, this.usedTeleporterComponentType); + + assert usedTeleporter != null; + + TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType); + TeleportRecord teleportRecord = archetypeChunk.getComponent(index, this.teleportRecordComponentType); if (transformComponent == null) { return true; } else { - UUID destinationWorldUuid = usedTeleporter.getDestinationWorldUuid(); - if (destinationWorldUuid != null && !entityWorld.getWorldConfig().getUuid().equals(destinationWorldUuid)) { - return true; + Archetype archetype = archetypeChunk.getArchetype(); + if (!archetype.contains(this.teleportComponentType) && !archetype.contains(this.pendingTeleportComponentType)) { + if (teleportRecord != null && !teleportRecord.hasElapsedSinceLastTeleport(System.nanoTime(), TELEPORTER_GLOBAL_COOLDOWN)) { + return false; + } else { + UUID destinationWorldUuid = usedTeleporter.getDestinationWorldUuid(); + if (destinationWorldUuid != null && !world.getWorldConfig().getUuid().equals(destinationWorldUuid)) { + return true; + } else { + Vector3d entityPosition = transformComponent.getPosition(); + Vector3d destinationPosition = usedTeleporter.getDestinationPosition(); + double deltaY = Math.abs(entityPosition.y - destinationPosition.y); + double distanceXZsq = Vector2d.distanceSquared(entityPosition.x, entityPosition.z, destinationPosition.x, destinationPosition.z); + return deltaY > usedTeleporter.getClearOutY() || distanceXZsq > usedTeleporter.getClearOutXZ(); + } + } } else { - Vector3d entityPosition = transformComponent.getPosition(); - Vector3d destinationPosition = usedTeleporter.getDestinationPosition(); - double deltaY = Math.abs(entityPosition.y - destinationPosition.y); - double distanceXZsq = Vector2d.distanceSquared(entityPosition.x, entityPosition.z, destinationPosition.x, destinationPosition.z); - return deltaY > usedTeleporter.getClearOutY() || distanceXZsq > usedTeleporter.getClearOutXZ(); + return false; } } } - @NullableDecl + @Nonnull @Override public Query getQuery() { - return UsedTeleporter.getComponentType(); + return this.usedTeleporterComponentType; } } diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/system/CreateWarpWhenTeleporterPlacedSystem.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/system/CreateWarpWhenTeleporterPlacedSystem.java index 4f0debee..80ebef23 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/system/CreateWarpWhenTeleporterPlacedSystem.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/system/CreateWarpWhenTeleporterPlacedSystem.java @@ -31,6 +31,30 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class CreateWarpWhenTeleporterPlacedSystem extends RefChangeSystem { + @Nonnull + private final ComponentType placedByInteractionComponentType; + @Nonnull + private final ComponentType teleporterComponentType; + @Nonnull + private final ComponentType blockStateInfoComponentType; + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final Query query; + + public CreateWarpWhenTeleporterPlacedSystem( + @Nonnull ComponentType placedByInteractionComponentType, + @Nonnull ComponentType teleporterComponentType, + @Nonnull ComponentType blockStateInfoComponentType, + @Nonnull ComponentType playerRefComponentType + ) { + this.placedByInteractionComponentType = placedByInteractionComponentType; + this.teleporterComponentType = teleporterComponentType; + this.blockStateInfoComponentType = blockStateInfoComponentType; + this.playerRefComponentType = playerRefComponentType; + this.query = Query.and(placedByInteractionComponentType, teleporterComponentType, blockStateInfoComponentType); + } + public void onComponentAdded( @Nonnull Ref ref, @Nonnull PlacedByInteractionComponent placedBy, @@ -42,21 +66,21 @@ public class CreateWarpWhenTeleporterPlacedSystem extends RefChangeSystem whoPlacedRef = entityStore.getRefFromUUID(whoPlacedUuid); if (whoPlacedRef != null && whoPlacedRef.isValid()) { - PlayerRef playerRefComponent = entityStore.getStore().getComponent(whoPlacedRef, PlayerRef.getComponentType()); + PlayerRef playerRefComponent = entityStore.getStore().getComponent(whoPlacedRef, this.playerRefComponentType); String language = playerRefComponent == null ? null : playerRefComponent.getLanguage(); if (language != null) { - BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); + BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType); assert blockStateInfoComponent != null; Ref chunkRef = blockStateInfoComponent.getChunkRef(); - if (chunkRef != null && chunkRef.isValid()) { + if (chunkRef.isValid()) { WorldChunk worldChunk = chunkStore.getComponent(chunkRef, WorldChunk.getComponentType()); if (worldChunk != null) { String cannedName = CannedWarpNames.generateCannedWarpName(ref, language); if (cannedName != null) { createWarp(worldChunk, blockStateInfoComponent, cannedName); - Teleporter teleporterComponent = commandBuffer.getComponent(ref, Teleporter.getComponentType()); + Teleporter teleporterComponent = commandBuffer.getComponent(ref, this.teleporterComponentType); assert teleporterComponent != null; @@ -76,21 +100,20 @@ public class CreateWarpWhenTeleporterPlacedSystem extends RefChangeSystem componentType() { - return PlacedByInteractionComponent.getComponentType(); + return this.placedByInteractionComponentType; } - @Nullable + @Nonnull @Override public Query getQuery() { - return Query.and(PlacedByInteractionComponent.getComponentType(), Teleporter.getComponentType(), BlockModule.BlockStateInfo.getComponentType()); + return this.query; } } diff --git a/src/com/hypixel/hytale/builtin/adventure/teleporter/util/CannedWarpNames.java b/src/com/hypixel/hytale/builtin/adventure/teleporter/util/CannedWarpNames.java index cf8257ae..fe86bccd 100644 --- a/src/com/hypixel/hytale/builtin/adventure/teleporter/util/CannedWarpNames.java +++ b/src/com/hypixel/hytale/builtin/adventure/teleporter/util/CannedWarpNames.java @@ -21,23 +21,23 @@ public final class CannedWarpNames { } @Nullable - public static String generateCannedWarpName(Ref blockRef, String language) { + public static String generateCannedWarpName(@Nonnull Ref blockRef, @Nonnull String language) { String translationKey = generateCannedWarpNameKey(blockRef, language); return translationKey == null ? null : I18nModule.get().getMessage(language, translationKey); } @Nullable - public static String generateCannedWarpNameKey(Ref blockRef, String language) { + public static String generateCannedWarpNameKey(@Nonnull Ref blockRef, @Nonnull String language) { Store store = blockRef.getStore(); World world = store.getExternalData().getWorld(); BlockModule.BlockStateInfo blockStateInfo = store.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType()); Random random = blockStateInfo == null ? new Random() : new Random(blockStateInfo.getIndex()); - Teleporter teleporter = store.getComponent(blockRef, Teleporter.getComponentType()); - String wordListKey = teleporter == null ? null : teleporter.getWarpNameWordListKey(); + Teleporter teleporterComponent = store.getComponent(blockRef, Teleporter.getComponentType()); + String wordListKey = teleporterComponent == null ? null : teleporterComponent.getWarpNameWordListKey(); Set existingNames = getWarpNamesInWorld(world); - if (teleporter != null) { - String ownName = teleporter.getOwnedWarp(); - if (ownName != null && !teleporter.isCustomName()) { + if (teleporterComponent != null) { + String ownName = teleporterComponent.getOwnedWarp(); + if (ownName != null && !teleporterComponent.isCustomName()) { existingNames.remove(ownName); } } @@ -46,7 +46,7 @@ public final class CannedWarpNames { } @Nonnull - private static Set getWarpNamesInWorld(World world) { + private static Set getWarpNamesInWorld(@Nonnull World world) { Set existingNames = new HashSet<>(); for (Warp warp : TeleportPlugin.get().getWarps().values()) { diff --git a/src/com/hypixel/hytale/builtin/adventure/worldlocationcondition/NeighbourBlockTagsLocationCondition.java b/src/com/hypixel/hytale/builtin/adventure/worldlocationcondition/NeighbourBlockTagsLocationCondition.java index c8f8dcdf..4384cee7 100644 --- a/src/com/hypixel/hytale/builtin/adventure/worldlocationcondition/NeighbourBlockTagsLocationCondition.java +++ b/src/com/hypixel/hytale/builtin/adventure/worldlocationcondition/NeighbourBlockTagsLocationCondition.java @@ -21,6 +21,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class NeighbourBlockTagsLocationCondition extends WorldLocationCondition { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( NeighbourBlockTagsLocationCondition.class, NeighbourBlockTagsLocationCondition::new, WorldLocationCondition.BASE_CODEC ) @@ -53,11 +54,12 @@ public class NeighbourBlockTagsLocationCondition extends WorldLocationCondition protected IntRange support = new IntRange(1, 4); @Override - public boolean test(World world, int worldX, int worldY, int worldZ) { + public boolean test(@Nonnull World world, int worldX, int worldY, int worldZ) { if (worldY <= 0) { return false; } else { - WorldChunk worldChunk = world.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(worldX, worldZ)); + long chunkIndex = ChunkUtil.indexChunkFromBlock(worldX, worldZ); + WorldChunk worldChunk = world.getNonTickingChunk(chunkIndex); if (worldChunk == null) { return false; } else if (this.neighbourDirection == NeighbourBlockTagsLocationCondition.NeighbourDirection.SIDEWAYS) { @@ -95,15 +97,24 @@ public class NeighbourBlockTagsLocationCondition extends WorldLocationCondition } } - private boolean checkBlockHasTag(int x, int y, int z, @Nonnull BlockAccessor worldChunk) { - int blockIndex = worldChunk.getBlock(x, y, z); - TagPattern tagPattern = TagPattern.getAssetMap().getAsset(this.tagPatternId); - if (tagPattern != null) { - AssetExtraInfo.Data data = BlockType.getAssetMap().getAsset(blockIndex).getData(); - return data == null ? false : tagPattern.test(data.getTags()); - } else { - HytaleLogger.getLogger().at(Level.WARNING).log("No TagPattern asset found for id: " + this.tagPatternId); + private boolean checkBlockHasTag(int x, int y, int z, @Nullable BlockAccessor worldChunk) { + if (worldChunk == null) { return false; + } else { + int blockIndex = worldChunk.getBlock(x, y, z); + TagPattern tagPattern = TagPattern.getAssetMap().getAsset(this.tagPatternId); + if (tagPattern != null) { + BlockType blockType = BlockType.getAssetMap().getAsset(blockIndex); + if (blockType == null) { + return false; + } else { + AssetExtraInfo.Data data = blockType.getData(); + return data == null ? false : tagPattern.test(data.getTags()); + } + } else { + HytaleLogger.getLogger().at(Level.WARNING).log("No TagPattern asset found for id: " + this.tagPatternId); + return false; + } } } @@ -145,7 +156,7 @@ public class NeighbourBlockTagsLocationCondition extends WorldLocationCondition + super.toString(); } - private static enum NeighbourDirection { + protected static enum NeighbourDirection { ABOVE, BELOW, SIDEWAYS; diff --git a/src/com/hypixel/hytale/builtin/ambience/AmbiencePlugin.java b/src/com/hypixel/hytale/builtin/ambience/AmbiencePlugin.java index a238da24..d106696b 100644 --- a/src/com/hypixel/hytale/builtin/ambience/AmbiencePlugin.java +++ b/src/com/hypixel/hytale/builtin/ambience/AmbiencePlugin.java @@ -10,23 +10,33 @@ import com.hypixel.hytale.builtin.ambience.systems.ForcedMusicSystems; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.server.core.asset.type.model.config.Model; import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.modules.entity.component.AudioComponent; +import com.hypixel.hytale.server.core.modules.entity.component.Intangible; +import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; +import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import com.hypixel.hytale.server.core.prefab.PrefabCopyableComponent; +import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.util.Config; import java.util.logging.Level; import javax.annotation.Nonnull; public class AmbiencePlugin extends JavaPlugin { + @Nonnull private static final String DEFAULT_AMBIENT_EMITTER_MODEL = "NPC_Spawn_Marker"; private static AmbiencePlugin instance; private ComponentType ambienceTrackerComponentType; private ComponentType ambientEmitterComponentType; private ResourceType ambienceResourceType; + @Nonnull private final Config config = this.withConfig("AmbiencePlugin", AmbiencePlugin.AmbiencePluginConfig.CODEC); private Model ambientEmitterModel; @@ -41,15 +51,32 @@ public class AmbiencePlugin extends JavaPlugin { @Override protected void setup() { - this.ambienceTrackerComponentType = this.getEntityStoreRegistry().registerComponent(AmbienceTracker.class, AmbienceTracker::new); - this.ambientEmitterComponentType = this.getEntityStoreRegistry() - .registerComponent(AmbientEmitterComponent.class, "AmbientEmitter", AmbientEmitterComponent.CODEC); - this.ambienceResourceType = this.getEntityStoreRegistry().registerResource(AmbienceResource.class, AmbienceResource::new); - this.getEntityStoreRegistry().registerSystem(new AmbientEmitterSystems.EntityAdded()); - this.getEntityStoreRegistry().registerSystem(new AmbientEmitterSystems.EntityRefAdded()); - this.getEntityStoreRegistry().registerSystem(new AmbientEmitterSystems.Ticking()); - this.getEntityStoreRegistry().registerSystem(new ForcedMusicSystems.Tick()); - this.getEntityStoreRegistry().registerSystem(new ForcedMusicSystems.PlayerAdded()); + ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); + this.ambienceTrackerComponentType = entityStoreRegistry.registerComponent(AmbienceTracker.class, AmbienceTracker::new); + this.ambientEmitterComponentType = entityStoreRegistry.registerComponent(AmbientEmitterComponent.class, "AmbientEmitter", AmbientEmitterComponent.CODEC); + this.ambienceResourceType = entityStoreRegistry.registerResource(AmbienceResource.class, AmbienceResource::new); + ComponentType transformComponentType = TransformComponent.getComponentType(); + ComponentType networkIdComponentType = NetworkId.getComponentType(); + ComponentType intangibleComponentType = Intangible.getComponentType(); + ComponentType prefabCopyableComponentType = PrefabCopyableComponent.getComponentType(); + ComponentType audioComponentType = AudioComponent.getComponentType(); + ComponentType playerComponentType = Player.getComponentType(); + ComponentType playerRefComponentType = PlayerRef.getComponentType(); + entityStoreRegistry.registerSystem( + new AmbientEmitterSystems.EntityAdded( + this.ambientEmitterComponentType, transformComponentType, networkIdComponentType, intangibleComponentType, prefabCopyableComponentType + ) + ); + entityStoreRegistry.registerSystem( + new AmbientEmitterSystems.EntityRefAdded( + this.ambientEmitterComponentType, transformComponentType, audioComponentType, networkIdComponentType, intangibleComponentType + ) + ); + entityStoreRegistry.registerSystem(new AmbientEmitterSystems.Ticking(this.ambientEmitterComponentType, transformComponentType)); + entityStoreRegistry.registerSystem( + new ForcedMusicSystems.Tick(playerComponentType, playerRefComponentType, this.ambienceTrackerComponentType, this.ambienceResourceType) + ); + entityStoreRegistry.registerSystem(new ForcedMusicSystems.PlayerAdded(playerRefComponentType, this.ambienceTrackerComponentType)); this.getCommandRegistry().registerCommand(new AmbienceCommands()); } @@ -87,6 +114,7 @@ public class AmbiencePlugin extends JavaPlugin { } public static class AmbiencePluginConfig { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AmbiencePlugin.AmbiencePluginConfig.class, AmbiencePlugin.AmbiencePluginConfig::new ) diff --git a/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceClearCommand.java b/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceClearCommand.java index 0b14ab52..e7d4d45e 100644 --- a/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceClearCommand.java +++ b/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceClearCommand.java @@ -10,14 +10,17 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; public class AmbienceClearCommand extends AbstractWorldCommand { + @Nonnull + private static final Message MESSAGE_SERVER_COMMANDS_AMBIENCE_CLEAR_SUCCESS = Message.translation("server.commands.ambience.clear.success"); + public AmbienceClearCommand() { super("clear", "server.commands.ambience.clear.desc"); } @Override protected void execute(@Nonnull CommandContext context, @Nonnull World world, @Nonnull Store store) { - AmbienceResource resource = store.getResource(AmbienceResource.getResourceType()); - resource.setForcedMusicAmbience(null); - context.sendMessage(Message.translation("server.commands.ambience.clear.success")); + AmbienceResource ambienceResource = store.getResource(AmbienceResource.getResourceType()); + ambienceResource.setForcedMusicAmbience(null); + context.sendMessage(MESSAGE_SERVER_COMMANDS_AMBIENCE_CLEAR_SUCCESS); } } diff --git a/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceEmitterAddCommand.java b/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceEmitterAddCommand.java index cbc855a8..ab701891 100644 --- a/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceEmitterAddCommand.java +++ b/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceEmitterAddCommand.java @@ -32,6 +32,8 @@ public class AmbienceEmitterAddCommand extends AbstractPlayerCommand { "server.commands.ambience.emitter.add.arg.soundEvent.name", SoundEvent.class, "server.commands.ambience.emitter.add.arg.soundEvent.usage" ); @Nonnull + private static final Message MESSAGE_SERVER_COMMANDS_ERRORS_PLAYER_ONLY = Message.translation("server.commands.errors.playerOnly"); + @Nonnull private final RequiredArg soundEventArg = this.withRequiredArg( "soundEvent", "server.commands.ambience.emitter.add.arg.soundEvent.desc", SOUND_EVENT_ASSET_TYPE ); @@ -45,42 +47,41 @@ public class AmbienceEmitterAddCommand extends AbstractPlayerCommand { @Nonnull CommandContext context, @Nonnull Store store, @Nonnull Ref ref, @Nonnull PlayerRef playerRef, @Nonnull World world ) { if (!context.isPlayer()) { - throw new GeneralCommandException(Message.translation("server.commands.errors.playerOnly")); + throw new GeneralCommandException(MESSAGE_SERVER_COMMANDS_ERRORS_PLAYER_ONLY); } else { TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); + if (transformComponent != null) { + Holder holder = EntityStore.REGISTRY.newHolder(); + SoundEvent soundEvent = this.soundEventArg.get(context); + boolean looping = false; - assert transformComponent != null; - - Holder holder = EntityStore.REGISTRY.newHolder(); - SoundEvent soundEvent = this.soundEventArg.get(context); - boolean looping = false; - - for (SoundEventLayer layer : soundEvent.getLayers()) { - if (layer.isLooping()) { - looping = true; - break; + for (SoundEventLayer layer : soundEvent.getLayers()) { + if (layer.isLooping()) { + looping = true; + break; + } } - } - if (!looping) { - context.sendMessage(Message.translation("server.commands.ambience.emitter.add.notLooping").param("soundEventId", soundEvent.getId())); - } else { - AmbientEmitterComponent emitterComponent = new AmbientEmitterComponent(); - emitterComponent.setSoundEventId(soundEvent.getId()); - holder.addComponent(AmbientEmitterComponent.getComponentType(), emitterComponent); - TransformComponent emitterTransform = transformComponent.clone(); - holder.addComponent(TransformComponent.getComponentType(), emitterTransform); - holder.addComponent(Nameplate.getComponentType(), new Nameplate(soundEvent.getId())); - holder.ensureComponent(UUIDComponent.getComponentType()); - holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType()); - Model model = AmbiencePlugin.get().getAmbientEmitterModel(); - holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model)); - holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference())); - Ref emitterRef = store.addEntity(holder, AddReason.SPAWN); - if (emitterRef != null && emitterRef.isValid()) { - context.sendMessage(Message.translation("server.commands.ambience.emitter.add.added").param("soundEventId", soundEvent.getId())); + if (!looping) { + context.sendMessage(Message.translation("server.commands.ambience.emitter.add.notLooping").param("soundEventId", soundEvent.getId())); } else { - context.sendMessage(Message.translation("server.commands.ambience.emitter.add.failed").param("soundEventId", soundEvent.getId())); + AmbientEmitterComponent emitterComponent = new AmbientEmitterComponent(); + emitterComponent.setSoundEventId(soundEvent.getId()); + holder.addComponent(AmbientEmitterComponent.getComponentType(), emitterComponent); + TransformComponent emitterTransform = transformComponent.clone(); + holder.addComponent(TransformComponent.getComponentType(), emitterTransform); + holder.addComponent(Nameplate.getComponentType(), new Nameplate(soundEvent.getId())); + holder.ensureComponent(UUIDComponent.getComponentType()); + holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType()); + Model model = AmbiencePlugin.get().getAmbientEmitterModel(); + holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model)); + holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference())); + Ref emitterRef = store.addEntity(holder, AddReason.SPAWN); + if (emitterRef != null && emitterRef.isValid()) { + context.sendMessage(Message.translation("server.commands.ambience.emitter.add.added").param("soundEventId", soundEvent.getId())); + } else { + context.sendMessage(Message.translation("server.commands.ambience.emitter.add.failed").param("soundEventId", soundEvent.getId())); + } } } } diff --git a/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceSetMusicCommand.java b/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceSetMusicCommand.java index fc80935f..b9662e2c 100644 --- a/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceSetMusicCommand.java +++ b/src/com/hypixel/hytale/builtin/ambience/commands/AmbienceSetMusicCommand.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; public class AmbienceSetMusicCommand extends AbstractWorldCommand { + @Nonnull private final RequiredArg ambienceFxIdArg = this.withRequiredArg( "ambienceFxId", "server.commands.ambience.setmusic.arg.ambiencefxid.desc", ArgTypes.AMBIENCE_FX_ASSET ); @@ -24,8 +25,8 @@ public class AmbienceSetMusicCommand extends AbstractWorldCommand { @Override protected void execute(@Nonnull CommandContext context, @Nonnull World world, @Nonnull Store store) { AmbienceFX ambienceFX = this.ambienceFxIdArg.get(context); - AmbienceResource resource = store.getResource(AmbienceResource.getResourceType()); - resource.setForcedMusicAmbience(ambienceFX.getId()); + AmbienceResource ambienceResource = store.getResource(AmbienceResource.getResourceType()); + ambienceResource.setForcedMusicAmbience(ambienceFX.getId()); context.sendMessage(Message.translation("server.commands.ambience.setmusic.success").param("ambience", ambienceFX.getId())); } } diff --git a/src/com/hypixel/hytale/builtin/ambience/components/AmbienceTracker.java b/src/com/hypixel/hytale/builtin/ambience/components/AmbienceTracker.java index 748319ac..3fc2461e 100644 --- a/src/com/hypixel/hytale/builtin/ambience/components/AmbienceTracker.java +++ b/src/com/hypixel/hytale/builtin/ambience/components/AmbienceTracker.java @@ -5,9 +5,11 @@ import com.hypixel.hytale.component.Component; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.protocol.packets.world.UpdateEnvironmentMusic; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import javax.annotation.Nonnull; import javax.annotation.Nullable; public class AmbienceTracker implements Component { + @Nonnull private final UpdateEnvironmentMusic musicPacket = new UpdateEnvironmentMusic(0); private int forcedMusicIndex; @@ -23,6 +25,7 @@ public class AmbienceTracker implements Component { return this.forcedMusicIndex; } + @Nonnull public UpdateEnvironmentMusic getMusicPacket() { return this.musicPacket; } diff --git a/src/com/hypixel/hytale/builtin/ambience/components/AmbientEmitterComponent.java b/src/com/hypixel/hytale/builtin/ambience/components/AmbientEmitterComponent.java index 0a0a3ae8..21700a1b 100644 --- a/src/com/hypixel/hytale/builtin/ambience/components/AmbientEmitterComponent.java +++ b/src/com/hypixel/hytale/builtin/ambience/components/AmbientEmitterComponent.java @@ -8,9 +8,11 @@ import com.hypixel.hytale.component.Component; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import javax.annotation.Nonnull; import javax.annotation.Nullable; public class AmbientEmitterComponent implements Component { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(AmbientEmitterComponent.class, AmbientEmitterComponent::new) .append(new KeyedCodec<>("SoundEventId", Codec.STRING), (emitter, s) -> emitter.soundEventId = s, emitter -> emitter.soundEventId) .add() diff --git a/src/com/hypixel/hytale/builtin/ambience/systems/AmbientEmitterSystems.java b/src/com/hypixel/hytale/builtin/ambience/systems/AmbientEmitterSystems.java index 401f7f5d..1aff5cb3 100644 --- a/src/com/hypixel/hytale/builtin/ambience/systems/AmbientEmitterSystems.java +++ b/src/com/hypixel/hytale/builtin/ambience/systems/AmbientEmitterSystems.java @@ -29,18 +29,37 @@ import javax.annotation.Nonnull; public class AmbientEmitterSystems { public static class EntityAdded extends HolderSystem { @Nonnull - private final Query query = Query.and(AmbientEmitterComponent.getComponentType(), TransformComponent.getComponentType()); + private final ComponentType networkIdComponentType; + @Nonnull + private final ComponentType intangibleComponentType; + @Nonnull + private final ComponentType prefabCopyableComponentType; + @Nonnull + private final Query query; + + public EntityAdded( + @Nonnull ComponentType ambientEmitterComponentType, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType networkIdComponentType, + @Nonnull ComponentType intangibleComponentType, + @Nonnull ComponentType prefabCopyableComponentType + ) { + this.networkIdComponentType = networkIdComponentType; + this.intangibleComponentType = intangibleComponentType; + this.prefabCopyableComponentType = prefabCopyableComponentType; + this.query = Query.and(ambientEmitterComponentType, transformComponentType); + } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { Archetype archetype = holder.getArchetype(); - ComponentType networkIdComponentType = NetworkId.getComponentType(); - if (!archetype.contains(networkIdComponentType)) { - holder.addComponent(networkIdComponentType, new NetworkId(store.getExternalData().takeNextNetworkId())); + if (!archetype.contains(this.networkIdComponentType)) { + int nextNetworkId = store.getExternalData().takeNextNetworkId(); + holder.addComponent(this.networkIdComponentType, new NetworkId(nextNetworkId)); } - holder.ensureComponent(Intangible.getComponentType()); - holder.ensureComponent(PrefabCopyableComponent.getComponentType()); + holder.ensureComponent(this.intangibleComponentType); + holder.ensureComponent(this.prefabCopyableComponentType); } @Override @@ -56,29 +75,56 @@ public class AmbientEmitterSystems { public static class EntityRefAdded extends RefSystem { @Nonnull - private final Query query = Query.and(AmbientEmitterComponent.getComponentType(), TransformComponent.getComponentType()); + private final ComponentType ambientEmitterComponentType; + @Nonnull + private final ComponentType transformComponentType; + @Nonnull + private final ComponentType audioComponentType; + @Nonnull + private final ComponentType networkIdComponentType; + @Nonnull + private final ComponentType intangibleComponentType; + @Nonnull + private final Query query; + + public EntityRefAdded( + @Nonnull ComponentType ambientEmitterComponentType, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType audioComponentType, + @Nonnull ComponentType networkIdComponentType, + @Nonnull ComponentType intangibleComponentType + ) { + this.ambientEmitterComponentType = ambientEmitterComponentType; + this.transformComponentType = transformComponentType; + this.audioComponentType = audioComponentType; + this.networkIdComponentType = networkIdComponentType; + this.intangibleComponentType = intangibleComponentType; + this.query = Query.and(ambientEmitterComponentType, transformComponentType); + } @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - AmbientEmitterComponent emitterComponent = store.getComponent(ref, AmbientEmitterComponent.getComponentType()); + AmbientEmitterComponent emitterComponent = store.getComponent(ref, this.ambientEmitterComponentType); assert emitterComponent != null; - TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); + TransformComponent transformComponent = store.getComponent(ref, this.transformComponentType); assert transformComponent != null; Holder emitterHolder = EntityStore.REGISTRY.newHolder(); - emitterHolder.addComponent(TransformComponent.getComponentType(), transformComponent.clone()); + emitterHolder.addComponent(this.transformComponentType, transformComponent.clone()); AudioComponent audioComponent = new AudioComponent(); audioComponent.addSound(SoundEvent.getAssetMap().getIndex(emitterComponent.getSoundEventId())); - emitterHolder.addComponent(AudioComponent.getComponentType(), audioComponent); - emitterHolder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId())); - emitterHolder.ensureComponent(Intangible.getComponentType()); + emitterHolder.addComponent(this.audioComponentType, audioComponent); + int nextNetworkId = store.getExternalData().takeNextNetworkId(); + emitterHolder.addComponent(this.networkIdComponentType, new NetworkId(nextNetworkId)); + emitterHolder.ensureComponent(this.intangibleComponentType); emitterHolder.addComponent(EntityStore.REGISTRY.getNonSerializedComponentType(), NonSerialized.get()); - emitterComponent.setSpawnedEmitter(commandBuffer.addEntity(emitterHolder, AddReason.SPAWN)); + Ref emitterRef = commandBuffer.addEntity(emitterHolder, AddReason.SPAWN); + emitterComponent.setSpawnedEmitter(emitterRef); } @Override @@ -86,7 +132,7 @@ public class AmbientEmitterSystems { @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { if (reason == RemoveReason.REMOVE) { - AmbientEmitterComponent emitterComponent = store.getComponent(ref, AmbientEmitterComponent.getComponentType()); + AmbientEmitterComponent emitterComponent = store.getComponent(ref, this.ambientEmitterComponentType); assert emitterComponent != null; @@ -106,7 +152,20 @@ public class AmbientEmitterSystems { public static class Ticking extends EntityTickingSystem { @Nonnull - private final Query query = Query.and(AmbientEmitterComponent.getComponentType(), TransformComponent.getComponentType()); + private final ComponentType ambientEmitterComponentType; + @Nonnull + private final ComponentType transformComponentType; + @Nonnull + private final Query query; + + public Ticking( + @Nonnull ComponentType ambientEmitterComponentType, + @Nonnull ComponentType transformComponentType + ) { + this.ambientEmitterComponentType = ambientEmitterComponentType; + this.transformComponentType = transformComponentType; + this.query = Query.and(ambientEmitterComponentType, transformComponentType); + } @Override public void tick( @@ -116,17 +175,17 @@ public class AmbientEmitterSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - AmbientEmitterComponent emitterComponent = archetypeChunk.getComponent(index, AmbientEmitterComponent.getComponentType()); + AmbientEmitterComponent emitterComponent = archetypeChunk.getComponent(index, this.ambientEmitterComponentType); assert emitterComponent != null; - TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType); assert transformComponent != null; Ref spawnedEmitterRef = emitterComponent.getSpawnedEmitter(); if (spawnedEmitterRef != null && spawnedEmitterRef.isValid()) { - TransformComponent ownedEmitterTransform = commandBuffer.getComponent(spawnedEmitterRef, TransformComponent.getComponentType()); + TransformComponent ownedEmitterTransform = commandBuffer.getComponent(spawnedEmitterRef, this.transformComponentType); if (ownedEmitterTransform != null) { if (transformComponent.getPosition().distanceSquaredTo(ownedEmitterTransform.getPosition()) > 1.0) { ownedEmitterTransform.setPosition(transformComponent.getPosition()); diff --git a/src/com/hypixel/hytale/builtin/ambience/systems/ForcedMusicSystems.java b/src/com/hypixel/hytale/builtin/ambience/systems/ForcedMusicSystems.java index 3e9d3f16..f0a9ad42 100644 --- a/src/com/hypixel/hytale/builtin/ambience/systems/ForcedMusicSystems.java +++ b/src/com/hypixel/hytale/builtin/ambience/systems/ForcedMusicSystems.java @@ -6,8 +6,10 @@ import com.hypixel.hytale.component.AddReason; import com.hypixel.hytale.component.Archetype; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.RemoveReason; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.HolderSystem; @@ -17,26 +19,37 @@ import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class ForcedMusicSystems { - private static final Query TICK_QUERY = Archetype.of( - Player.getComponentType(), PlayerRef.getComponentType(), AmbienceTracker.getComponentType() - ); - public static class PlayerAdded extends HolderSystem { + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final ComponentType ambienceTrackerComponentType; + @Nonnull + private final Query query; + + public PlayerAdded( + @Nonnull ComponentType playerRefComponentType, + @Nonnull ComponentType ambienceTrackerComponentType + ) { + this.playerRefComponentType = playerRefComponentType; + this.ambienceTrackerComponentType = ambienceTrackerComponentType; + this.query = Query.and(playerRefComponentType, ambienceTrackerComponentType); + } + @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - holder.ensureComponent(AmbienceTracker.getComponentType()); + holder.ensureComponent(this.ambienceTrackerComponentType); } @Override public void onEntityRemoved(@Nonnull Holder holder, @Nonnull RemoveReason reason, @Nonnull Store store) { - AmbienceTracker ambienceTrackerComponent = holder.getComponent(AmbienceTracker.getComponentType()); + AmbienceTracker ambienceTrackerComponent = holder.getComponent(this.ambienceTrackerComponentType); assert ambienceTrackerComponent != null; - PlayerRef playerRefComponent = holder.getComponent(PlayerRef.getComponentType()); + PlayerRef playerRefComponent = holder.getComponent(this.playerRefComponentType); assert playerRefComponent != null; @@ -45,14 +58,35 @@ public class ForcedMusicSystems { playerRefComponent.getPacketHandler().write(pooledPacket); } - @Nullable + @Nonnull @Override public Query getQuery() { - return Query.and(PlayerRef.getComponentType(), AmbienceTracker.getComponentType()); + return this.query; } } public static class Tick extends EntityTickingSystem { + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final ComponentType ambienceTrackerComponentType; + @Nonnull + private final ResourceType ambienceResourceType; + @Nonnull + private final Query query; + + public Tick( + @Nonnull ComponentType playerComponentType, + @Nonnull ComponentType playerRefComponentType, + @Nonnull ComponentType ambienceTrackerComponentType, + @Nonnull ResourceType ambienceResourceType + ) { + this.playerRefComponentType = playerRefComponentType; + this.ambienceTrackerComponentType = ambienceTrackerComponentType; + this.ambienceResourceType = ambienceResourceType; + this.query = Archetype.of(playerComponentType, playerRefComponentType, ambienceTrackerComponentType); + } + @Override public void tick( float dt, @@ -61,23 +95,29 @@ public class ForcedMusicSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - AmbienceResource ambienceResource = store.getResource(AmbienceResource.getResourceType()); - AmbienceTracker tracker = archetypeChunk.getComponent(index, AmbienceTracker.getComponentType()); - PlayerRef playerRef = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); - int have = tracker.getForcedMusicIndex(); + AmbienceResource ambienceResource = store.getResource(this.ambienceResourceType); + AmbienceTracker ambienceTrackerComponent = archetypeChunk.getComponent(index, this.ambienceTrackerComponentType); + + assert ambienceTrackerComponent != null; + + PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType); + + assert playerRefComponent != null; + + int have = ambienceTrackerComponent.getForcedMusicIndex(); int desired = ambienceResource.getForcedMusicIndex(); if (have != desired) { - tracker.setForcedMusicIndex(desired); - UpdateEnvironmentMusic pooledPacket = tracker.getMusicPacket(); + ambienceTrackerComponent.setForcedMusicIndex(desired); + UpdateEnvironmentMusic pooledPacket = ambienceTrackerComponent.getMusicPacket(); pooledPacket.environmentIndex = desired; - playerRef.getPacketHandler().write(pooledPacket); + playerRefComponent.getPacketHandler().write(pooledPacket); } } - @Nullable + @Nonnull @Override public Query getQuery() { - return ForcedMusicSystems.TICK_QUERY; + return this.query; } } } diff --git a/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorGamePacketHandler.java b/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorGamePacketHandler.java index a09509d5..a8536fa0 100644 --- a/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorGamePacketHandler.java +++ b/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorGamePacketHandler.java @@ -65,22 +65,28 @@ public class AssetEditorGamePacketHandler implements SubPacketHandler { if (ref != null && ref.isValid()) { Store store = ref.getStore(); World world = store.getExternalData().getWorld(); - CompletableFuture.runAsync(() -> { + world.execute( + () -> { Player playerComponent = store.getComponent(ref, Player.getComponentType()); if (!this.lacksPermission(playerComponent, true)) { - ; + CompletableFuture.runAsync( + () -> { + LOGGER.at(Level.INFO).log("%s updating json asset at %s", this.packetHandler.getPlayerRef().getUsername(), packet.path); + EditorClient mockClient = new EditorClient(playerRef); + AssetEditorPlugin.get() + .handleJsonAssetUpdate( + mockClient, + packet.path != null ? new AssetPath(packet.path) : null, + packet.assetType, + packet.assetIndex, + packet.commands, + packet.token + ); + } + ); } - }, world) - .thenRunAsync( - () -> { - LOGGER.at(Level.INFO).log("%s updating json asset at %s", this.packetHandler.getPlayerRef().getUsername(), packet.path); - EditorClient mockClient = new EditorClient(playerRef); - AssetEditorPlugin.get() - .handleJsonAssetUpdate( - mockClient, packet.path != null ? new AssetPath(packet.path) : null, packet.assetType, packet.assetIndex, packet.commands, packet.token - ); - } - ); + } + ); } else { throw new RuntimeException("Unable to process AssetEditorUpdateJsonAsset packet. Player ref is invalid!"); } @@ -89,7 +95,7 @@ public class AssetEditorGamePacketHandler implements SubPacketHandler { private boolean lacksPermission(@Nonnull Player player, boolean shouldShowDenialMessage) { if (!player.hasPermission("hytale.editor.asset")) { if (shouldShowDenialMessage) { - player.sendMessage(Messages.USAGE_DENIED_MESSAGE); + player.sendMessage(Messages.USAGE_DENIED); } return true; diff --git a/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPacketHandler.java b/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPacketHandler.java index d692ed34..977f77a6 100644 --- a/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPacketHandler.java +++ b/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPacketHandler.java @@ -409,7 +409,7 @@ public class AssetEditorPacketHandler extends GenericPacketHandler { private boolean lacksPermission(int token) { if (!this.editorClient.hasPermission("hytale.editor.asset")) { - this.editorClient.sendFailureReply(token, Messages.USAGE_DENIED_MESSAGE); + this.editorClient.sendFailureReply(token, Messages.USAGE_DENIED); return true; } else { return false; @@ -422,7 +422,7 @@ public class AssetEditorPacketHandler extends GenericPacketHandler { private boolean lacksPermission(String permissionId) { if (!this.editorClient.hasPermission(permissionId)) { - this.editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.USAGE_DENIED_MESSAGE); + this.editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.USAGE_DENIED); return true; } else { return false; @@ -431,7 +431,7 @@ public class AssetEditorPacketHandler extends GenericPacketHandler { private boolean lacksPermission(int token, String permissionId) { if (!this.editorClient.hasPermission(permissionId)) { - this.editorClient.sendFailureReply(token, Messages.USAGE_DENIED_MESSAGE); + this.editorClient.sendFailureReply(token, Messages.USAGE_DENIED); return true; } else { return false; diff --git a/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPlugin.java b/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPlugin.java index 0dfadceb..5970710e 100644 --- a/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPlugin.java +++ b/src/com/hypixel/hytale/builtin/asseteditor/AssetEditorPlugin.java @@ -36,6 +36,7 @@ import com.hypixel.hytale.common.util.FormatUtil; import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.event.EventRegistry; import com.hypixel.hytale.event.IEventDispatcher; import com.hypixel.hytale.protocol.Packet; import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorAsset; @@ -69,6 +70,7 @@ import com.hypixel.hytale.protocol.packets.asseteditor.SchemaFile; import com.hypixel.hytale.protocol.packets.asseteditor.TimestampedAssetReference; import com.hypixel.hytale.protocol.packets.assets.UpdateTranslations; import com.hypixel.hytale.server.core.HytaleServer; +import com.hypixel.hytale.server.core.HytaleServerConfig; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.Options; import com.hypixel.hytale.server.core.asset.AssetModule; @@ -96,7 +98,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -118,22 +119,32 @@ import org.bson.BsonValue; public class AssetEditorPlugin extends JavaPlugin { private static AssetEditorPlugin instance; + @Nonnull private final StampedLock globalEditLock = new StampedLock(); + @Nonnull private final Map> uuidToEditorClients = new ConcurrentHashMap<>(); + @Nonnull private final Map clientOpenAssetPathMapping = new ConcurrentHashMap<>(); + @Nonnull private final Set clientsSubscribedToModifiedAssetsChanges = ConcurrentHashMap.newKeySet(); @Nonnull private Map schemas = new Object2ObjectOpenHashMap<>(); private AssetEditorSetupSchemas setupSchemasPacket; + @Nonnull private final StampedLock initLock = new StampedLock(); + @Nonnull private final Set initQueue = new HashSet<>(); @Nonnull private AssetEditorPlugin.InitState initState = AssetEditorPlugin.InitState.NOT_INITIALIZED; @Nullable private ScheduledFuture scheduledReinitFuture; + @Nonnull private final Map assetPackDataSources = new ConcurrentHashMap<>(); + @Nonnull private final AssetTypeRegistry assetTypeRegistry = new AssetTypeRegistry(); + @Nonnull private final UndoRedoManager undoRedoManager = new UndoRedoManager(); + @Nullable private ScheduledFuture pingClientsTask; public static AssetEditorPlugin get() { @@ -145,7 +156,7 @@ public class AssetEditorPlugin extends JavaPlugin { } @Nullable - DataSource registerDataSourceForPack(AssetPack assetPack) { + DataSource registerDataSourceForPack(@Nonnull AssetPack assetPack) { PluginManifest manifest = assetPack.getManifest(); if (manifest == null) { this.getLogger().at(Level.SEVERE).log("Could not load asset pack manifest for " + assetPack.getName()); @@ -160,6 +171,7 @@ public class AssetEditorPlugin extends JavaPlugin { @Override protected void setup() { instance = this; + EventRegistry eventRegistry = this.getEventRegistry(); for (AssetPack assetPack : AssetModule.get().getAssetPacks()) { this.registerDataSourceForPack(assetPack); @@ -180,13 +192,13 @@ public class AssetEditorPlugin extends JavaPlugin { this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Sound", null, ".ogg", AssetEditorEditorType.None)); this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("UI", null, ".ui", AssetEditorEditorType.Text)); this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Language", null, ".lang", AssetEditorEditorType.Text)); - this.getEventRegistry().register(RegisterAssetStoreEvent.class, this::onRegisterAssetStore); - this.getEventRegistry().register(RemoveAssetStoreEvent.class, this::onUnregisterAssetStore); - this.getEventRegistry().register(AssetPackRegisterEvent.class, this::onRegisterAssetPack); - this.getEventRegistry().register(AssetPackUnregisterEvent.class, this::onUnregisterAssetPack); - this.getEventRegistry().register(AssetStoreMonitorEvent.class, this::onAssetMonitor); - this.getEventRegistry().register(CommonAssetMonitorEvent.class, this::onAssetMonitor); - this.getEventRegistry().register(MessagesUpdated.class, this::onI18nMessagesUpdated); + eventRegistry.register(RegisterAssetStoreEvent.class, this::onRegisterAssetStore); + eventRegistry.register(RemoveAssetStoreEvent.class, this::onUnregisterAssetStore); + eventRegistry.register(AssetPackRegisterEvent.class, this::onRegisterAssetPack); + eventRegistry.register(AssetPackUnregisterEvent.class, this::onUnregisterAssetPack); + eventRegistry.register(AssetStoreMonitorEvent.class, this::onAssetMonitor); + eventRegistry.register(CommonAssetMonitorEvent.class, this::onAssetMonitor); + eventRegistry.register(MessagesUpdated.class, this::onI18nMessagesUpdated); AssetSpecificFunctionality.setup(); } @@ -210,38 +222,49 @@ public class AssetEditorPlugin extends JavaPlugin { } } - this.pingClientsTask.cancel(false); + if (this.pingClientsTask != null) { + this.pingClientsTask.cancel(false); + } else { + this.getLogger().at(Level.WARNING).log("Failed to cancel ping clients task as it was null"); + } for (DataSource dataSource : this.assetPackDataSources.values()) { dataSource.shutdown(); } } - public DataSource getDataSourceForPath(AssetPath path) { + @Nullable + public DataSource getDataSourceForPath(@Nonnull AssetPath path) { return this.getDataSourceForPack(path.packId()); } - public DataSource getDataSourceForPack(String assetPack) { + @Nullable + public DataSource getDataSourceForPack(@Nonnull String assetPack) { return this.assetPackDataSources.get(assetPack); } + @Nonnull public Collection getDataSources() { return this.assetPackDataSources.values(); } + @Nonnull public AssetTypeRegistry getAssetTypeRegistry() { return this.assetTypeRegistry; } - public Schema getSchema(String id) { + @Nullable + public Schema getSchema(@Nonnull String id) { return this.schemas.get(id); } + @Nonnull public Map getClientOpenAssetPathMapping() { return this.clientOpenAssetPathMapping; } - public Set getEditorClients(UUID uuid) { + @Nullable + public Set getEditorClients(@Nonnull UUID uuid) { return this.uuidToEditorClients.get(uuid); } @@ -259,7 +282,7 @@ public class AssetEditorPlugin extends JavaPlugin { } @Nonnull - private List getClientsWithOpenAssetPath(AssetPath path) { + private List getClientsWithOpenAssetPath(@Nonnull AssetPath path) { if (this.clientOpenAssetPathMapping.isEmpty()) { return Collections.emptyList(); } else { @@ -275,11 +298,12 @@ public class AssetEditorPlugin extends JavaPlugin { } } - public AssetPath getOpenAssetPath(EditorClient editorClient) { + @Nullable + public AssetPath getOpenAssetPath(@Nonnull EditorClient editorClient) { return this.clientOpenAssetPathMapping.get(editorClient); } - private void onRegisterAssetPack(AssetPackRegisterEvent event) { + private void onRegisterAssetPack(@Nonnull AssetPackRegisterEvent event) { if (!this.assetPackDataSources.containsKey(event.getAssetPack().getName())) { DataSource dataSource = this.registerDataSourceForPack(event.getAssetPack()); if (dataSource != null) { @@ -307,7 +331,7 @@ public class AssetEditorPlugin extends JavaPlugin { } } - private void onUnregisterAssetPack(AssetPackUnregisterEvent event) { + private void onUnregisterAssetPack(@Nonnull AssetPackUnregisterEvent event) { if (this.assetPackDataSources.containsKey(event.getAssetPack().getName())) { DataSource dataSource = this.assetPackDataSources.remove(event.getAssetPack().getName()); dataSource.shutdown(); @@ -633,7 +657,7 @@ public class AssetEditorPlugin extends JavaPlugin { this.getLogger().at(Level.INFO).log("Done Initializing %s", editorClient.getUsername()); } - public void handleEditorClientDisconnected(@Nonnull EditorClient editorClient, PacketHandler.DisconnectReason disconnectReason) { + public void handleEditorClientDisconnected(@Nonnull EditorClient editorClient, @Nonnull PacketHandler.DisconnectReason disconnectReason) { IEventDispatcher dispatch = HytaleServer.get() .getEventBus() .dispatchFor(AssetEditorClientDisconnectEvent.class); @@ -655,11 +679,11 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleDeleteAssetPack(@Nonnull EditorClient editorClient, @Nonnull String packId) { if (packId.equalsIgnoreCase("Hytale:Hytale")) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK); } else { DataSource dataSource = this.getDataSourceForPack(packId); if (dataSource == null) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK); } else { AssetModule.get().unregisterPack(packId); @@ -692,9 +716,7 @@ public class AssetEditorPlugin extends JavaPlugin { } if (!isInModsDirectory) { - editorClient.sendPopupNotification( - AssetEditorPopupNotificationType.Error, Message.translation("server.assetEditor.messages.packOutsideDirectory") - ); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.PACK_OUTSIDE_DIRECTORY); } else { try { FileUtil.deleteDirectory(targetPath); @@ -708,17 +730,17 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleUpdateAssetPack(@Nonnull EditorClient editorClient, @Nonnull String packId, @Nonnull AssetPackManifest packetManifest) { if (packId.equals("Hytale:Hytale")) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK); } else { DataSource dataSource = this.getDataSourceForPack(packId); if (dataSource == null) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.ASSETS_READ_ONLY); } else { PluginManifest manifest = dataSource.getManifest(); if (manifest == null) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Message.translation("server.assetEditor.messages.manifestNotFound")); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.MANIFEST_NOT_FOUND); } else { boolean didIdentifierChange = false; if (packetManifest.name != null && !packetManifest.name.isEmpty() && !manifest.getName().equals(packetManifest.name)) { @@ -742,11 +764,9 @@ public class AssetEditorPlugin extends JavaPlugin { if (packetManifest.version != null && !packetManifest.version.isEmpty()) { try { manifest.setVersion(Semver.fromString(packetManifest.version)); - } catch (IllegalArgumentException var14) { - this.getLogger().at(Level.WARNING).withCause(var14).log("Invalid version format: %s", packetManifest.version); - editorClient.sendPopupNotification( - AssetEditorPopupNotificationType.Error, Message.translation("server.assetEditor.messages.invalidVersionFormat") - ); + } catch (IllegalArgumentException var15) { + this.getLogger().at(Level.WARNING).withCause(var15).log("Invalid version format: %s", packetManifest.version); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.INVALID_VERSION_FORMAT); return; } } @@ -765,23 +785,35 @@ public class AssetEditorPlugin extends JavaPlugin { manifest.setAuthors(authors); } + if (packetManifest.serverVersion != null) { + manifest.setServerVersion(packetManifest.serverVersion); + } + Path manifestPath = dataSource.getRootPath().resolve("manifest.json"); try { BsonUtil.writeSync(manifestPath, PluginManifest.CODEC, manifest, this.getLogger()); this.getLogger().at(Level.INFO).log("Saved manifest for pack %s", packId); - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Success, Message.translation("server.assetEditor.messages.manifestSaved")); - } catch (IOException var13) { - this.getLogger().at(Level.SEVERE).withCause(var13).log("Failed to save manifest for pack %s", packId); - editorClient.sendPopupNotification( - AssetEditorPopupNotificationType.Error, Message.translation("server.assetEditor.messages.manifestSaveFailed") - ); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Success, Messages.MANIFEST_SAVED); + } catch (IOException var14) { + this.getLogger().at(Level.SEVERE).withCause(var14).log("Failed to save manifest for pack %s", packId); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.MANIFEST_SAVE_FAILED); } this.broadcastPackAddedOrUpdated(packId, manifest); if (didIdentifierChange) { - String newPackId = new PluginIdentifier(manifest).toString(); + PluginIdentifier newPackIdentifier = new PluginIdentifier(manifest); + String newPackId = newPackIdentifier.toString(); Path packPath = dataSource.getRootPath(); + HytaleServerConfig serverConfig = HytaleServer.get().getConfig(); + HytaleServerConfig.ModConfig.setBoot(serverConfig, newPackIdentifier, true); + Map modConfig = serverConfig.getModConfig(); + modConfig.remove(PluginIdentifier.fromString(packId)); + serverConfig.markChanged(); + if (serverConfig.consumeHasChanged()) { + HytaleServerConfig.save(serverConfig).join(); + } + AssetModule assetModule = AssetModule.get(); assetModule.unregisterPack(packId); assetModule.registerPack(newPackId, packPath, manifest); @@ -793,7 +825,7 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleCreateAssetPack(@Nonnull EditorClient editorClient, @Nonnull AssetPackManifest packetManifest, int requestToken) { if (packetManifest.name == null || packetManifest.name.isEmpty()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.packNameRequired")); + editorClient.sendFailureReply(requestToken, Messages.PACK_NAME_REQUIRED); } else if (packetManifest.group != null && !packetManifest.group.isEmpty()) { PluginManifest manifest = new PluginManifest(); manifest.setName(packetManifest.name); @@ -809,9 +841,9 @@ public class AssetEditorPlugin extends JavaPlugin { if (packetManifest.version != null && !packetManifest.version.isEmpty()) { try { manifest.setVersion(Semver.fromString(packetManifest.version)); - } catch (IllegalArgumentException var12) { - this.getLogger().at(Level.WARNING).withCause(var12).log("Invalid version format: %s", packetManifest.version); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.invalidVersionFormat")); + } catch (IllegalArgumentException var13) { + this.getLogger().at(Level.WARNING).withCause(var13).log("Invalid version format: %s", packetManifest.version); + editorClient.sendFailureReply(requestToken, Messages.INVALID_VERSION_FORMAT); return; } } @@ -830,9 +862,10 @@ public class AssetEditorPlugin extends JavaPlugin { manifest.setAuthors(authors); } + manifest.setServerVersion(packetManifest.serverVersion); String packId = new PluginIdentifier(manifest).toString(); if (this.assetPackDataSources.containsKey(packId)) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.packAlreadyExists")); + editorClient.sendFailureReply(requestToken, Messages.PACK_ALREADY_EXISTS); } else { Path modsPath = PluginManager.MODS_PATH; String dirName = AssetPathUtil.removeInvalidFileNameChars( @@ -840,33 +873,41 @@ public class AssetEditorPlugin extends JavaPlugin { ); Path normalized = Path.of(dirName).normalize(); if (AssetPathUtil.isInvalidFileName(normalized)) { - editorClient.sendFailureReply(requestToken, Messages.INVALID_FILENAME_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.INVALID_FILE_NAME); } else { Path packPath = modsPath.resolve(normalized).normalize(); if (!packPath.startsWith(modsPath)) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.packOutsideDirectory")); + editorClient.sendFailureReply(requestToken, Messages.PACK_OUTSIDE_DIRECTORY); } else if (Files.exists(packPath)) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.packAlreadyExistsAtPath")); + editorClient.sendFailureReply(requestToken, Messages.PACK_ALREADY_EXISTS_AT_PATH); } else { try { Files.createDirectories(packPath); Path manifestPath = packPath.resolve("manifest.json"); BsonUtil.writeSync(manifestPath, PluginManifest.CODEC, manifest, this.getLogger()); + HytaleServerConfig serverConfig = HytaleServer.get().getConfig(); + HytaleServerConfig.ModConfig.setBoot(serverConfig, new PluginIdentifier(manifest), true); + serverConfig.markChanged(); + if (serverConfig.consumeHasChanged()) { + HytaleServerConfig.save(serverConfig).join(); + } + AssetModule.get().registerPack(packId, packPath, manifest); - editorClient.sendSuccessReply(requestToken, Message.translation("server.assetEditor.messages.packCreated")); + editorClient.sendSuccessReply(requestToken, Messages.PACK_CREATED); this.getLogger().at(Level.INFO).log("Created new pack: %s at %s", packId, packPath); - } catch (IOException var11) { - this.getLogger().at(Level.SEVERE).withCause(var11).log("Failed to create pack %s", packId); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.packCreationFailed")); + } catch (IOException var12) { + this.getLogger().at(Level.SEVERE).withCause(var12).log("Failed to create pack %s", packId); + editorClient.sendFailureReply(requestToken, Messages.PACK_CREATION_FAILED); } } } } } else { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.packGroupRequired")); + editorClient.sendFailureReply(requestToken, Messages.PACK_GROUP_REQUIRED); } } + @Nonnull private static AssetPackManifest toManifestPacket(@Nonnull PluginManifest manifest) { AssetPackManifest packet = new AssetPackManifest(); packet.name = manifest.getName(); @@ -874,6 +915,7 @@ public class AssetEditorPlugin extends JavaPlugin { packet.group = manifest.getGroup(); packet.version = manifest.getVersion() != null ? manifest.getVersion().toString() : ""; packet.website = manifest.getWebsite() != null ? manifest.getWebsite() : ""; + packet.serverVersion = manifest.getServerVersion() != null ? manifest.getServerVersion() : ""; List authors = new ObjectArrayList<>(); for (AuthorInfo a : manifest.getAuthors()) { @@ -887,7 +929,7 @@ public class AssetEditorPlugin extends JavaPlugin { return packet; } - private void broadcastPackAddedOrUpdated(String packId, PluginManifest manifest) { + private void broadcastPackAddedOrUpdated(@Nonnull String packId, @Nonnull PluginManifest manifest) { AssetPackManifest manifestPacket = toManifestPacket(manifest); for (Set clients : this.uuidToEditorClients.values()) { @@ -993,11 +1035,11 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleAssetUpdate(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, @Nonnull byte[] data, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken); if (assetTypeHandler != null) { @@ -1007,13 +1049,13 @@ public class AssetEditorPlugin extends JavaPlugin { try { if (!dataSource.doesAssetExist(assetPath.path())) { this.getLogger().at(Level.WARNING).log("%s does not exist", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.doesntExist")); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_DOESNT_EXIST); return; } if (!assetTypeHandler.isValidData(data)) { this.getLogger().at(Level.WARNING).log("Failed to validate data for %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createAsset.failed")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_ASSET_FAILED); return; } @@ -1026,7 +1068,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.WARNING).log("Failed to update asset %s in data source!", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.failed")); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1048,26 +1090,26 @@ public class AssetEditorPlugin extends JavaPlugin { int requestToken ) { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.getAssetTypeHandler(assetType); - if (!(assetTypeHandler instanceof JsonTypeHandler)) { + if (!(assetTypeHandler instanceof JsonTypeHandler jsonTypeHandler)) { this.getLogger().at(Level.WARNING).log("Invalid asset type %s", assetType); editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.unknownAssetType").param("assetType", assetType)); } else { DataSource dataSource; - if (assetIndex > -1 && assetTypeHandler instanceof AssetStoreTypeHandler) { - AssetStore assetStore = ((AssetStoreTypeHandler)assetTypeHandler).getAssetStore(); + if (assetIndex > -1 && assetTypeHandler instanceof AssetStoreTypeHandler assetStoreTypeHandler) { + AssetStore assetStore = assetStoreTypeHandler.getAssetStore(); AssetMap assetMap = assetStore.getAssetMap(); String keyString = AssetStoreUtil.getIdFromIndex(assetStore, assetIndex); Object key = assetStore.decodeStringKey(keyString); Path storedPath = assetMap.getPath(key); String storedAssetPack = assetMap.getAssetPack(key); if (storedPath == null || storedAssetPack == null) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.unknownAssetIndex")); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_INDEX); return; } dataSource = this.getDataSourceForPack(storedAssetPack); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); return; } @@ -1075,18 +1117,18 @@ public class AssetEditorPlugin extends JavaPlugin { } else { dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); return; } } if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else if (!assetPath.path().startsWith(assetTypeHandler.getRootPath())) { this.getLogger().at(Level.WARNING).log("%s is not within valid asset directory", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.directoryOutsideRoot")); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ROOT); } else { String fileExtension = PathUtil.getFileExtension(assetPath.path()); if (!fileExtension.equalsIgnoreCase(assetTypeHandler.getConfig().fileExtension)) { @@ -1107,7 +1149,7 @@ public class AssetEditorPlugin extends JavaPlugin { byte[] bytes = dataSource.getAssetBytes(assetPath.path()); if (bytes == null) { this.getLogger().at(Level.WARNING).log("%s does not exist", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.doesntExist")); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_DOESNT_EXIST); return; } @@ -1118,9 +1160,9 @@ public class AssetEditorPlugin extends JavaPlugin { asset = this.applyCommandsToAsset(bytes, assetPath, commands, rebuildCacheBuilder); String json = BsonUtil.toJson(asset) + "\n"; bytes = json.getBytes(StandardCharsets.UTF_8); - } catch (Exception var23) { - this.getLogger().at(Level.WARNING).withCause(var23).log("Failed to apply commands to %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.failed")); + } catch (Exception var24) { + this.getLogger().at(Level.WARNING).withCause(var24).log("Failed to apply commands to %s", assetPath); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_FAILED); return; } @@ -1135,18 +1177,17 @@ public class AssetEditorPlugin extends JavaPlugin { this.updateJsonAssetForConnectedClients(assetPath, commands, editorClient); editorClient.sendSuccessReply(requestToken); this.sendModifiedAssetsUpdateToConnectedUsers(); - ((JsonTypeHandler)assetTypeHandler) - .loadAssetFromDocument( - assetPath, - dataSource.getFullPathToAssetData(assetPath.path()), - asset.clone(), - new AssetUpdateQuery(rebuildCacheBuilder.build()), - editorClient - ); + jsonTypeHandler.loadAssetFromDocument( + assetPath, + dataSource.getFullPathToAssetData(assetPath.path()), + asset.clone(), + new AssetUpdateQuery(rebuildCacheBuilder.build()), + editorClient + ); return; } - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.failed")); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1158,17 +1199,17 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleUndo(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken); if (assetTypeHandler != null) { if (!(assetTypeHandler instanceof JsonTypeHandler)) { this.getLogger().at(Level.WARNING).log("Undo can only be applied to an instance of JsonTypeHandler"); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.invalidAssetType")); + editorClient.sendFailureReply(requestToken, Messages.INVALID_ASSET_TYPE); } else { long stamp = this.globalEditLock.writeLock(); @@ -1176,7 +1217,7 @@ public class AssetEditorPlugin extends JavaPlugin { AssetUndoRedoInfo undoRedo = this.undoRedoManager.getUndoRedoStack(assetPath); if (undoRedo == null || undoRedo.undoStack.isEmpty()) { this.getLogger().at(Level.INFO).log("Nothing to undo"); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.undo.empty")); + editorClient.sendFailureReply(requestToken, Messages.UNDO_EMPTY); return; } @@ -1195,7 +1236,7 @@ public class AssetEditorPlugin extends JavaPlugin { byte[] bytes = dataSource.getAssetBytes(assetPath.path()); if (bytes == null) { this.getLogger().at(Level.WARNING).log("%s does not exist", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.doesntExist")); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_DOESNT_EXIST); return; } @@ -1208,7 +1249,7 @@ public class AssetEditorPlugin extends JavaPlugin { bytes = json.getBytes(StandardCharsets.UTF_8); } catch (Exception var18) { this.getLogger().at(Level.WARNING).withCause(var18).log("Failed to undo for %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.undo.failed")); + editorClient.sendFailureReply(requestToken, Messages.UNDO_FAILED); return; } @@ -1229,7 +1270,7 @@ public class AssetEditorPlugin extends JavaPlugin { return; } - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.undo.failed")); + editorClient.sendFailureReply(requestToken, Messages.UNDO_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1241,17 +1282,17 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleRedo(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken); if (assetTypeHandler != null) { if (!(assetTypeHandler instanceof JsonTypeHandler)) { this.getLogger().at(Level.WARNING).log("Redo can only be applied to an instance of JsonTypeHandler"); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.invalidAssetType")); + editorClient.sendFailureReply(requestToken, Messages.INVALID_ASSET_TYPE); } else { long stamp = this.globalEditLock.writeLock(); @@ -1259,14 +1300,14 @@ public class AssetEditorPlugin extends JavaPlugin { AssetUndoRedoInfo undoRedo = this.undoRedoManager.getUndoRedoStack(assetPath); if (undoRedo == null || undoRedo.redoStack.isEmpty()) { this.getLogger().at(Level.WARNING).log("Nothing to redo"); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.redo.empty")); + editorClient.sendFailureReply(requestToken, Messages.REDO_EMPTY); return; } byte[] bytes = dataSource.getAssetBytes(assetPath.path()); if (bytes == null) { this.getLogger().at(Level.WARNING).log("%s does not exist", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.update.doesntExist")); + editorClient.sendFailureReply(requestToken, Messages.UPDATE_DOESNT_EXIST); return; } @@ -1280,7 +1321,7 @@ public class AssetEditorPlugin extends JavaPlugin { bytes = json.getBytes(StandardCharsets.UTF_8); } catch (Exception var17) { this.getLogger().at(Level.WARNING).withCause(var17).log("Failed to redo for %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.redo.failed")); + editorClient.sendFailureReply(requestToken, Messages.REDO_FAILED); return; } @@ -1301,7 +1342,7 @@ public class AssetEditorPlugin extends JavaPlugin { return; } - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.redo.failed")); + editorClient.sendFailureReply(requestToken, Messages.REDO_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1313,16 +1354,16 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleFetchAsset(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else if (this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken) != null) { long stamp = this.globalEditLock.readLock(); try { if (!dataSource.doesAssetExist(assetPath.path())) { this.getLogger().at(Level.WARNING).log("%s is not a regular file", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.fetchAsset.doesntExist")); + editorClient.sendFailureReply(requestToken, Messages.FETCH_ASSET_DOESNT_EXIST); return; } @@ -1334,7 +1375,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.INFO).log("Failed to get '%s'", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.fetchAsset.failed")); + editorClient.sendFailureReply(requestToken, Messages.FETCH_ASSET_FAILED); } finally { this.globalEditLock.unlockRead(stamp); } @@ -1344,9 +1385,9 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleFetchJsonAssetWithParents(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, boolean isFromOpenedTab, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else if (this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken) != null) { long stamp = this.globalEditLock.readLock(); @@ -1362,7 +1403,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.INFO).log("Failed to get '%s'", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.fetchAsset.failed")); + editorClient.sendFailureReply(requestToken, Messages.FETCH_ASSET_FAILED); } finally { this.globalEditLock.unlockRead(stamp); } @@ -1372,43 +1413,38 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleRequestChildIds(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); + } else if (!(this.assetTypeRegistry.getAssetTypeHandlerForPath(assetPath.path()) instanceof AssetStoreTypeHandler assetStoreTypeHandler)) { + this.getLogger().at(Level.WARNING).log("Invalid asset type for %s", assetPath); + editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.REQUEST_CHILD_IDS_ASSET_TYPE_MISSING); } else { - AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.getAssetTypeHandlerForPath(assetPath.path()); - if (!(assetTypeHandler instanceof AssetStoreTypeHandler)) { - this.getLogger().at(Level.WARNING).log("Invalid asset type for %s", assetPath); - editorClient.sendPopupNotification( - AssetEditorPopupNotificationType.Error, Message.translation("server.assetEditor.messages.requestChildIds.assetTypeMissing") - ); - } else { - AssetStore assetStore = ((AssetStoreTypeHandler)assetTypeHandler).getAssetStore(); - Object key = assetStore.decodeFilePathKey(assetPath.path()); - Set children = assetStore.getAssetMap().getChildren(key); - HashSet childrenIds = new HashSet<>(); - if (children != null) { - for (Object child : children) { - if (assetStore.getAssetMap().getPath(child) != null) { - childrenIds.add(child.toString()); - } + AssetStore assetStore = assetStoreTypeHandler.getAssetStore(); + Object key = assetStore.decodeFilePathKey(assetPath.path()); + Set children = assetStore.getAssetMap().getChildren(key); + HashSet childrenIds = new HashSet(); + if (children != null) { + for (Object child : children) { + if (assetStore.getAssetMap().getPath(child) != null) { + childrenIds.add(child.toString()); } } - - this.getLogger().at(Level.INFO).log("Children ids for '%s': %s", key.toString(), childrenIds); - editorClient.getPacketHandler().write(new AssetEditorRequestChildrenListReply(assetPath.toPacket(), childrenIds.toArray(String[]::new))); } + + this.getLogger().at(Level.INFO).log("Children ids for '%s': %s", key.toString(), childrenIds); + editorClient.getPacketHandler().write(new AssetEditorRequestChildrenListReply(assetPath.toPacket(), childrenIds.toArray(String[]::new))); } } public void handleDeleteAsset(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken); if (assetTypeHandler != null) { @@ -1418,7 +1454,7 @@ public class AssetEditorPlugin extends JavaPlugin { try { if (!dataSource.doesAssetExist(assetPath.path())) { this.getLogger().at(Level.WARNING).log("%s does not exist", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.deleteAsset.alreadyDeleted")); + editorClient.sendFailureReply(requestToken, Messages.DELETE_ASSET_ALREADY_DELETED); return; } @@ -1434,7 +1470,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.WARNING).log("Failed to delete %s from data source", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.failedToDeleteAsset")); + editorClient.sendFailureReply(requestToken, Messages.FAILED_TO_DELETE_ASSET); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1447,24 +1483,24 @@ public class AssetEditorPlugin extends JavaPlugin { } } - public void handleSubscribeToModifiedAssetsChanges(EditorClient editorClient) { + public void handleSubscribeToModifiedAssetsChanges(@Nonnull EditorClient editorClient) { this.clientsSubscribedToModifiedAssetsChanges.add(editorClient); } - public void handleUnsubscribeFromModifiedAssetsChanges(EditorClient editorClient) { + public void handleUnsubscribeFromModifiedAssetsChanges(@Nonnull EditorClient editorClient) { this.clientsSubscribedToModifiedAssetsChanges.remove(editorClient); } public void handleRenameAsset(@Nonnull EditorClient editorClient, @Nonnull AssetPath oldAssetPath, @Nonnull AssetPath newAssetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(oldAssetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, oldAssetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else if (!this.isValidPath(dataSource, newAssetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.tryGetAssetTypeHandler(oldAssetPath.path(), editorClient, requestToken); if (assetTypeHandler != null) { @@ -1479,21 +1515,21 @@ public class AssetEditorPlugin extends JavaPlugin { ); } else if (!newAssetPath.path().startsWith(assetTypeHandler.getRootPath())) { this.getLogger().at(Level.WARNING).log("%s is not within valid asset directory", newAssetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.directoryOutsideRoot")); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ROOT); } else { long stamp = this.globalEditLock.writeLock(); try { if (dataSource.doesAssetExist(newAssetPath.path())) { this.getLogger().at(Level.WARNING).log("%s already exists", newAssetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.renameAsset.alreadyExists")); + editorClient.sendFailureReply(requestToken, Messages.RENAME_ASSET_ALREADY_EXISTS); return; } byte[] oldAsset = dataSource.getAssetBytes(oldAssetPath.path()); if (oldAsset == null) { this.getLogger().at(Level.WARNING).log("%s is not a regular file", oldAssetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.renameAsset.doesntExist")); + editorClient.sendFailureReply(requestToken, Messages.RENAME_ASSET_DOESNT_EXIST); return; } @@ -1517,7 +1553,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.WARNING).log("Failed to move file %s to %s", oldAssetPath, newAssetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.renameAsset.failed")); + editorClient.sendFailureReply(requestToken, Messages.RENAME_ASSET_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1529,24 +1565,24 @@ public class AssetEditorPlugin extends JavaPlugin { public void handleDeleteDirectory(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.directoryOutsideRoot")); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ROOT); } else if (!this.getAssetTypeRegistry().isPathInAssetTypeFolder(assetPath.path())) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { long stamp = this.globalEditLock.writeLock(); try { if (!dataSource.doesDirectoryExist(assetPath.path())) { this.getLogger().at(Level.WARNING).log("Directory doesn't exist %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createDirectory.alreadyExists")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_DIRECTORY_ALREADY_EXISTS); return; } if (!dataSource.getAssetTree().isDirectoryEmpty(assetPath.path())) { this.getLogger().at(Level.WARNING).log("%s must be empty", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.deleteDirectory.notEmpty")); + editorClient.sendFailureReply(requestToken, Messages.DELETE_DIRECTORY_NOT_EMPTY); return; } @@ -1560,7 +1596,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.WARNING).log("Directory %s could not be deleted!", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.deleteDirectory.failed")); + editorClient.sendFailureReply(requestToken, Messages.DELETE_DIRECTORY_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1568,31 +1604,31 @@ public class AssetEditorPlugin extends JavaPlugin { } public void handleRenameDirectory(@Nonnull EditorClient editorClient, AssetPath path, AssetPath newPath, int requestToken) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.renameDirectory.unsupported")); + editorClient.sendFailureReply(requestToken, Messages.RENAME_DIRECTORY_UNSUPPORTED); } public void handleCreateDirectory(@Nonnull EditorClient editorClient, @Nonnull AssetPath assetPath, int requestToken) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createDirectory.noDataSource")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_DIRECTORY_NO_DATA_SOURCE); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createDirectory.noPath")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_DIRECTORY_NO_PATH); } else { long stamp = this.globalEditLock.writeLock(); try { if (dataSource.doesDirectoryExist(assetPath.path())) { this.getLogger().at(Level.WARNING).log("Directory already exists at %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createDirectory.alreadyExists")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_DIRECTORY_ALREADY_EXISTS); return; } Path parentDirectoryPath = assetPath.path().getParent(); if (!dataSource.doesDirectoryExist(parentDirectoryPath)) { this.getLogger().at(Level.WARNING).log("Parent directory is missing for %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.parentDirectoryMissing")); + editorClient.sendFailureReply(requestToken, Messages.PARENT_DIRECTORY_MISSING); return; } @@ -1609,7 +1645,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.WARNING).log("Failed to create directory %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.failedToCreateDirectory")); + editorClient.sendFailureReply(requestToken, Messages.FAILED_TO_CREATE_DIRECTORY); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1626,11 +1662,11 @@ public class AssetEditorPlugin extends JavaPlugin { ) { DataSource dataSource = this.getDataSourceForPath(assetPath); if (dataSource == null) { - editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSETPACK_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.UNKNOWN_ASSET_PACK); } else if (dataSource.isImmutable()) { - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.assetsReadOnly")); + editorClient.sendFailureReply(requestToken, Messages.ASSETS_READ_ONLY); } else if (!this.isValidPath(dataSource, assetPath)) { - editorClient.sendFailureReply(requestToken, Messages.OUTSIDE_ASSET_ROOT_MESSAGE); + editorClient.sendFailureReply(requestToken, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT); } else { AssetTypeHandler assetTypeHandler = this.assetTypeRegistry.tryGetAssetTypeHandler(assetPath.path(), editorClient, requestToken); if (assetTypeHandler != null) { @@ -1639,13 +1675,13 @@ public class AssetEditorPlugin extends JavaPlugin { try { if (dataSource.doesAssetExist(assetPath.path())) { this.getLogger().at(Level.WARNING).log("%s already exists", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createAsset.idAlreadyExists")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_ASSET_ID_ALREADY_EXISTS); return; } if (!assetTypeHandler.isValidData(data)) { this.getLogger().at(Level.WARNING).log("Failed to validate data for %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createAsset.failed")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_ASSET_FAILED); return; } @@ -1681,7 +1717,7 @@ public class AssetEditorPlugin extends JavaPlugin { } this.getLogger().at(Level.WARNING).log("Failed to create asset %s", assetPath); - editorClient.sendFailureReply(requestToken, Message.translation("server.assetEditor.messages.createAsset.failed")); + editorClient.sendFailureReply(requestToken, Messages.CREATE_ASSET_FAILED); } finally { this.globalEditLock.unlockWrite(stamp); } @@ -1778,13 +1814,13 @@ public class AssetEditorPlugin extends JavaPlugin { this.updateAssetForConnectedClients(assetPath, null); } - private void updateAssetForConnectedClients(@Nonnull AssetPath assetPath, EditorClient ignoreEditorClient) { + private void updateAssetForConnectedClients(@Nonnull AssetPath assetPath, @Nullable EditorClient ignoreEditorClient) { DataSource dataSource = this.getDataSourceForPath(assetPath); byte[] bytes = dataSource.getAssetBytes(assetPath.path()); this.updateAssetForConnectedClients(assetPath, bytes, ignoreEditorClient); } - private void updateAssetForConnectedClients(@Nonnull AssetPath assetPath, byte[] bytes, EditorClient ignoreEditorClient) { + private void updateAssetForConnectedClients(@Nonnull AssetPath assetPath, byte[] bytes, @Nullable EditorClient ignoreEditorClient) { AssetEditorAssetUpdated updatePacket = new AssetEditorAssetUpdated(assetPath.toPacket(), bytes); for (Entry entry : this.clientOpenAssetPathMapping.entrySet()) { @@ -1794,11 +1830,13 @@ public class AssetEditorPlugin extends JavaPlugin { } } - private void updateJsonAssetForConnectedClients(@Nonnull AssetPath assetPath, JsonUpdateCommand[] commands) { + private void updateJsonAssetForConnectedClients(@Nonnull AssetPath assetPath, @Nonnull JsonUpdateCommand[] commands) { this.updateJsonAssetForConnectedClients(assetPath, commands, null); } - private void updateJsonAssetForConnectedClients(@Nonnull AssetPath assetPath, JsonUpdateCommand[] commands, EditorClient ignoreEditorClient) { + private void updateJsonAssetForConnectedClients( + @Nonnull AssetPath assetPath, @Nonnull JsonUpdateCommand[] commands, @Nullable EditorClient ignoreEditorClient + ) { AssetEditorJsonAssetUpdated updatePacket = new AssetEditorJsonAssetUpdated(assetPath.toPacket(), commands); for (Entry connectedPlayer : this.clientOpenAssetPathMapping.entrySet()) { @@ -1810,7 +1848,7 @@ public class AssetEditorPlugin extends JavaPlugin { @Nonnull private AssetEditorLastModifiedAssets buildAssetEditorLastModifiedAssetsPacket() { - ArrayList allAssets = new ArrayList<>(); + List allAssets = new ObjectArrayList<>(); for (Entry dataSource : this.assetPackDataSources.entrySet()) { if (dataSource.getValue() instanceof StandardDataSource standardDataSource) { diff --git a/src/com/hypixel/hytale/builtin/asseteditor/Messages.java b/src/com/hypixel/hytale/builtin/asseteditor/Messages.java index 110e717e..c152158d 100644 --- a/src/com/hypixel/hytale/builtin/asseteditor/Messages.java +++ b/src/com/hypixel/hytale/builtin/asseteditor/Messages.java @@ -1,10 +1,93 @@ package com.hypixel.hytale.builtin.asseteditor; import com.hypixel.hytale.server.core.Message; +import javax.annotation.Nonnull; public class Messages { - public static final Message USAGE_DENIED_MESSAGE = Message.translation("server.assetEditor.messages.usageDenied"); - public static final Message INVALID_FILENAME_MESSAGE = Message.translation("server.assetEditor.messages.invalidFileName"); - public static final Message OUTSIDE_ASSET_ROOT_MESSAGE = Message.translation("server.assetEditor.messages.directoryOutsideAssetTypeRoot"); - public static final Message UNKNOWN_ASSETPACK_MESSAGE = Message.translation("server.assetEditor.messages.unknownAssetPack"); + @Nonnull + public static final Message USAGE_DENIED = Message.translation("server.assetEditor.messages.usageDenied"); + @Nonnull + public static final Message INVALID_FILE_NAME = Message.translation("server.assetEditor.messages.invalidFileName"); + @Nonnull + public static final Message DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT = Message.translation("server.assetEditor.messages.directoryOutsideAssetTypeRoot"); + @Nonnull + public static final Message UNKNOWN_ASSET_PACK = Message.translation("server.assetEditor.messages.unknownAssetPack"); + @Nonnull + public static final Message ASSETS_READ_ONLY = Message.translation("server.assetEditor.messages.assetsReadOnly"); + @Nonnull + public static final Message UPDATE_DOESNT_EXIST = Message.translation("server.assetEditor.messages.update.doesntExist"); + @Nonnull + public static final Message CREATE_ASSET_FAILED = Message.translation("server.assetEditor.messages.createAsset.failed"); + @Nonnull + public static final Message UPDATE_FAILED = Message.translation("server.assetEditor.messages.update.failed"); + @Nonnull + public static final Message PACK_OUTSIDE_DIRECTORY = Message.translation("server.assetEditor.messages.packOutsideDirectory"); + @Nonnull + public static final Message PACK_ALREADY_EXISTS_AT_PATH = Message.translation("server.assetEditor.messages.packAlreadyExistsAtPath"); + @Nonnull + public static final Message PACK_CREATED = Message.translation("server.assetEditor.messages.packCreated"); + @Nonnull + public static final Message PACK_CREATION_FAILED = Message.translation("server.assetEditor.messages.packCreationFailed"); + @Nonnull + public static final Message UNKNOWN_ASSET_INDEX = Message.translation("server.assetEditor.messages.unknownAssetIndex"); + @Nonnull + public static final Message DIRECTORY_OUTSIDE_ROOT = Message.translation("server.assetEditor.messages.directoryOutsideRoot"); + @Nonnull + public static final Message INVALID_ASSET_TYPE = Message.translation("server.assetEditor.messages.invalidAssetType"); + @Nonnull + public static final Message UNDO_EMPTY = Message.translation("server.assetEditor.messages.undo.empty"); + @Nonnull + public static final Message UNDO_FAILED = Message.translation("server.assetEditor.messages.undo.failed"); + @Nonnull + public static final Message REDO_EMPTY = Message.translation("server.assetEditor.messages.redo.empty"); + @Nonnull + public static final Message REDO_FAILED = Message.translation("server.assetEditor.messages.redo.failed"); + @Nonnull + public static final Message FETCH_ASSET_DOESNT_EXIST = Message.translation("server.assetEditor.messages.fetchAsset.doesntExist"); + @Nonnull + public static final Message FETCH_ASSET_FAILED = Message.translation("server.assetEditor.messages.fetchAsset.failed"); + @Nonnull + public static final Message REQUEST_CHILD_IDS_ASSET_TYPE_MISSING = Message.translation("server.assetEditor.messages.requestChildIds.assetTypeMissing"); + @Nonnull + public static final Message DELETE_ASSET_ALREADY_DELETED = Message.translation("server.assetEditor.messages.deleteAsset.alreadyDeleted"); + @Nonnull + public static final Message FAILED_TO_DELETE_ASSET = Message.translation("server.assetEditor.messages.failedToDeleteAsset"); + @Nonnull + public static final Message RENAME_ASSET_ALREADY_EXISTS = Message.translation("server.assetEditor.messages.renameAsset.alreadyExists"); + @Nonnull + public static final Message RENAME_ASSET_DOESNT_EXIST = Message.translation("server.assetEditor.messages.renameAsset.doesntExist"); + @Nonnull + public static final Message RENAME_ASSET_FAILED = Message.translation("server.assetEditor.messages.renameAsset.failed"); + @Nonnull + public static final Message CREATE_DIRECTORY_ALREADY_EXISTS = Message.translation("server.assetEditor.messages.createDirectory.alreadyExists"); + @Nonnull + public static final Message DELETE_DIRECTORY_NOT_EMPTY = Message.translation("server.assetEditor.messages.deleteDirectory.notEmpty"); + @Nonnull + public static final Message DELETE_DIRECTORY_FAILED = Message.translation("server.assetEditor.messages.deleteDirectory.failed"); + @Nonnull + public static final Message RENAME_DIRECTORY_UNSUPPORTED = Message.translation("server.assetEditor.messages.renameDirectory.unsupported"); + @Nonnull + public static final Message CREATE_DIRECTORY_NO_DATA_SOURCE = Message.translation("server.assetEditor.messages.createDirectory.noDataSource"); + @Nonnull + public static final Message CREATE_DIRECTORY_NO_PATH = Message.translation("server.assetEditor.messages.createDirectory.noPath"); + @Nonnull + public static final Message PARENT_DIRECTORY_MISSING = Message.translation("server.assetEditor.messages.parentDirectoryMissing"); + @Nonnull + public static final Message FAILED_TO_CREATE_DIRECTORY = Message.translation("server.assetEditor.messages.failedToCreateDirectory"); + @Nonnull + public static final Message CREATE_ASSET_ID_ALREADY_EXISTS = Message.translation("server.assetEditor.messages.createAsset.idAlreadyExists"); + @Nonnull + public static final Message MANIFEST_NOT_FOUND = Message.translation("server.assetEditor.messages.manifestNotFound"); + @Nonnull + public static final Message INVALID_VERSION_FORMAT = Message.translation("server.assetEditor.messages.invalidVersionFormat"); + @Nonnull + public static final Message MANIFEST_SAVED = Message.translation("server.assetEditor.messages.manifestSaved"); + @Nonnull + public static final Message MANIFEST_SAVE_FAILED = Message.translation("server.assetEditor.messages.manifestSaveFailed"); + @Nonnull + public static final Message PACK_NAME_REQUIRED = Message.translation("server.assetEditor.messages.packNameRequired"); + @Nonnull + public static final Message PACK_GROUP_REQUIRED = Message.translation("server.assetEditor.messages.packGroupRequired"); + @Nonnull + public static final Message PACK_ALREADY_EXISTS = Message.translation("server.assetEditor.messages.packAlreadyExists"); } diff --git a/src/com/hypixel/hytale/builtin/asseteditor/assettypehandler/CommonAssetTypeHandler.java b/src/com/hypixel/hytale/builtin/asseteditor/assettypehandler/CommonAssetTypeHandler.java index 1c5ec892..95cc6edc 100644 --- a/src/com/hypixel/hytale/builtin/asseteditor/assettypehandler/CommonAssetTypeHandler.java +++ b/src/com/hypixel/hytale/builtin/asseteditor/assettypehandler/CommonAssetTypeHandler.java @@ -21,11 +21,12 @@ import java.nio.file.Path; import java.util.Collections; import java.util.logging.Level; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class CommonAssetTypeHandler extends AssetTypeHandler { private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); - public CommonAssetTypeHandler(String id, String icon, String fileExtension, AssetEditorEditorType editorType) { + public CommonAssetTypeHandler(String id, @Nullable String icon, String fileExtension, AssetEditorEditorType editorType) { super(new AssetEditorAssetType(id, icon, true, "Common", fileExtension, editorType)); } diff --git a/src/com/hypixel/hytale/builtin/asseteditor/datasource/StandardDataSource.java b/src/com/hypixel/hytale/builtin/asseteditor/datasource/StandardDataSource.java index b0306dbe..d71998ad 100644 --- a/src/com/hypixel/hytale/builtin/asseteditor/datasource/StandardDataSource.java +++ b/src/com/hypixel/hytale/builtin/asseteditor/datasource/StandardDataSource.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.builtin.asseteditor.data.AssetState; import com.hypixel.hytale.builtin.asseteditor.data.ModifiedAsset; import com.hypixel.hytale.codec.ExtraInfo; import com.hypixel.hytale.common.plugin.PluginManifest; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.Options; @@ -134,7 +135,12 @@ public class StandardDataSource implements DataSource { } public Path resolveAbsolutePath(Path path) { - return this.rootPath.resolve(path.toString()).toAbsolutePath(); + Path resolved = this.rootPath.resolve(path.toString()).toAbsolutePath(); + if (!PathUtil.isChildOf(this.rootPath, resolved)) { + throw new IllegalArgumentException("Invalid path: " + path); + } else { + return resolved; + } } @Override diff --git a/src/com/hypixel/hytale/builtin/beds/BedsPlugin.java b/src/com/hypixel/hytale/builtin/beds/BedsPlugin.java index 884d00ad..314caad2 100644 --- a/src/com/hypixel/hytale/builtin/beds/BedsPlugin.java +++ b/src/com/hypixel/hytale/builtin/beds/BedsPlugin.java @@ -6,15 +6,20 @@ import com.hypixel.hytale.builtin.beds.sleep.components.SleepTracker; import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSomnolence; import com.hypixel.hytale.builtin.beds.sleep.systems.player.EnterBedSystem; import com.hypixel.hytale.builtin.beds.sleep.systems.player.RegisterTrackerSystem; +import com.hypixel.hytale.builtin.beds.sleep.systems.player.SleepNotificationSystem; import com.hypixel.hytale.builtin.beds.sleep.systems.player.UpdateSleepPacketSystem; import com.hypixel.hytale.builtin.beds.sleep.systems.player.WakeUpOnDismountSystem; import com.hypixel.hytale.builtin.beds.sleep.systems.world.StartSlumberSystem; import com.hypixel.hytale.builtin.beds.sleep.systems.world.UpdateWorldSlumberSystem; +import com.hypixel.hytale.builtin.mounts.MountedComponent; +import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; +import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; @@ -35,15 +40,26 @@ public class BedsPlugin extends JavaPlugin { @Override protected void setup() { instance = this; - this.playerSomnolenceComponentType = this.getEntityStoreRegistry().registerComponent(PlayerSomnolence.class, PlayerSomnolence::new); - this.sleepTrackerComponentType = this.getEntityStoreRegistry().registerComponent(SleepTracker.class, SleepTracker::new); - this.worldSomnolenceResourceType = this.getEntityStoreRegistry().registerResource(WorldSomnolence.class, WorldSomnolence::new); - this.getEntityStoreRegistry().registerSystem(new StartSlumberSystem()); - this.getEntityStoreRegistry().registerSystem(new UpdateSleepPacketSystem()); - this.getEntityStoreRegistry().registerSystem(new WakeUpOnDismountSystem()); - this.getEntityStoreRegistry().registerSystem(new RegisterTrackerSystem()); - this.getEntityStoreRegistry().registerSystem(new UpdateWorldSlumberSystem()); - this.getEntityStoreRegistry().registerSystem(new EnterBedSystem()); + ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); + this.playerSomnolenceComponentType = entityStoreRegistry.registerComponent(PlayerSomnolence.class, PlayerSomnolence::new); + this.sleepTrackerComponentType = entityStoreRegistry.registerComponent(SleepTracker.class, SleepTracker::new); + this.worldSomnolenceResourceType = entityStoreRegistry.registerResource(WorldSomnolence.class, WorldSomnolence::new); + ComponentType playerRefComponentType = PlayerRef.getComponentType(); + ComponentType mountedComponentType = MountedComponent.getComponentType(); + ResourceType worldTimeResourceType = WorldTimeResource.getResourceType(); + entityStoreRegistry.registerSystem(new RegisterTrackerSystem(playerRefComponentType, this.sleepTrackerComponentType)); + entityStoreRegistry.registerSystem(new WakeUpOnDismountSystem(mountedComponentType, this.playerSomnolenceComponentType)); + entityStoreRegistry.registerSystem(new EnterBedSystem(mountedComponentType, playerRefComponentType)); + entityStoreRegistry.registerSystem( + new UpdateSleepPacketSystem( + playerRefComponentType, this.playerSomnolenceComponentType, this.sleepTrackerComponentType, this.worldSomnolenceResourceType, worldTimeResourceType + ) + ); + entityStoreRegistry.registerSystem(new StartSlumberSystem(this.playerSomnolenceComponentType, this.worldSomnolenceResourceType, worldTimeResourceType)); + entityStoreRegistry.registerSystem( + new UpdateWorldSlumberSystem(this.playerSomnolenceComponentType, this.worldSomnolenceResourceType, worldTimeResourceType) + ); + entityStoreRegistry.registerSystem(new SleepNotificationSystem()); Interaction.CODEC.register("Bed", BedInteraction.class, BedInteraction.CODEC); } diff --git a/src/com/hypixel/hytale/builtin/beds/interactions/BedInteraction.java b/src/com/hypixel/hytale/builtin/beds/interactions/BedInteraction.java index 0628ea4c..f46d563c 100644 --- a/src/com/hypixel/hytale/builtin/beds/interactions/BedInteraction.java +++ b/src/com/hypixel/hytale/builtin/beds/interactions/BedInteraction.java @@ -5,6 +5,7 @@ import com.hypixel.hytale.builtin.beds.respawn.SelectOverrideRespawnPointPage; import com.hypixel.hytale.builtin.beds.respawn.SetNameRespawnPointPage; import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSleep; import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSomnolence; +import com.hypixel.hytale.builtin.beds.sleep.systems.player.SleepNotificationSystem; import com.hypixel.hytale.builtin.mounts.BlockMountAPI; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.component.AddReason; @@ -58,70 +59,71 @@ public class BedInteraction extends SimpleBlockInteraction { @Nonnull CooldownHandler cooldownHandler ) { Ref ref = context.getEntity(); - Player player = commandBuffer.getComponent(ref, Player.getComponentType()); - if (player != null) { + Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType()); + if (playerComponent != null) { Store store = commandBuffer.getStore(); PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType()); - - assert playerRefComponent != null; - - UUIDComponent playerUuidComponent = commandBuffer.getComponent(ref, UUIDComponent.getComponentType()); - - assert playerUuidComponent != null; - - UUID playerUuid = playerUuidComponent.getUuid(); - Ref chunkReference = world.getChunkStore().getChunkReference(ChunkUtil.indexChunkFromBlock(pos.x, pos.z)); - if (chunkReference != null) { - Store chunkStore = chunkReference.getStore(); - BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkReference, BlockComponentChunk.getComponentType()); - - assert blockComponentChunk != null; - - int blockIndex = ChunkUtil.indexBlockInColumn(pos.x, pos.y, pos.z); - Ref blockRef = blockComponentChunk.getEntityReference(blockIndex); - if (blockRef == null || !blockRef.isValid()) { - Holder holder = ChunkStore.REGISTRY.newHolder(); - holder.putComponent(BlockModule.BlockStateInfo.getComponentType(), new BlockModule.BlockStateInfo(blockIndex, chunkReference)); - holder.ensureComponent(RespawnBlock.getComponentType()); - blockRef = chunkStore.addEntity(holder, AddReason.SPAWN); - } - - if (blockRef != null && blockRef.isValid()) { - RespawnBlock respawnBlockComponent = chunkStore.getComponent(blockRef, RespawnBlock.getComponentType()); - if (respawnBlockComponent != null) { - UUID ownerUUID = respawnBlockComponent.getOwnerUUID(); - PageManager pageManager = player.getPageManager(); - boolean isOwner = playerUuid.equals(ownerUUID); - if (isOwner) { - BlockPosition targetBlockPosition = context.getMetaStore().getMetaObject(TARGET_BLOCK_RAW); - Vector3f whereWasHit = new Vector3f(targetBlockPosition.x + 0.5F, targetBlockPosition.y + 0.5F, targetBlockPosition.z + 0.5F); - BlockMountAPI.BlockMountResult result = BlockMountAPI.mountOnBlock(ref, commandBuffer, pos, whereWasHit); - if (result instanceof BlockMountAPI.DidNotMount) { - player.sendMessage(Message.translation("server.interactions.didNotMount").param("state", result.toString())); - } else if (result instanceof BlockMountAPI.Mounted) { - commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.NoddingOff.createComponent()); + if (playerRefComponent != null) { + UUIDComponent playerUuidComponent = commandBuffer.getComponent(ref, UUIDComponent.getComponentType()); + if (playerUuidComponent != null) { + UUID playerUuid = playerUuidComponent.getUuid(); + long chunkIndex = ChunkUtil.indexChunkFromBlock(pos.x, pos.z); + Ref chunkRef = world.getChunkStore().getChunkReference(chunkIndex); + if (chunkRef != null && chunkRef.isValid()) { + Store chunkStore = chunkRef.getStore(); + BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkRef, BlockComponentChunk.getComponentType()); + if (blockComponentChunk != null) { + int blockIndex = ChunkUtil.indexBlockInColumn(pos.x, pos.y, pos.z); + Ref blockRef = blockComponentChunk.getEntityReference(blockIndex); + if (blockRef == null || !blockRef.isValid()) { + Holder holder = ChunkStore.REGISTRY.newHolder(); + holder.putComponent(BlockModule.BlockStateInfo.getComponentType(), new BlockModule.BlockStateInfo(blockIndex, chunkRef)); + holder.ensureComponent(RespawnBlock.getComponentType()); + blockRef = chunkStore.addEntity(holder, AddReason.SPAWN); } - } else if (ownerUUID != null) { - player.sendMessage(MESSAGE_SERVER_CUSTOM_UI_RESPAWN_POINT_CLAIMED); - } else { - PlayerRespawnPointData[] respawnPoints = player.getPlayerConfigData().getPerWorldData(world.getName()).getRespawnPoints(); - RespawnConfig respawnConfig = world.getGameplayConfig().getRespawnConfig(); - int radiusLimitRespawnPoint = respawnConfig.getRadiusLimitRespawnPoint(); - PlayerRespawnPointData[] nearbyRespawnPoints = getNearbySavedRespawnPoints(pos, respawnPoints, radiusLimitRespawnPoint); - if (nearbyRespawnPoints != null) { - pageManager.openCustomPage( - ref, - store, - new OverrideNearbyRespawnPointPage( - playerRefComponent, type, pos, respawnBlockComponent, nearbyRespawnPoints, radiusLimitRespawnPoint - ) - ); - } else if (respawnPoints != null && respawnPoints.length >= respawnConfig.getMaxRespawnPointsPerPlayer()) { - pageManager.openCustomPage( - ref, store, new SelectOverrideRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent, respawnPoints) - ); - } else { - pageManager.openCustomPage(ref, store, new SetNameRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent)); + + if (blockRef != null && blockRef.isValid()) { + RespawnBlock respawnBlockComponent = chunkStore.getComponent(blockRef, RespawnBlock.getComponentType()); + if (respawnBlockComponent != null) { + UUID ownerUUID = respawnBlockComponent.getOwnerUUID(); + PageManager pageManager = playerComponent.getPageManager(); + boolean isOwner = playerUuid.equals(ownerUUID); + if (isOwner) { + BlockPosition targetBlockPosition = context.getMetaStore().getMetaObject(TARGET_BLOCK_RAW); + Vector3f whereWasHit = new Vector3f(targetBlockPosition.x + 0.5F, targetBlockPosition.y + 0.5F, targetBlockPosition.z + 0.5F); + BlockMountAPI.BlockMountResult result = BlockMountAPI.mountOnBlock(ref, commandBuffer, pos, whereWasHit); + if (result instanceof BlockMountAPI.DidNotMount) { + playerComponent.sendMessage(Message.translation("server.interactions.didNotMount").param("state", result.toString())); + } else if (result instanceof BlockMountAPI.Mounted) { + commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.NoddingOff.createComponent()); + commandBuffer.run(s -> SleepNotificationSystem.maybeDoNotification(s, false)); + } + } else if (ownerUUID != null) { + playerComponent.sendMessage(MESSAGE_SERVER_CUSTOM_UI_RESPAWN_POINT_CLAIMED); + } else { + PlayerRespawnPointData[] respawnPoints = playerComponent.getPlayerConfigData() + .getPerWorldData(world.getName()) + .getRespawnPoints(); + RespawnConfig respawnConfig = world.getGameplayConfig().getRespawnConfig(); + int radiusLimitRespawnPoint = respawnConfig.getRadiusLimitRespawnPoint(); + PlayerRespawnPointData[] nearbyRespawnPoints = getNearbySavedRespawnPoints(pos, respawnPoints, radiusLimitRespawnPoint); + if (nearbyRespawnPoints != null) { + pageManager.openCustomPage( + ref, + store, + new OverrideNearbyRespawnPointPage( + playerRefComponent, type, pos, respawnBlockComponent, nearbyRespawnPoints, radiusLimitRespawnPoint + ) + ); + } else if (respawnPoints != null && respawnPoints.length >= respawnConfig.getMaxRespawnPointsPerPlayer()) { + pageManager.openCustomPage( + ref, store, new SelectOverrideRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent, respawnPoints) + ); + } else { + pageManager.openCustomPage(ref, store, new SetNameRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent)); + } + } + } } } } diff --git a/src/com/hypixel/hytale/builtin/beds/respawn/OverrideNearbyRespawnPointPage.java b/src/com/hypixel/hytale/builtin/beds/respawn/OverrideNearbyRespawnPointPage.java index eb8a1f50..c0f995b6 100644 --- a/src/com/hypixel/hytale/builtin/beds/respawn/OverrideNearbyRespawnPointPage.java +++ b/src/com/hypixel/hytale/builtin/beds/respawn/OverrideNearbyRespawnPointPage.java @@ -50,37 +50,38 @@ public class OverrideNearbyRespawnPointPage extends RespawnPointPage { ) { commandBuilder.append("Pages/OverrideNearbyRespawnPointPage.ui"); HeadRotation headRotationComponent = store.getComponent(ref, HeadRotation.getComponentType()); + if (headRotationComponent != null) { + PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType()); + if (playerRefComponent != null) { + double direction = Math.toDegrees(headRotationComponent.getRotation().getYaw()); + commandBuilder.set( + "#DescriptionLabel.Text", + Message.translation("server.customUI.overrideNearbyRespawnPoint.label") + .param("respawnPointCount", this.nearbyRespawnPoints.length) + .param("minDistance", this.radiusLimitRespawnPoint) + ); - assert headRotationComponent != null; + for (int i = 0; i < this.nearbyRespawnPoints.length; i++) { + String selector = "#RespawnPointList[" + i + "]"; + PlayerRespawnPointData nearbyRespawnPoint = this.nearbyRespawnPoints[i]; + commandBuilder.append("#RespawnPointList", "Pages/OverrideRespawnPointButton.ui"); + commandBuilder.set(selector + ".Disabled", true); + commandBuilder.set(selector + " #Name.Text", nearbyRespawnPoint.getName()); + Vector3i nearbyRespawnPointPosition = nearbyRespawnPoint.getBlockPosition(); + int distance = (int)this.respawnPointPosition + .distanceTo(nearbyRespawnPointPosition.x, this.respawnPointPosition.y, nearbyRespawnPointPosition.z); + commandBuilder.set(selector + " #Distance.Text", Message.translation("server.customUI.respawnPointDistance").param("distance", distance)); + double angle = Math.atan2(nearbyRespawnPointPosition.z - this.respawnPointPosition.z, nearbyRespawnPointPosition.x - this.respawnPointPosition.x); + commandBuilder.set(selector + " #Icon.Angle", Math.toDegrees(angle) + direction + 90.0); + } - PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType()); - - assert playerRefComponent != null; - - double direction = Math.toDegrees(headRotationComponent.getRotation().getYaw()); - commandBuilder.set( - "#DescriptionLabel.Text", - Message.translation("server.customUI.overrideNearbyRespawnPoint.label") - .param("respawnPointCount", this.nearbyRespawnPoints.length) - .param("minDistance", this.radiusLimitRespawnPoint) - ); - - for (int i = 0; i < this.nearbyRespawnPoints.length; i++) { - String selector = "#RespawnPointList[" + i + "]"; - PlayerRespawnPointData nearbyRespawnPoint = this.nearbyRespawnPoints[i]; - commandBuilder.append("#RespawnPointList", "Pages/OverrideRespawnPointButton.ui"); - commandBuilder.set(selector + ".Disabled", true); - commandBuilder.set(selector + " #Name.Text", nearbyRespawnPoint.getName()); - Vector3i nearbyRespawnPointPosition = nearbyRespawnPoint.getBlockPosition(); - int distance = (int)this.respawnPointPosition.distanceTo(nearbyRespawnPointPosition.x, this.respawnPointPosition.y, nearbyRespawnPointPosition.z); - commandBuilder.set(selector + " #Distance.Text", Message.translation("server.customUI.respawnPointDistance").param("distance", distance)); - double angle = Math.atan2(nearbyRespawnPointPosition.z - this.respawnPointPosition.z, nearbyRespawnPointPosition.x - this.respawnPointPosition.x); - commandBuilder.set(selector + " #Icon.Angle", Math.toDegrees(angle) + direction + 90.0); + commandBuilder.set( + "#NameInput.Value", Message.translation("server.customUI.defaultRespawnPointName").param("name", playerRefComponent.getUsername()) + ); + eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#ConfirmButton", EventData.of("@RespawnPointName", "#NameInput.Value")); + eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#CancelButton", EventData.of("Action", "Cancel")); + } } - - commandBuilder.set("#NameInput.Value", Message.translation("server.customUI.defaultRespawnPointName").param("name", playerRefComponent.getUsername())); - eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#ConfirmButton", EventData.of("@RespawnPointName", "#NameInput.Value")); - eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#CancelButton", EventData.of("Action", "Cancel")); } public void handleDataEvent(@Nonnull Ref ref, @Nonnull Store store, @Nonnull RespawnPointPage.RespawnPointEventData data) { diff --git a/src/com/hypixel/hytale/builtin/beds/respawn/RespawnPointPage.java b/src/com/hypixel/hytale/builtin/beds/respawn/RespawnPointPage.java index f8cedf57..4042c536 100644 --- a/src/com/hypixel/hytale/builtin/beds/respawn/RespawnPointPage.java +++ b/src/com/hypixel/hytale/builtin/beds/respawn/RespawnPointPage.java @@ -65,48 +65,47 @@ public abstract class RespawnPointPage extends InteractiveCustomUIPage ref, @Nonnull Store store, @Nonnull RespawnPointPage.RespawnPointEventData data) { diff --git a/src/com/hypixel/hytale/builtin/beds/respawn/SetNameRespawnPointPage.java b/src/com/hypixel/hytale/builtin/beds/respawn/SetNameRespawnPointPage.java index 40d11400..91851d03 100644 --- a/src/com/hypixel/hytale/builtin/beds/respawn/SetNameRespawnPointPage.java +++ b/src/com/hypixel/hytale/builtin/beds/respawn/SetNameRespawnPointPage.java @@ -38,33 +38,33 @@ public class SetNameRespawnPointPage extends RespawnPointPage { ) { commandBuilder.append("Pages/NameRespawnPointPage.ui"); Player playerComponent = store.getComponent(ref, Player.getComponentType()); - - assert playerComponent != null; - - PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType()); - - assert playerRefComponent != null; - - World world = store.getExternalData().getWorld(); - PlayerRespawnPointData[] respawnPoints = playerComponent.getPlayerConfigData().getPerWorldData(world.getName()).getRespawnPoints(); - String respawnPointName = null; - if (respawnPoints != null) { - for (PlayerRespawnPointData respawnPoint : respawnPoints) { - if (respawnPoint.getBlockPosition().equals(this.respawnBlockPosition)) { - respawnPointName = respawnPoint.getName(); - break; + if (playerComponent != null) { + PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType()); + if (playerRefComponent != null) { + World world = store.getExternalData().getWorld(); + PlayerRespawnPointData[] respawnPoints = playerComponent.getPlayerConfigData().getPerWorldData(world.getName()).getRespawnPoints(); + String respawnPointName = null; + if (respawnPoints != null) { + for (PlayerRespawnPointData respawnPoint : respawnPoints) { + if (respawnPoint.getBlockPosition().equals(this.respawnBlockPosition)) { + respawnPointName = respawnPoint.getName(); + break; + } + } } + + if (respawnPointName == null) { + commandBuilder.set( + "#NameInput.Value", Message.translation("server.customUI.defaultRespawnPointName").param("name", playerRefComponent.getUsername()) + ); + } else { + commandBuilder.set("#NameInput.Value", respawnPointName); + } + + eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#SetButton", EventData.of("@RespawnPointName", "#NameInput.Value")); + eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#CancelButton", EventData.of("Action", "Cancel")); } } - - if (respawnPointName == null) { - commandBuilder.set("#NameInput.Value", Message.translation("server.customUI.defaultRespawnPointName").param("name", playerRefComponent.getUsername())); - } else { - commandBuilder.set("#NameInput.Value", respawnPointName); - } - - eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#SetButton", EventData.of("@RespawnPointName", "#NameInput.Value")); - eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#CancelButton", EventData.of("Action", "Cancel")); } public void handleDataEvent(@Nonnull Ref ref, @Nonnull Store store, @Nonnull RespawnPointPage.RespawnPointEventData data) { diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/components/PlayerSleep.java b/src/com/hypixel/hytale/builtin/beds/sleep/components/PlayerSleep.java index 68b35e8a..d2e1d61e 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/components/PlayerSleep.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/components/PlayerSleep.java @@ -1,21 +1,33 @@ package com.hypixel.hytale.builtin.beds.sleep.components; import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; +import java.time.Duration; import java.time.Instant; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public sealed interface PlayerSleep permits PlayerSleep.FullyAwake, PlayerSleep.MorningWakeUp, PlayerSleep.NoddingOff, PlayerSleep.Slumber { public static enum FullyAwake implements PlayerSleep { INSTANCE; } - public record MorningWakeUp(Instant gameTimeStart) implements PlayerSleep { + public record MorningWakeUp(@Nullable Instant gameTimeStart) implements PlayerSleep { + private static final Duration WAKE_UP_AUTOSLEEP_DELAY = Duration.ofHours(1L); + @Nonnull - public static PlayerSomnolence createComponent(@Nonnull WorldTimeResource worldTimeResource) { - Instant now = worldTimeResource.getGameTime(); - PlayerSleep.MorningWakeUp state = new PlayerSleep.MorningWakeUp(now); + public static PlayerSomnolence createComponent(@Nullable Instant gameTimeStart) { + PlayerSleep.MorningWakeUp state = new PlayerSleep.MorningWakeUp(gameTimeStart); return new PlayerSomnolence(state); } + + public boolean isReadyToSleepAgain(Instant worldTime) { + if (this.gameTimeStart == null) { + return true; + } else { + Instant readyTime = worldTime.plus(WAKE_UP_AUTOSLEEP_DELAY); + return worldTime.isAfter(readyTime); + } + } } public record NoddingOff(Instant realTimeStart) implements PlayerSleep { diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/resources/WorldSomnolence.java b/src/com/hypixel/hytale/builtin/beds/sleep/resources/WorldSomnolence.java index d1e63e53..ed5af286 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/resources/WorldSomnolence.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/resources/WorldSomnolence.java @@ -10,6 +10,7 @@ import javax.annotation.Nullable; public class WorldSomnolence implements Resource { @Nonnull private WorldSleep state = WorldSleep.Awake.INSTANCE; + private long lastSleepNotification; public static ResourceType getResourceType() { return BedsPlugin.getInstance().getWorldSomnolenceResourceType(); @@ -24,6 +25,21 @@ public class WorldSomnolence implements Resource { this.state = state; } + public boolean useSleepNotificationCooldown(long now, long cooldownMs) { + long elapsedMs = now - this.lastSleepNotification; + boolean ready = elapsedMs >= cooldownMs; + if (ready) { + this.lastSleepNotification = now; + return true; + } else { + return false; + } + } + + public void resetNotificationCooldown() { + this.lastSleepNotification = 0L; + } + @Nullable @Override public Resource clone() { diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/EnterBedSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/EnterBedSystem.java index 4978a52d..a92d8dbc 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/EnterBedSystem.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/EnterBedSystem.java @@ -9,9 +9,11 @@ import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.RefChangeSystem; import com.hypixel.hytale.protocol.BlockMountType; +import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.server.core.Message; -import com.hypixel.hytale.server.core.asset.type.gameplay.SleepConfig; +import com.hypixel.hytale.server.core.asset.type.gameplay.sleep.SleepConfig; import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.SoundUtil; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.time.Duration; @@ -28,23 +30,36 @@ public class EnterBedSystem extends RefChangeSystem QUERY = Query.and(MountedComponent.getComponentType(), PlayerRef.getComponentType()); + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final Query query; + + public EnterBedSystem( + @Nonnull ComponentType mountedComponentType, @Nonnull ComponentType playerRefComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.playerRefComponentType = playerRefComponentType; + this.query = Query.and(mountedComponentType, playerRefComponentType); + } @Nonnull @Override public ComponentType componentType() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } public void onComponentAdded( @Nonnull Ref ref, @Nonnull MountedComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - check(ref, component, store); + check(ref, component, store, this.playerRefComponentType); } public void onComponentSet( @@ -54,7 +69,7 @@ public class EnterBedSystem extends RefChangeSystem store, @Nonnull CommandBuffer commandBuffer ) { - check(ref, newComponent, store); + check(ref, newComponent, store, this.playerRefComponentType); } public void onComponentRemoved( @@ -62,30 +77,38 @@ public class EnterBedSystem extends RefChangeSystem ref, @Nonnull MountedComponent component, @Nonnull Store store) { + private static void check( + @Nonnull Ref ref, + @Nonnull MountedComponent component, + @Nonnull Store store, + @Nonnull ComponentType playerRefComponentType + ) { if (component.getBlockMountType() == BlockMountType.Bed) { - onEnterBed(ref, store); + onEnterBed(ref, store, playerRefComponentType); } } - public static void onEnterBed(@Nonnull Ref ref, @Nonnull Store store) { + private static void onEnterBed( + @Nonnull Ref ref, @Nonnull Store store, @Nonnull ComponentType playerRefComponentType + ) { World world = store.getExternalData().getWorld(); CanSleepInWorld.Result canSleepResult = CanSleepInWorld.check(world); if (canSleepResult.isNegative()) { - PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType()); + PlayerRef playerRefComponent = store.getComponent(ref, playerRefComponentType); - assert playerRef != null; + assert playerRefComponent != null; - if (canSleepResult instanceof CanSleepInWorld.NotDuringSleepHoursRange(LocalDateTime msg, SleepConfig var13)) { - LocalTime startTime = var13.getSleepStartTime(); - Duration untilSleep = var13.computeDurationUntilSleep(msg); + if (canSleepResult instanceof CanSleepInWorld.NotDuringSleepHoursRange(LocalDateTime msg, SleepConfig var14)) { + LocalTime startTime = var14.getSleepStartTime(); + Duration untilSleep = var14.computeDurationUntilSleep(msg); Message msgx = Message.translation("server.interactions.sleep.sleepAtTheseHours") .param("timeValue", startTime.toString()) .param("until", formatDuration(untilSleep)); - playerRef.sendMessage(msgx.color("#F2D729")); + playerRefComponent.sendMessage(msgx.color("#F2D729")); + SoundUtil.playSoundEvent2dToPlayer(playerRefComponent, var14.getSounds().getFailIndex(), SoundCategory.UI); } else { Message msg = getMessage(canSleepResult); - playerRef.sendMessage(msg); + playerRefComponent.sendMessage(msg); } } } diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/RegisterTrackerSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/RegisterTrackerSystem.java index c025cf68..8d2caba5 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/RegisterTrackerSystem.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/RegisterTrackerSystem.java @@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.beds.sleep.systems.player; import com.hypixel.hytale.builtin.beds.sleep.components.SleepTracker; import com.hypixel.hytale.component.AddReason; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.RemoveReason; import com.hypixel.hytale.component.Store; @@ -10,21 +11,32 @@ import com.hypixel.hytale.component.system.HolderSystem; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class RegisterTrackerSystem extends HolderSystem { + @Nonnull + private final ComponentType sleepTrackerComponentType; + @Nonnull + private final Query query; + + public RegisterTrackerSystem( + @Nonnull ComponentType playerRefComponentType, @Nonnull ComponentType sleepTrackerComponentType + ) { + this.sleepTrackerComponentType = sleepTrackerComponentType; + this.query = playerRefComponentType; + } + @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - holder.ensureComponent(SleepTracker.getComponentType()); + holder.ensureComponent(this.sleepTrackerComponentType); } @Override public void onEntityRemoved(@Nonnull Holder holder, @Nonnull RemoveReason reason, @Nonnull Store store) { } - @Nullable + @Nonnull @Override public Query getQuery() { - return PlayerRef.getComponentType(); + return this.query; } } diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/SleepNotificationSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/SleepNotificationSystem.java new file mode 100644 index 00000000..97113818 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/SleepNotificationSystem.java @@ -0,0 +1,174 @@ +package com.hypixel.hytale.builtin.beds.sleep.systems.player; + +import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSomnolence; +import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSleep; +import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSlumber; +import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSomnolence; +import com.hypixel.hytale.builtin.beds.sleep.systems.world.CanSleepInWorld; +import com.hypixel.hytale.builtin.beds.sleep.systems.world.StartSlumberSystem; +import com.hypixel.hytale.component.ComponentAccessor; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.component.system.DelayedSystem; +import com.hypixel.hytale.protocol.SoundCategory; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.asset.type.gameplay.sleep.SleepSoundsConfig; +import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.SoundUtil; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.compatqual.NonNullDecl; + +public class SleepNotificationSystem extends DelayedSystem { + public static final int SMALL_SERVER_PLAYER_COUNT = 4; + public static final double BIG_SERVER_SLEEPERS_RATIO = 0.5; + public static final String COLOR = "#5AB5B5"; + + public SleepNotificationSystem() { + super(1.0F); + } + + @Override + public void delayedTick(float dt, int systemIndex, @NonNullDecl Store store) { + World world = store.getExternalData().getWorld(); + SleepSoundsConfig sleepSounds = world.getGameplayConfig().getWorldConfig().getSleepConfig().getSounds(); + if (sleepSounds.isNotificationLoopEnabled()) { + maybeDoNotification(store, true); + } + } + + public static void maybeDoNotification(Store store, boolean fromAutoLoop) { + World world = store.getExternalData().getWorld(); + SleepSoundsConfig sleepSounds = world.getGameplayConfig().getWorldConfig().getSleepConfig().getSounds(); + SleepNotificationSystem.NotificationState state = getNotificationState(world); + if (state != SleepNotificationSystem.NotReady.INSTANCE) { + long now = System.currentTimeMillis(); + WorldSomnolence worldSomnolence = store.getResource(WorldSomnolence.getResourceType()); + if (worldSomnolence.useSleepNotificationCooldown(now, sleepSounds.getNotificationLoopCooldownMs())) { + int soundIndex = fromAutoLoop ? sleepSounds.getNotificationLoopIndex() : sleepSounds.getNotificationIndex(); + Collection playerRefs = world.getPlayerRefs(); + + for (PlayerRef playerRef : playerRefs) { + Ref ref = playerRef.getReference(); + if (ref != null && !StartSlumberSystem.canNotifyOthersAboutTryingToSleep(store, ref)) { + SoundUtil.playSoundEvent2dToPlayer(playerRef, soundIndex, SoundCategory.UI); + if (state instanceof SleepNotificationSystem.SmallServer) { + if (state.readyToSleep() == 1) { + Message sleeperName = playerRefs.stream() + .map(PlayerRef::getReference) + .filter(r -> StartSlumberSystem.canNotifyOthersAboutTryingToSleep(store, (Ref)r)) + .map(SleepNotificationSystem::getSleeperName) + .findFirst() + .orElseGet(() -> Message.raw("???")); + String msgKey = fromAutoLoop ? "server.interactions.sleep.notificationSingle" : "server.interactions.sleep.notificationSingleEnter"; + playerRef.sendMessage(Message.translation(msgKey).color("#5AB5B5").param("player", sleeperName)); + } else { + playerRef.sendMessage( + Message.translation("server.interactions.sleep.notificationSmall").color("#5AB5B5").param("sleepers", state.readyToSleep()) + ); + } + } else if (state instanceof SleepNotificationSystem.BigServer) { + playerRef.sendMessage( + Message.translation("server.interactions.sleep.notificationBig") + .color("#5AB5B5") + .param("sleepers", state.readyToSleep()) + .param("total", state.playerCount()) + ); + } + } + } + } + } + } + + private static SleepNotificationSystem.NotificationState getNotificationState(World world) { + if (CanSleepInWorld.check(world).isNegative()) { + return SleepNotificationSystem.NotReady.INSTANCE; + } else { + Store store = world.getEntityStore().getStore(); + WorldSleep worldSleep = store.getResource(WorldSomnolence.getResourceType()).getState(); + if (worldSleep instanceof WorldSlumber) { + return SleepNotificationSystem.NotReady.INSTANCE; + } else { + List> refs = world.getPlayerRefs().stream().map(PlayerRef::getReference).filter(Objects::nonNull).toList(); + int playerCount = refs.size(); + int readyToSleep = countReadyToSleep(refs, store); + if (playerCount <= 4) { + boolean ready = readyToSleep > 0; + return (SleepNotificationSystem.NotificationState)(ready + ? new SleepNotificationSystem.SmallServer(readyToSleep, playerCount) + : SleepNotificationSystem.NotReady.INSTANCE); + } else { + double sleepersRatio = (double)readyToSleep / playerCount; + boolean ready = sleepersRatio >= 0.5; + return (SleepNotificationSystem.NotificationState)(ready + ? new SleepNotificationSystem.BigServer(sleepersRatio, readyToSleep, playerCount) + : SleepNotificationSystem.NotReady.INSTANCE); + } + } + } + } + + private static int countReadyToSleep(Collection> playerRefs, ComponentAccessor store) { + int count = 0; + + for (Ref ref : playerRefs) { + PlayerSomnolence somnolence = store.getComponent(ref, PlayerSomnolence.getComponentType()); + if (somnolence != null) { + boolean readyToSleep = StartSlumberSystem.canNotifyOthersAboutTryingToSleep(store, ref); + if (readyToSleep) { + count++; + } + } + } + + return count; + } + + public static Message getSleeperName(@Nullable Ref ref) { + if (ref != null && ref.isValid()) { + Store store = ref.getStore(); + DisplayNameComponent displayNameComponent = store.getComponent(ref, DisplayNameComponent.getComponentType()); + Message lastSleeperDisplay = displayNameComponent == null ? null : displayNameComponent.getDisplayName(); + if (lastSleeperDisplay != null) { + return lastSleeperDisplay; + } else { + PlayerRef sleeperPlayerRef = store.getComponent(ref, PlayerRef.getComponentType()); + return Message.raw(sleeperPlayerRef == null ? "???" : sleeperPlayerRef.getUsername()); + } + } else { + return Message.raw("???"); + } + } + + private record BigServer(double ratio, int readyToSleep, int playerCount) implements SleepNotificationSystem.NotificationState { + } + + private static enum NotReady implements SleepNotificationSystem.NotificationState { + INSTANCE; + + @Override + public int readyToSleep() { + return 0; + } + + @Override + public int playerCount() { + return 0; + } + } + + private sealed interface NotificationState permits SleepNotificationSystem.NotReady, SleepNotificationSystem.SmallServer, SleepNotificationSystem.BigServer { + int readyToSleep(); + + int playerCount(); + } + + private record SmallServer(int readyToSleep, int playerCount) implements SleepNotificationSystem.NotificationState { + } +} diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/UpdateSleepPacketSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/UpdateSleepPacketSystem.java index 96155ca3..86d14be3 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/UpdateSleepPacketSystem.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/UpdateSleepPacketSystem.java @@ -10,13 +10,16 @@ import com.hypixel.hytale.builtin.beds.sleep.systems.world.CanSleepInWorld; import com.hypixel.hytale.builtin.beds.sleep.systems.world.StartSlumberSystem; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.tick.DelayedEntitySystem; import com.hypixel.hytale.protocol.packets.world.SleepClock; import com.hypixel.hytale.protocol.packets.world.SleepMultiplayer; import com.hypixel.hytale.protocol.packets.world.UpdateSleepState; +import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; @@ -30,23 +33,47 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class UpdateSleepPacketSystem extends DelayedEntitySystem { + private static final int MAX_SAMPLE_COUNT = 5; + private static final float SYSTEM_INTERVAL_S = 0.25F; @Nonnull - public static final Query QUERY = Query.and(PlayerRef.getComponentType(), PlayerSomnolence.getComponentType(), SleepTracker.getComponentType()); - public static final Duration SPAN_BEFORE_BLACK_SCREEN = Duration.ofMillis(1200L); - public static final int MAX_SAMPLE_COUNT = 5; + private static final Duration SPAN_BEFORE_BLACK_SCREEN = Duration.ofMillis(1200L); @Nonnull private static final UUID[] EMPTY_UUIDS = new UUID[0]; @Nonnull private static final UpdateSleepState PACKET_NO_SLEEP_UI = new UpdateSleepState(false, false, null, null); - private static final float SYSTEM_INTERVAL_S = 0.25F; + @Nonnull + private final ComponentType playerRefComponentType; + @Nonnull + private final ComponentType playerSomnolenceComponentType; + @Nonnull + private final ComponentType sleepTrackerComponentType; + @Nonnull + private final ResourceType worldSomnolenceResourceType; + @Nonnull + private final ResourceType worldTimeResourceType; + @Nonnull + private final Query query; - @Override - public Query getQuery() { - return QUERY; + public UpdateSleepPacketSystem( + @Nonnull ComponentType playerRefComponentType, + @Nonnull ComponentType playerSomnolenceComponentType, + @Nonnull ComponentType sleepTrackerComponentType, + @Nonnull ResourceType worldSomnolenceResourceType, + @Nonnull ResourceType worldTimeResourceType + ) { + super(0.25F); + this.playerRefComponentType = playerRefComponentType; + this.playerSomnolenceComponentType = playerSomnolenceComponentType; + this.sleepTrackerComponentType = sleepTrackerComponentType; + this.worldSomnolenceResourceType = worldSomnolenceResourceType; + this.worldTimeResourceType = worldTimeResourceType; + this.query = Query.and(playerRefComponentType, playerSomnolenceComponentType, sleepTrackerComponentType); } - public UpdateSleepPacketSystem() { - super(0.25F); + @Nonnull + @Override + public Query getQuery() { + return this.query; } @Override @@ -58,13 +85,13 @@ public class UpdateSleepPacketSystem extends DelayedEntitySystem { @Nonnull CommandBuffer commandBuffer ) { UpdateSleepState packet = this.createSleepPacket(store, index, archetypeChunk); - SleepTracker sleepTrackerComponent = archetypeChunk.getComponent(index, SleepTracker.getComponentType()); + SleepTracker sleepTrackerComponent = archetypeChunk.getComponent(index, this.sleepTrackerComponentType); assert sleepTrackerComponent != null; packet = sleepTrackerComponent.generatePacketToSend(packet); if (packet != null) { - PlayerRef playerRefComponent = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); + PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType); assert playerRefComponent != null; @@ -75,9 +102,9 @@ public class UpdateSleepPacketSystem extends DelayedEntitySystem { @Nonnull private UpdateSleepState createSleepPacket(@Nonnull Store store, int index, @Nonnull ArchetypeChunk archetypeChunk) { World world = store.getExternalData().getWorld(); - WorldSomnolence worldSomnolence = store.getResource(WorldSomnolence.getResourceType()); - WorldSleep worldSleepState = worldSomnolence.getState(); - PlayerSomnolence playerSomnolenceComponent = archetypeChunk.getComponent(index, PlayerSomnolence.getComponentType()); + WorldSomnolence worldSomnolenceResource = store.getResource(this.worldSomnolenceResourceType); + WorldSleep worldSleepState = worldSomnolenceResource.getState(); + PlayerSomnolence playerSomnolenceComponent = archetypeChunk.getComponent(index, this.playerSomnolenceComponentType); assert playerSomnolenceComponent != null; @@ -118,12 +145,14 @@ public class UpdateSleepPacketSystem extends DelayedEntitySystem { for (PlayerRef playerRef : playerRefs) { Ref ref = playerRef.getReference(); - boolean readyToSleep = StartSlumberSystem.isReadyToSleep(store, ref); - if (readyToSleep) { - sleepersCount++; - } else { - awakeCount++; - awakeSampleList.add(playerRef.getUuid()); + if (ref != null && ref.isValid()) { + boolean readyToSleep = StartSlumberSystem.isReadyToSleep(store, ref); + if (readyToSleep) { + sleepersCount++; + } else { + awakeCount++; + awakeSampleList.add(playerRef.getUuid()); + } } } diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/WakeUpOnDismountSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/WakeUpOnDismountSystem.java index d0472652..b4433919 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/WakeUpOnDismountSystem.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/player/WakeUpOnDismountSystem.java @@ -15,14 +15,28 @@ import javax.annotation.Nullable; public class WakeUpOnDismountSystem extends RefChangeSystem { @Nonnull - @Override - public ComponentType componentType() { - return MountedComponent.getComponentType(); + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType playerSomnolenceComponentType; + + public WakeUpOnDismountSystem( + @Nonnull ComponentType mountedComponentType, + @Nonnull ComponentType playerSomnolenceComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.playerSomnolenceComponentType = playerSomnolenceComponentType; } + @Nonnull + @Override + public ComponentType componentType() { + return this.mountedComponentType; + } + + @Nonnull @Override public Query getQuery() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } public void onComponentAdded( @@ -43,7 +57,7 @@ public class WakeUpOnDismountSystem extends RefChangeSystem ref, @Nonnull MountedComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { if (component.getBlockMountType() == BlockMountType.Bed) { - commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSomnolence.AWAKE); + commandBuffer.putComponent(ref, this.playerSomnolenceComponentType, PlayerSomnolence.AWAKE); } } } diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/CanSleepInWorld.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/CanSleepInWorld.java index 67af7cf3..5ff3f9ef 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/CanSleepInWorld.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/CanSleepInWorld.java @@ -1,7 +1,7 @@ package com.hypixel.hytale.builtin.beds.sleep.systems.world; import com.hypixel.hytale.component.Store; -import com.hypixel.hytale.server.core.asset.type.gameplay.SleepConfig; +import com.hypixel.hytale.server.core.asset.type.gameplay.sleep.SleepConfig; import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/StartSlumberSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/StartSlumberSystem.java index c0bdc569..a51981c5 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/StartSlumberSystem.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/StartSlumberSystem.java @@ -6,11 +6,16 @@ import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSleep; import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSlumber; import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSomnolence; import com.hypixel.hytale.component.ComponentAccessor; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.system.DelayedSystem; +import com.hypixel.hytale.protocol.SoundCategory; +import com.hypixel.hytale.server.core.asset.type.gameplay.sleep.SleepConfig; import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.SoundUtil; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.time.Duration; @@ -20,6 +25,7 @@ import java.time.ZoneOffset; import java.util.Collection; import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class StartSlumberSystem extends DelayedSystem { @Nonnull @@ -27,9 +33,22 @@ public class StartSlumberSystem extends DelayedSystem { @Nonnull private static final Duration WAKE_UP_AUTOSLEEP_DELAY = Duration.ofHours(1L); private static final float SYSTEM_INTERVAL_S = 0.3F; + @Nonnull + private final ComponentType playerSomnolenceComponentType; + @Nonnull + private final ResourceType worldSomnolenceResourceType; + @Nonnull + private final ResourceType worldTimeResourceType; - public StartSlumberSystem() { + public StartSlumberSystem( + @Nonnull ComponentType playerSomnolenceComponentType, + @Nonnull ResourceType worldSomnolenceResourceType, + @Nonnull ResourceType worldTimeResourceType + ) { super(0.3F); + this.playerSomnolenceComponentType = playerSomnolenceComponentType; + this.worldSomnolenceResourceType = worldSomnolenceResourceType; + this.worldTimeResourceType = worldTimeResourceType; } @Override @@ -42,20 +61,26 @@ public class StartSlumberSystem extends DelayedSystem { Collection playerRefs = world.getPlayerRefs(); if (!playerRefs.isEmpty()) { if (!CanSleepInWorld.check(world).isNegative()) { - float wakeUpHour = world.getGameplayConfig().getWorldConfig().getSleepConfig().getWakeUpHour(); - WorldSomnolence worldSomnolenceResource = store.getResource(WorldSomnolence.getResourceType()); + SleepConfig sleepConfig = world.getGameplayConfig().getWorldConfig().getSleepConfig(); + float wakeUpHour = sleepConfig.getWakeUpHour(); + WorldSomnolence worldSomnolenceResource = store.getResource(this.worldSomnolenceResourceType); WorldSleep worldState = worldSomnolenceResource.getState(); if (worldState == WorldSleep.Awake.INSTANCE) { - if (isEveryoneReadyToSleep(store)) { - WorldTimeResource timeResource = store.getResource(WorldTimeResource.getResourceType()); + if (this.isEveryoneReadyToSleep(store)) { + WorldTimeResource timeResource = store.getResource(this.worldTimeResourceType); Instant now = timeResource.getGameTime(); Instant target = this.computeWakeupInstant(now, wakeUpHour); float irlSeconds = computeIrlSeconds(now, target); worldSomnolenceResource.setState(new WorldSlumber(now, target, irlSeconds)); - store.forEachEntityParallel(PlayerSomnolence.getComponentType(), (index, archetypeChunk, commandBuffer) -> { + store.forEachEntityParallel(this.playerSomnolenceComponentType, (index, archetypeChunk, commandBuffer) -> { Ref ref = archetypeChunk.getReferenceTo(index); - commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.Slumber.createComponent(timeResource)); + commandBuffer.putComponent(ref, this.playerSomnolenceComponentType, PlayerSleep.Slumber.createComponent(timeResource)); + PlayerRef playerRef = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); + if (playerRef != null) { + SoundUtil.playSoundEvent2dToPlayer(playerRef, sleepConfig.getSounds().getSuccessIndex(), SoundCategory.UI); + } }); + worldSomnolenceResource.resetNotificationCooldown(); } } } @@ -81,7 +106,7 @@ public class StartSlumberSystem extends DelayedSystem { return (float)Math.ceil(seconds); } - private static boolean isEveryoneReadyToSleep(@Nonnull ComponentAccessor store) { + private boolean isEveryoneReadyToSleep(@Nonnull ComponentAccessor store) { World world = store.getExternalData().getWorld(); Collection playerRefs = world.getPlayerRefs(); if (playerRefs.isEmpty()) { @@ -98,31 +123,54 @@ public class StartSlumberSystem extends DelayedSystem { } } - public static boolean isReadyToSleep(@Nonnull ComponentAccessor store, @Nonnull Ref ref) { - if (!ref.isValid()) { - return true; - } else { - PlayerSomnolence somnolence = store.getComponent(ref, PlayerSomnolence.getComponentType()); - if (somnolence == null) { + public static boolean isReadyToSleep(@Nonnull ComponentAccessor store, @Nullable Ref ref) { + if (ref != null && ref.isValid()) { + PlayerSomnolence somnolenceComponent = store.getComponent(ref, PlayerSomnolence.getComponentType()); + if (somnolenceComponent == null) { return false; } else { - PlayerSleep sleepState = somnolence.getSleepState(); + PlayerSleep sleepState = somnolenceComponent.getSleepState(); return switch (sleepState) { - case PlayerSleep.FullyAwake ignored -> false; + case PlayerSleep.FullyAwake fullAwake -> false; case PlayerSleep.MorningWakeUp morningWakeUp -> { WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType()); - Instant readyTime = morningWakeUp.gameTimeStart().plus(WAKE_UP_AUTOSLEEP_DELAY); - yield worldTimeResource.getGameTime().isAfter(readyTime); + yield morningWakeUp.isReadyToSleepAgain(worldTimeResource.getGameTime()); } case PlayerSleep.NoddingOff noddingOff -> { Instant sleepStart = noddingOff.realTimeStart().plus(NODDING_OFF_DURATION); yield Instant.now().isAfter(sleepStart); } - case PlayerSleep.Slumber ignoredx -> true; + case PlayerSleep.Slumber ignored -> true; default -> throw new MatchException(null, null); }; } + } else { + return true; + } + } + + public static boolean canNotifyOthersAboutTryingToSleep(@Nonnull ComponentAccessor store, @Nullable Ref ref) { + if (ref != null && ref.isValid()) { + PlayerSomnolence somnolenceComponent = store.getComponent(ref, PlayerSomnolence.getComponentType()); + if (somnolenceComponent == null) { + return false; + } else { + PlayerSleep sleepState = somnolenceComponent.getSleepState(); + + return switch (sleepState) { + case PlayerSleep.FullyAwake fullAwake -> false; + case PlayerSleep.MorningWakeUp morningWakeUp -> { + WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType()); + yield morningWakeUp.isReadyToSleepAgain(worldTimeResource.getGameTime()); + } + case PlayerSleep.NoddingOff noddingOff -> true; + case PlayerSleep.Slumber ignored -> true; + default -> throw new MatchException(null, null); + }; + } + } else { + return true; } } } diff --git a/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/UpdateWorldSlumberSystem.java b/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/UpdateWorldSlumberSystem.java index 7e7c031f..640ee1d6 100644 --- a/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/UpdateWorldSlumberSystem.java +++ b/src/com/hypixel/hytale/builtin/beds/sleep/systems/world/UpdateWorldSlumberSystem.java @@ -6,7 +6,9 @@ import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSleep; import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSlumber; import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSomnolence; import com.hypixel.hytale.component.ComponentAccessor; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.system.tick.TickingSystem; import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; @@ -19,26 +21,47 @@ import java.util.Collection; import javax.annotation.Nonnull; public class UpdateWorldSlumberSystem extends TickingSystem { + @Nonnull + private final ComponentType playerSomnolenceComponentType; + @Nonnull + private final ResourceType worldSomnolenceResourceType; + @Nonnull + private final ResourceType worldTimeResourceType; + + public UpdateWorldSlumberSystem( + @Nonnull ComponentType playerSomnolenceComponentType, + @Nonnull ResourceType worldSomnolenceResourceType, + @Nonnull ResourceType worldTimeResourceType + ) { + this.playerSomnolenceComponentType = playerSomnolenceComponentType; + this.worldSomnolenceResourceType = worldSomnolenceResourceType; + this.worldTimeResourceType = worldTimeResourceType; + } + @Override public void tick(float dt, int systemIndex, @Nonnull Store store) { World world = store.getExternalData().getWorld(); - WorldSomnolence worldSomnolence = store.getResource(WorldSomnolence.getResourceType()); - if (worldSomnolence.getState() instanceof WorldSlumber slumber) { + WorldSomnolence worldSomnolenceResource = store.getResource(this.worldSomnolenceResourceType); + if (worldSomnolenceResource.getState() instanceof WorldSlumber slumber) { slumber.incrementProgressSeconds(dt); - boolean sleepingIsOver = slumber.getProgressSeconds() >= slumber.getIrlDurationSeconds() || isSomeoneAwake(store); + boolean itsMorningTimeToWAKEUP = slumber.getProgressSeconds() >= slumber.getIrlDurationSeconds(); + boolean someoneIsAwake = isSomeoneAwake(store, this.playerSomnolenceComponentType); + boolean sleepingIsOver = itsMorningTimeToWAKEUP || someoneIsAwake; if (sleepingIsOver) { - worldSomnolence.setState(WorldSleep.Awake.INSTANCE); - WorldTimeResource timeResource = store.getResource(WorldTimeResource.getResourceType()); + worldSomnolenceResource.setState(WorldSleep.Awake.INSTANCE); + WorldTimeResource timeResource = store.getResource(this.worldTimeResourceType); + Instant now = timeResource.getGameTime(); Instant wakeUpTime = computeWakeupTime(slumber); timeResource.setGameTime(wakeUpTime, world, store); - store.forEachEntityParallel(PlayerSomnolence.getComponentType(), (index, archetypeChunk, commandBuffer) -> { - PlayerSomnolence somnolenceComponent = archetypeChunk.getComponent(index, PlayerSomnolence.getComponentType()); + store.forEachEntityParallel(this.playerSomnolenceComponentType, (index, archetypeChunk, commandBuffer) -> { + PlayerSomnolence somnolenceComponent = archetypeChunk.getComponent(index, this.playerSomnolenceComponentType); assert somnolenceComponent != null; if (somnolenceComponent.getSleepState() instanceof PlayerSleep.Slumber) { Ref ref = archetypeChunk.getReferenceTo(index); - commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.MorningWakeUp.createComponent(timeResource)); + PlayerSomnolence sleepComponent = PlayerSleep.MorningWakeUp.createComponent(itsMorningTimeToWAKEUP ? now : null); + commandBuffer.putComponent(ref, this.playerSomnolenceComponentType, sleepComponent); } }); } @@ -53,7 +76,9 @@ public class UpdateWorldSlumberSystem extends TickingSystem { return slumber.getStartInstant().plusNanos(progressNanos); } - private static boolean isSomeoneAwake(@Nonnull ComponentAccessor store) { + private static boolean isSomeoneAwake( + @Nonnull ComponentAccessor store, @Nonnull ComponentType playerSomnolenceComponentType + ) { World world = store.getExternalData().getWorld(); Collection playerRefs = world.getPlayerRefs(); if (playerRefs.isEmpty()) { @@ -62,7 +87,7 @@ public class UpdateWorldSlumberSystem extends TickingSystem { for (PlayerRef playerRef : playerRefs) { Ref ref = playerRef.getReference(); if (ref != null && ref.isValid()) { - PlayerSomnolence somnolenceComponent = store.getComponent(ref, PlayerSomnolence.getComponentType()); + PlayerSomnolence somnolenceComponent = store.getComponent(ref, playerSomnolenceComponentType); if (somnolenceComponent == null) { return true; } diff --git a/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsSystems.java b/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsSystems.java index 755e9718..44dd8109 100644 --- a/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsSystems.java +++ b/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsSystems.java @@ -5,6 +5,7 @@ import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.DisableProcessingAssert; +import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.dependency.Dependency; import com.hypixel.hytale.component.dependency.Order; @@ -30,10 +31,12 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BlockPhysicsSystems { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); public static final int MAX_SUPPORT_RADIUS = 14; public static class CachedAccessor extends AbstractCachedAccessor { + @Nonnull private static final ThreadLocal THREAD_LOCAL = ThreadLocal.withInitial(BlockPhysicsSystems.CachedAccessor::new); private static final int PHYSICS_COMPONENT = 0; private static final int FLUID_COMPONENT = 1; @@ -125,9 +128,11 @@ public class BlockPhysicsSystems { } public static class Ticking extends EntityTickingSystem implements DisableProcessingAssert { + @Nonnull private static final Query QUERY = Query.and( ChunkSection.getComponentType(), BlockSection.getComponentType(), BlockPhysics.getComponentType(), FluidSection.getComponentType() ); + @Nonnull private static final Set> DEPENDENCIES = Set.of( new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class), new SystemDependency<>(Order.BEFORE, ChunkBlockTickSystem.Ticking.class) ); @@ -157,28 +162,40 @@ public class BlockPhysicsSystems { assert section != null; try { - BlockSection blockSection = archetypeChunk.getComponent(index, BlockSection.getComponentType()); - - assert blockSection != null; - - if (blockSection.getTickingBlocksCountCopy() <= 0) { + BlockSection blockSectionComponent = archetypeChunk.getComponent(index, BlockSection.getComponentType()); + if (blockSectionComponent == null) { return; } - BlockPhysics blockPhysics = archetypeChunk.getComponent(index, BlockPhysics.getComponentType()); + if (blockSectionComponent.getTickingBlocksCountCopy() <= 0) { + return; + } - assert blockPhysics != null; + BlockPhysics blockPhysicsComponent = archetypeChunk.getComponent(index, BlockPhysics.getComponentType()); + if (blockPhysicsComponent == null) { + return; + } - FluidSection fluidSection = archetypeChunk.getComponent(index, FluidSection.getComponentType()); + FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType()); + if (fluidSectionComponent == null) { + return; + } - assert fluidSection != null; + Ref columnRef = section.getChunkColumnReference(); + if (columnRef == null || !columnRef.isValid()) { + return; + } + + WorldChunk worldChunkComponent = commandBuffer.getComponent(columnRef, WorldChunk.getComponentType()); + if (worldChunkComponent == null) { + return; + } - WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType()); BlockPhysicsSystems.CachedAccessor accessor = BlockPhysicsSystems.CachedAccessor.of( - commandBuffer, blockSection, blockPhysics, fluidSection, section.getX(), section.getY(), section.getZ(), 14 + commandBuffer, blockSectionComponent, blockPhysicsComponent, fluidSectionComponent, section.getX(), section.getY(), section.getZ(), 14 ); - blockSection.forEachTicking( - worldChunk, + blockSectionComponent.forEachTicking( + worldChunkComponent, accessor, section.getY(), (wc, accessor1, localX, localY, localZ, blockId) -> { @@ -218,8 +235,8 @@ public class BlockPhysicsSystems { } } ); - } catch (Exception var12) { - BlockPhysicsSystems.LOGGER.at(Level.SEVERE).withCause(var12).log("Failed to tick chunk: %s", section); + } catch (Exception var13) { + BlockPhysicsSystems.LOGGER.at(Level.SEVERE).withCause(var13).log("Failed to tick chunk: %s", section); } } } diff --git a/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsUtil.java b/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsUtil.java index 97872125..ae2db82b 100644 --- a/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsUtil.java +++ b/src/com/hypixel/hytale/builtin/blockphysics/BlockPhysicsUtil.java @@ -34,7 +34,7 @@ public class BlockPhysicsUtil { @Nonnull public static BlockPhysicsUtil.Result applyBlockPhysics( - @Nullable ComponentAccessor commandBuffer, + @Nonnull ComponentAccessor componentAccessor, @Nonnull Ref chunkReference, @Nonnull BlockPhysicsSystems.CachedAccessor chunkAccessor, BlockSection blockSection, @@ -55,9 +55,7 @@ public class BlockPhysicsUtil { supportDistance = testBlockPhysics(chunkAccessor, blockSection, blockPhysics, fluidSection, blockX, blockY, blockZ, blockType, rotation, filler); } else { BlockBoundingBoxes boundingBoxes = BlockBoundingBoxes.getAssetMap().getAsset(blockType.getHitboxTypeIndex()); - if (!boundingBoxes.protrudesUnitBox()) { - supportDistance = testBlockPhysics(chunkAccessor, blockSection, blockPhysics, fluidSection, blockX, blockY, blockZ, blockType, rotation, filler); - } else { + if (boundingBoxes != null && boundingBoxes.protrudesUnitBox()) { BlockBoundingBoxes.RotatedVariantBoxes rotatedBox = boundingBoxes.get(rotation); Box boundingBox = rotatedBox.getBoundingBox(); int minX = (int)boundingBox.min.x; @@ -94,7 +92,7 @@ public class BlockPhysicsUtil { int blockHeight = Math.max(maxY - minY, 1); int blockDepth = Math.max(maxZ - minZ, 1); - label138: + label136: for (int x = 0; x < blockWidth; x++) { for (int y = 0; y < blockHeight; y++) { for (int z = 0; z < blockDepth; z++) { @@ -140,7 +138,7 @@ public class BlockPhysicsUtil { case Any: if (fillerSupportDistance == -2) { supportDistance = -2; - break label138; + break label136; } if (fillerSupportDistance == 0) { @@ -152,7 +150,7 @@ public class BlockPhysicsUtil { case All: if (fillerSupportDistance == 0) { supportDistance = 0; - break label138; + break label136; } if (fillerSupportDistance == -2) { @@ -165,21 +163,23 @@ public class BlockPhysicsUtil { } } } + } else { + supportDistance = testBlockPhysics(chunkAccessor, blockSection, blockPhysics, fluidSection, blockX, blockY, blockZ, blockType, rotation, filler); } } if (supportDistance == 0) { - World world = commandBuffer.getExternalData().getWorld(); + World world = componentAccessor.getExternalData().getWorld(); Store chunkStore = world.getChunkStore().getStore(); switch (blockType.getSupportDropType()) { case BREAK: BlockHarvestUtils.naturallyRemoveBlockByPhysics( - new Vector3i(blockX, blockY, blockZ), blockType, filler, 256, chunkReference, commandBuffer, chunkStore + new Vector3i(blockX, blockY, blockZ), blockType, filler, 256, chunkReference, componentAccessor, chunkStore ); break; case DESTROY: BlockHarvestUtils.naturallyRemoveBlockByPhysics( - new Vector3i(blockX, blockY, blockZ), blockType, filler, 2304, chunkReference, commandBuffer, chunkStore + new Vector3i(blockX, blockY, blockZ), blockType, filler, 2304, chunkReference, componentAccessor, chunkStore ); } @@ -289,7 +289,6 @@ public class BlockPhysicsUtil { if (requiredBlockFaceSupport.isAppliedToFiller(blockFillerOffset)) { boolean doesSatisfyRequirements = doesSatisfyRequirements( blockType, - fluid, blockFillerOffset, neighbourFillerOffset, blockFace, @@ -361,7 +360,6 @@ public class BlockPhysicsUtil { public static boolean doesSatisfyRequirements( @Nonnull BlockType blockType, - Fluid fluid, Vector3i blockFillerOffset, Vector3i neighbourFillerOffset, BlockFace blockFace, diff --git a/src/com/hypixel/hytale/builtin/blockphysics/PrefabBufferValidator.java b/src/com/hypixel/hytale/builtin/blockphysics/PrefabBufferValidator.java index bf8be09c..1692a8ce 100644 --- a/src/com/hypixel/hytale/builtin/blockphysics/PrefabBufferValidator.java +++ b/src/com/hypixel/hytale/builtin/blockphysics/PrefabBufferValidator.java @@ -31,16 +31,17 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class PrefabBufferValidator { + @Nonnull private static final FillerBlockUtil.FillerFetcher FILLER_FETCHER = new FillerBlockUtil.FillerFetcher() { - public int getBlock(IPrefabBuffer iPrefabBuffer, Void unused, int x, int y, int z) { + public int getBlock(@Nonnull IPrefabBuffer iPrefabBuffer, Void unused, int x, int y, int z) { return iPrefabBuffer.getBlockId(x, y, z); } - public int getFiller(IPrefabBuffer iPrefabBuffer, Void unused, int x, int y, int z) { + public int getFiller(@Nonnull IPrefabBuffer iPrefabBuffer, Void unused, int x, int y, int z) { return iPrefabBuffer.getFiller(x, y, z); } - public int getRotationIndex(IPrefabBuffer iPrefabBuffer, Void unused, int x, int y, int z) { + public int getRotationIndex(@Nonnull IPrefabBuffer iPrefabBuffer, Void unused, int x, int y, int z) { return iPrefabBuffer.getRotationIndex(x, y, z); } }; diff --git a/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerEntry.java b/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerEntry.java index c2cdd817..c108ab93 100644 --- a/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerEntry.java +++ b/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerEntry.java @@ -35,6 +35,7 @@ public class BlockSpawnerEntry implements IWeightedElement { ) .add() .build(); + @Nonnull public static final BlockSpawnerEntry[] EMPTY_ARRAY = new BlockSpawnerEntry[0]; private String blockName; private Holder blockComponents; @@ -63,6 +64,7 @@ public class BlockSpawnerEntry implements IWeightedElement { RANDOM, INHERIT; + @Nonnull public static final Codec CODEC = new EnumCodec<>(BlockSpawnerEntry.RotationMode.class); } } diff --git a/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerPlugin.java b/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerPlugin.java index 7216dab2..1896fccd 100644 --- a/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerPlugin.java +++ b/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerPlugin.java @@ -38,6 +38,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BlockSpawnerPlugin extends JavaPlugin { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); private ComponentType blockSpawnerComponentType; private static BlockSpawnerPlugin INSTANCE; @@ -70,14 +71,14 @@ public class BlockSpawnerPlugin extends JavaPlugin { this.getEventRegistry().registerGlobal(PrefabBufferValidator.ValidateBlockEvent.class, BlockSpawnerPlugin::validatePrefabBlock); } - private static void validatePrefabBlock(PrefabBufferValidator.ValidateBlockEvent validateBlockEvent) { + private static void validatePrefabBlock(@Nonnull PrefabBufferValidator.ValidateBlockEvent validateBlockEvent) { Holder holder = validateBlockEvent.holder(); if (holder != null) { - BlockSpawner spawner = holder.getComponent(BlockSpawner.getComponentType()); - if (spawner != null) { + BlockSpawner blockSpawnerComponent = holder.getComponent(BlockSpawner.getComponentType()); + if (blockSpawnerComponent != null) { BlockType blockType = BlockType.getAssetMap().getAsset(validateBlockEvent.blockId()); if (blockType != null) { - if (spawner.getBlockSpawnerId() == null) { + if (blockSpawnerComponent.getBlockSpawnerId() == null) { validateBlockEvent.reason() .append("\t Block ") .append(blockType.getId()) @@ -90,7 +91,7 @@ public class BlockSpawnerPlugin extends JavaPlugin { .append(" has no defined block spawner id") .append('\n'); } else { - BlockSpawnerTable blockSpawner = BlockSpawnerTable.getAssetMap().getAsset(spawner.getBlockSpawnerId()); + BlockSpawnerTable blockSpawner = BlockSpawnerTable.getAssetMap().getAsset(blockSpawnerComponent.getBlockSpawnerId()); if (blockSpawner == null) { validateBlockEvent.reason() .append("\t Block ") @@ -102,7 +103,7 @@ public class BlockSpawnerPlugin extends JavaPlugin { .append(", ") .append(validateBlockEvent.z()) .append(" has an invalid spawner id ") - .append(spawner.getBlockSpawnerId()) + .append(blockSpawnerComponent.getBlockSpawnerId()) .append('\n'); } } @@ -116,8 +117,11 @@ public class BlockSpawnerPlugin extends JavaPlugin { } private static class BlockSpawnerSystem extends RefSystem { + @Nonnull private static final ComponentType COMPONENT_TYPE = BlockSpawner.getComponentType(); + @Nonnull private static final ComponentType BLOCK_INFO_COMPONENT_TYPE = BlockModule.BlockStateInfo.getComponentType(); + @Nonnull private static final Query QUERY = Query.and(COMPONENT_TYPE, BLOCK_INFO_COMPONENT_TYPE); public BlockSpawnerSystem() { @@ -134,72 +138,74 @@ public class BlockSpawnerPlugin extends JavaPlugin { ) { WorldConfig worldConfig = store.getExternalData().getWorld().getWorldConfig(); if (worldConfig.getGameMode() != GameMode.Creative) { - BlockSpawner state = commandBuffer.getComponent(ref, COMPONENT_TYPE); + BlockSpawner blockSpawnerComponent = commandBuffer.getComponent(ref, COMPONENT_TYPE); - assert state != null; + assert blockSpawnerComponent != null; - BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BLOCK_INFO_COMPONENT_TYPE); + BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BLOCK_INFO_COMPONENT_TYPE); - assert info != null; + assert blockStateInfoComponent != null; - String blockSpawnerId = state.getBlockSpawnerId(); + String blockSpawnerId = blockSpawnerComponent.getBlockSpawnerId(); if (blockSpawnerId != null) { BlockSpawnerTable table = BlockSpawnerTable.getAssetMap().getAsset(blockSpawnerId); if (table == null) { BlockSpawnerPlugin.LOGGER.at(Level.WARNING).log("Failed to find BlockSpawner Asset by name: %s", blockSpawnerId); } else { - Ref chunk = info.getChunkRef(); - if (chunk != null) { - WorldChunk wc = commandBuffer.getComponent(chunk, WorldChunk.getComponentType()); - int x = ChunkUtil.worldCoordFromLocalCoord(wc.getX(), ChunkUtil.xFromBlockInColumn(info.getIndex())); - int y = ChunkUtil.yFromBlockInColumn(info.getIndex()); - int z = ChunkUtil.worldCoordFromLocalCoord(wc.getZ(), ChunkUtil.zFromBlockInColumn(info.getIndex())); - long seed = worldConfig.getSeed(); - double randomRnd = HashUtil.random(x, y, z, seed + -1699164769L); - BlockSpawnerEntry entry = table.getEntries().get(randomRnd); - if (entry != null) { - String blockKey = entry.getBlockName(); + Ref chunkRef = blockStateInfoComponent.getChunkRef(); + if (chunkRef.isValid()) { + WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkRef, WorldChunk.getComponentType()); + if (worldChunkComponent != null) { + int x = ChunkUtil.worldCoordFromLocalCoord(worldChunkComponent.getX(), ChunkUtil.xFromBlockInColumn(blockStateInfoComponent.getIndex())); + int y = ChunkUtil.yFromBlockInColumn(blockStateInfoComponent.getIndex()); + int z = ChunkUtil.worldCoordFromLocalCoord(worldChunkComponent.getZ(), ChunkUtil.zFromBlockInColumn(blockStateInfoComponent.getIndex())); + long seed = worldConfig.getSeed(); + double randomRnd = HashUtil.random(x, y, z, seed + -1699164769L); + BlockSpawnerEntry entry = table.getEntries().get(randomRnd); + if (entry != null) { + String blockKey = entry.getBlockName(); - RotationTuple rotation = switch (entry.getRotationMode()) { - case NONE -> RotationTuple.NONE; - case RANDOM -> { - String key = entry.getBlockName(); - VariantRotation variantRotation = BlockType.getAssetMap().getAsset(key).getVariantRotation(); - if (variantRotation == VariantRotation.None) { - yield RotationTuple.NONE; - } else { - int randomHash = (int)HashUtil.rehash(x, y, z, seed + -1699164769L); - Rotation rotationYaw = Rotation.NORMAL[(randomHash & 65535) % Rotation.NORMAL.length]; - yield BlockRotationUtil.getRotated(RotationTuple.NONE, Axis.Y, rotationYaw, variantRotation); + RotationTuple rotation = switch (entry.getRotationMode()) { + case NONE -> RotationTuple.NONE; + case RANDOM -> { + String key = entry.getBlockName(); + VariantRotation variantRotation = BlockType.getAssetMap().getAsset(key).getVariantRotation(); + if (variantRotation == VariantRotation.None) { + yield RotationTuple.NONE; + } else { + int randomHash = (int)HashUtil.rehash(x, y, z, seed + -1699164769L); + Rotation rotationYaw = Rotation.NORMAL[(randomHash & 65535) % Rotation.NORMAL.length]; + yield BlockRotationUtil.getRotated(RotationTuple.NONE, Axis.Y, rotationYaw, variantRotation); + } } - } - case INHERIT -> { - String key = entry.getBlockName(); - VariantRotation variantRotation = BlockType.getAssetMap().getAsset(key).getVariantRotation(); - if (variantRotation == VariantRotation.None) { - yield RotationTuple.NONE; - } else { - RotationTuple spawnerRotation = RotationTuple.get(wc.getRotationIndex(x, y, z)); - Rotation spawnerYaw = spawnerRotation.yaw(); - yield BlockRotationUtil.getRotated(RotationTuple.NONE, Axis.Y, spawnerYaw, variantRotation); + case INHERIT -> { + String key = entry.getBlockName(); + VariantRotation variantRotation = BlockType.getAssetMap().getAsset(key).getVariantRotation(); + if (variantRotation == VariantRotation.None) { + yield RotationTuple.NONE; + } else { + RotationTuple spawnerRotation = RotationTuple.get(worldChunkComponent.getRotationIndex(x, y, z)); + Rotation spawnerYaw = spawnerRotation.yaw(); + yield BlockRotationUtil.getRotated(RotationTuple.NONE, Axis.Y, spawnerYaw, variantRotation); + } + } + }; + Holder holder = entry.getBlockComponents(); + commandBuffer.removeEntity(ref, RemoveReason.REMOVE); + commandBuffer.run(_store -> { + int flags = 4; + if (holder != null) { + flags |= 2; } - } - }; - Holder holder = entry.getBlockComponents(); - commandBuffer.removeEntity(ref, RemoveReason.REMOVE); - commandBuffer.run(_store -> { - int flags = 4; - if (holder != null) { - flags |= 2; - } - int blockId = BlockType.getAssetMap().getIndex(blockKey); - BlockType blockType = BlockType.getAssetMap().getAsset(blockId); - wc.setBlock(x, y, z, blockId, blockType, rotation.index(), 0, flags); - if (holder != null) { - wc.setState(x, y, z, holder.clone()); - } - }); + int blockId = BlockType.getAssetMap().getIndex(blockKey); + BlockType blockType = BlockType.getAssetMap().getAsset(blockId); + worldChunkComponent.setBlock(x, y, z, blockId, blockType, rotation.index(), 0, flags); + if (holder != null) { + worldChunkComponent.setState(x, y, z, holder.clone()); + } + }); + } } } } diff --git a/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerTable.java b/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerTable.java index b745d5c6..3f127c7b 100644 --- a/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerTable.java +++ b/src/com/hypixel/hytale/builtin/blockspawner/BlockSpawnerTable.java @@ -16,6 +16,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BlockSpawnerTable implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( BlockSpawnerTable.class, BlockSpawnerTable::new, diff --git a/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerGetCommand.java b/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerGetCommand.java index c0508c0f..28387395 100644 --- a/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerGetCommand.java +++ b/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerGetCommand.java @@ -25,6 +25,8 @@ public class BlockSpawnerGetCommand extends AbstractWorldCommand { @Nonnull private static final Message MESSAGE_COMMANDS_ERRORS_PROVIDE_POSITION = Message.translation("server.commands.errors.providePosition"); @Nonnull + private static final Message MESSAGE_COMMANDS_ERRORS_PLAYER_NOT_IN_WORLD = Message.translation("server.commands.errors.playerNotInWorld"); + @Nonnull private static final Message MESSAGE_COMMANDS_BLOCK_SPAWNER_NO_BLOCK_SPAWNER_SET = Message.translation("server.commands.blockspawner.noBlockSpawnerSet"); @Nonnull private final OptionalArg positionArg = this.withOptionalArg( @@ -47,6 +49,10 @@ public class BlockSpawnerGetCommand extends AbstractWorldCommand { } Ref ref = context.senderAsPlayerRef(); + if (ref == null || !ref.isValid()) { + throw new GeneralCommandException(MESSAGE_COMMANDS_ERRORS_PLAYER_NOT_IN_WORLD); + } + Vector3i targetBlock = TargetUtil.getTargetBlock(ref, 10.0, store); if (targetBlock == null) { throw new GeneralCommandException(MESSAGE_GENERAL_BLOCK_TARGET_NOT_IN_RANGE); @@ -64,9 +70,7 @@ public class BlockSpawnerGetCommand extends AbstractWorldCommand { assert worldChunkComponent != null; Ref blockRef = worldChunkComponent.getBlockComponentEntity(position.x, position.y, position.z); - if (blockRef == null) { - context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); - } else { + if (blockRef != null && blockRef.isValid()) { BlockSpawner spawnerState = chunkStore.getStore().getComponent(blockRef, BlockSpawner.getComponentType()); if (spawnerState == null) { context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); @@ -77,6 +81,8 @@ public class BlockSpawnerGetCommand extends AbstractWorldCommand { context.sendMessage(Message.translation("server.commands.blockspawner.currentBlockSpawner").param("id", spawnerState.getBlockSpawnerId())); } } + } else { + context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); } } else { context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); diff --git a/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerSetCommand.java b/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerSetCommand.java index de3885a3..a0ec6065 100644 --- a/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerSetCommand.java +++ b/src/com/hypixel/hytale/builtin/blockspawner/command/BlockSpawnerSetCommand.java @@ -30,6 +30,8 @@ public class BlockSpawnerSetCommand extends AbstractWorldCommand { @Nonnull private static final Message MESSAGE_COMMANDS_ERRORS_PROVIDE_POSITION = Message.translation("server.commands.errors.providePosition"); @Nonnull + private static final Message MESSAGE_COMMANDS_ERRORS_PLAYER_NOT_IN_WORLD = Message.translation("server.commands.errors.playerNotInWorld"); + @Nonnull private static final SingleArgumentType BLOCK_SPAWNER_ASSET_TYPE = new AssetArgumentType( "server.commands.parsing.argtype.asset.blockspawnertable.name", BlockSpawnerTable.class, "server.commands.parsing.argtype.asset.blockspawnertable.usage" ); @@ -60,6 +62,10 @@ public class BlockSpawnerSetCommand extends AbstractWorldCommand { } Ref ref = context.senderAsPlayerRef(); + if (ref == null || !ref.isValid()) { + throw new GeneralCommandException(MESSAGE_COMMANDS_ERRORS_PLAYER_NOT_IN_WORLD); + } + Vector3i targetBlock = TargetUtil.getTargetBlock(ref, 10.0, store); if (targetBlock == null) { throw new GeneralCommandException(MESSAGE_GENERAL_BLOCK_TARGET_NOT_IN_RANGE); @@ -68,32 +74,37 @@ public class BlockSpawnerSetCommand extends AbstractWorldCommand { position = targetBlock; } - WorldChunk chunk = world.getChunk(ChunkUtil.indexChunkFromBlock(position.x, position.z)); - Ref blockRef = chunk.getBlockComponentEntity(position.x, position.y, position.z); - if (blockRef == null) { + WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(position.x, position.z)); + if (worldChunk == null) { context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); } else { - BlockSpawner spawnerState = world.getChunkStore().getStore().getComponent(blockRef, BlockSpawner.getComponentType()); - if (spawnerState == null) { - context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); - } else { - String spawnerId; - if (this.ignoreChecksFlag.get(context)) { - String[] input = context.getInput(this.blockSpawnerIdArg); - spawnerId = input != null && input.length > 0 ? input[0] : null; - if (spawnerId == null) { - context.sendMessage( - Message.translation("errors.validation_failure").param("message", "blockSpawnerId is required when --ignoreChecks is set") - ); - return; - } + Ref blockRef = worldChunk.getBlockComponentEntity(position.x, position.y, position.z); + if (blockRef != null && blockRef.isValid()) { + Store chunkStore = world.getChunkStore().getStore(); + BlockSpawner spawnerState = chunkStore.getComponent(blockRef, BlockSpawner.getComponentType()); + if (spawnerState == null) { + context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); } else { - spawnerId = this.blockSpawnerIdArg.get(context).getId(); - } + String spawnerId; + if (this.ignoreChecksFlag.get(context)) { + String[] input = context.getInput(this.blockSpawnerIdArg); + spawnerId = input != null && input.length > 0 ? input[0] : null; + if (spawnerId == null) { + context.sendMessage( + Message.translation("errors.validation_failure").param("message", "blockSpawnerId is required when --ignoreChecks is set") + ); + return; + } + } else { + spawnerId = this.blockSpawnerIdArg.get(context).getId(); + } - spawnerState.setBlockSpawnerId(spawnerId); - chunk.markNeedsSaving(); - context.sendMessage(Message.translation("server.commands.blockspawner.blockSpawnerSet").param("id", spawnerId)); + spawnerState.setBlockSpawnerId(spawnerId); + worldChunk.markNeedsSaving(); + context.sendMessage(Message.translation("server.commands.blockspawner.blockSpawnerSet").param("id", spawnerId)); + } + } else { + context.sendMessage(Message.translation("server.general.containerNotFound").param("block", position.toString())); } } } diff --git a/src/com/hypixel/hytale/builtin/blockspawner/state/BlockSpawner.java b/src/com/hypixel/hytale/builtin/blockspawner/state/BlockSpawner.java index 66b7958a..941ddaeb 100644 --- a/src/com/hypixel/hytale/builtin/blockspawner/state/BlockSpawner.java +++ b/src/com/hypixel/hytale/builtin/blockspawner/state/BlockSpawner.java @@ -11,6 +11,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BlockSpawner implements Component { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(BlockSpawner.class, BlockSpawner::new) .addField(new KeyedCodec<>("BlockSpawnerId", Codec.STRING), (state, s) -> state.blockSpawnerId = s, state -> state.blockSpawnerId) .build(); diff --git a/src/com/hypixel/hytale/builtin/blocktick/BlockTickPlugin.java b/src/com/hypixel/hytale/builtin/blocktick/BlockTickPlugin.java index 06445e1e..6c8ca34c 100644 --- a/src/com/hypixel/hytale/builtin/blocktick/BlockTickPlugin.java +++ b/src/com/hypixel/hytale/builtin/blocktick/BlockTickPlugin.java @@ -55,19 +55,17 @@ public class BlockTickPlugin extends JavaPlugin implements IBlockTickProvider { } } - public int discoverTickingBlocks(@Nonnull Holder holder, @Nonnull WorldChunk chunk) { + public int discoverTickingBlocks(@Nonnull Holder holder, @Nonnull WorldChunk worldChunk) { if (!this.isEnabled()) { return 0; } else { - BlockChunk bc = chunk.getBlockChunk(); - if (!bc.consumeNeedsPhysics()) { - return 0; - } else { - ChunkColumn column = holder.getComponent(ChunkColumn.getComponentType()); - if (column == null) { + BlockChunk blockChunkComponent = worldChunk.getBlockChunk(); + if (blockChunkComponent != null && blockChunkComponent.consumeNeedsPhysics()) { + ChunkColumn chunkColumnComponent = holder.getComponent(ChunkColumn.getComponentType()); + if (chunkColumnComponent == null) { return 0; } else { - Holder[] sections = column.getSectionHolders(); + Holder[] sections = chunkColumnComponent.getSectionHolders(); if (sections == null) { return 0; } else { @@ -76,14 +74,14 @@ public class BlockTickPlugin extends JavaPlugin implements IBlockTickProvider { for (int i = 0; i < sections.length; i++) { Holder sectionHolder = sections[i]; - BlockSection section = sectionHolder.ensureAndGetComponent(BlockSection.getComponentType()); - if (!section.isSolidAir()) { + BlockSection blockSectionComponent = sectionHolder.ensureAndGetComponent(BlockSection.getComponentType()); + if (!blockSectionComponent.isSolidAir()) { for (int blockIdx = 0; blockIdx < 32768; blockIdx++) { - int blockId = section.get(blockIdx); + int blockId = blockSectionComponent.get(blockIdx); BlockType blockType = assetMap.getAsset(blockId); if (blockType != null && blockType.getTickProcedure() != null) { - section.setTicking(blockIdx, true); - bc.markNeedsSaving(); + blockSectionComponent.setTicking(blockIdx, true); + blockChunkComponent.markNeedsSaving(); count++; } } @@ -93,6 +91,8 @@ public class BlockTickPlugin extends JavaPlugin implements IBlockTickProvider { return count; } } + } else { + return 0; } } } diff --git a/src/com/hypixel/hytale/builtin/blocktick/procedure/BasicChanceBlockGrowthProcedure.java b/src/com/hypixel/hytale/builtin/blocktick/procedure/BasicChanceBlockGrowthProcedure.java index 6c24dc54..f21ec9b6 100644 --- a/src/com/hypixel/hytale/builtin/blocktick/procedure/BasicChanceBlockGrowthProcedure.java +++ b/src/com/hypixel/hytale/builtin/blocktick/procedure/BasicChanceBlockGrowthProcedure.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import javax.annotation.Nonnull; public class BasicChanceBlockGrowthProcedure extends TickProcedure { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( BasicChanceBlockGrowthProcedure.class, BasicChanceBlockGrowthProcedure::new, TickProcedure.BASE_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/blocktick/procedure/SplitChanceBlockGrowthProcedure.java b/src/com/hypixel/hytale/builtin/blocktick/procedure/SplitChanceBlockGrowthProcedure.java index c7065285..9f7a0a46 100644 --- a/src/com/hypixel/hytale/builtin/blocktick/procedure/SplitChanceBlockGrowthProcedure.java +++ b/src/com/hypixel/hytale/builtin/blocktick/procedure/SplitChanceBlockGrowthProcedure.java @@ -14,6 +14,7 @@ import org.bson.BsonDocument; import org.bson.BsonValue; public class SplitChanceBlockGrowthProcedure extends BasicChanceBlockGrowthProcedure { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SplitChanceBlockGrowthProcedure.class, SplitChanceBlockGrowthProcedure::new, TickProcedure.BASE_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/blocktick/system/ChunkBlockTickSystem.java b/src/com/hypixel/hytale/builtin/blocktick/system/ChunkBlockTickSystem.java index e02dfa99..3016e5cd 100644 --- a/src/com/hypixel/hytale/builtin/blocktick/system/ChunkBlockTickSystem.java +++ b/src/com/hypixel/hytale/builtin/blocktick/system/ChunkBlockTickSystem.java @@ -21,20 +21,23 @@ import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.time.Instant; import java.util.Set; import java.util.logging.Level; import javax.annotation.Nonnull; public class ChunkBlockTickSystem { + @Nonnull protected static final HytaleLogger LOGGER = BlockTickPlugin.get().getLogger(); public static class PreTick extends EntityTickingSystem { - private static final ComponentType COMPONENT_TYPE = BlockChunk.getComponentType(); + @Nonnull + private static final ComponentType COMPONENT_TYPE_WORLD_CHUNK = BlockChunk.getComponentType(); @Override public Query getQuery() { - return COMPONENT_TYPE; + return COMPONENT_TYPE_WORLD_CHUNK; } @Override @@ -50,26 +53,30 @@ public class ChunkBlockTickSystem { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Instant time = commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()).getGameTime(); - BlockChunk chunk = archetypeChunk.getComponent(index, COMPONENT_TYPE); + World world = commandBuffer.getExternalData().getWorld(); + Store entityStore = world.getEntityStore().getStore(); + Instant timeResource = entityStore.getResource(WorldTimeResource.getResourceType()).getGameTime(); + BlockChunk blockChunkComponent = archetypeChunk.getComponent(index, COMPONENT_TYPE_WORLD_CHUNK); - assert chunk != null; + assert blockChunkComponent != null; try { - chunk.preTick(time); - } catch (Throwable var9) { - ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var9).log("Failed to pre-tick chunk: %s", chunk); + blockChunkComponent.preTick(timeResource); + } catch (Throwable var11) { + ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var11).log("Failed to pre-tick chunk: %s", blockChunkComponent); } } } public static class Ticking extends EntityTickingSystem { - private static final ComponentType COMPONENT_TYPE = WorldChunk.getComponentType(); + @Nonnull + private static final ComponentType COMPONENT_TYPE_WORLD_CHUNK = WorldChunk.getComponentType(); + @Nonnull private static final Set> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class)); @Override public Query getQuery() { - return COMPONENT_TYPE; + return COMPONENT_TYPE_WORLD_CHUNK; } @Nonnull @@ -87,24 +94,33 @@ public class ChunkBlockTickSystem { @Nonnull CommandBuffer commandBuffer ) { Ref reference = archetypeChunk.getReferenceTo(index); - WorldChunk worldChunk = archetypeChunk.getComponent(index, COMPONENT_TYPE); + WorldChunk worldChunkComponent = archetypeChunk.getComponent(index, COMPONENT_TYPE_WORLD_CHUNK); + + assert worldChunkComponent != null; try { - tick(reference, worldChunk); + tick(reference, worldChunkComponent); } catch (Throwable var9) { - ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var9).log("Failed to tick chunk: %s", worldChunk); + ChunkBlockTickSystem.LOGGER.at(Level.SEVERE).withCause(var9).log("Failed to tick chunk: %s", worldChunkComponent); } } - protected static void tick(Ref ref, @Nonnull WorldChunk worldChunk) { - int ticked = worldChunk.getBlockChunk().forEachTicking(ref, worldChunk, (r, c, localX, localY, localZ, blockId) -> { - World world = c.getWorld(); - int blockX = c.getX() << 5 | localX; - int blockZ = c.getZ() << 5 | localZ; - return tickProcedure(world, c, blockX, localY, blockZ, blockId); - }); - if (ticked > 0) { - ChunkBlockTickSystem.LOGGER.at(Level.FINER).log("Ticked %d blocks in chunk (%d, %d)", ticked, worldChunk.getX(), worldChunk.getZ()); + protected static void tick(@Nonnull Ref ref, @Nonnull WorldChunk worldChunk) { + BlockChunk blockChunkComponent = worldChunk.getBlockChunk(); + if (blockChunkComponent == null) { + ChunkBlockTickSystem.LOGGER + .at(Level.WARNING) + .log("World chunk (%d, %d) has no BlockChunk component, skipping block ticking.", worldChunk.getX(), worldChunk.getZ()); + } else { + int ticked = blockChunkComponent.forEachTicking(ref, worldChunk, (r, c, localX, localY, localZ, blockId) -> { + World world = c.getWorld(); + int blockX = c.getX() << 5 | localX; + int blockZ = c.getZ() << 5 | localZ; + return tickProcedure(world, c, blockX, localY, blockZ, blockId); + }); + if (ticked > 0) { + ChunkBlockTickSystem.LOGGER.at(Level.FINER).log("Ticked %d blocks in chunk (%d, %d)", ticked, worldChunk.getX(), worldChunk.getZ()); + } } } diff --git a/src/com/hypixel/hytale/builtin/blocktick/system/MergeWaitingBlocksSystem.java b/src/com/hypixel/hytale/builtin/blocktick/system/MergeWaitingBlocksSystem.java index 362fb77d..1228da96 100644 --- a/src/com/hypixel/hytale/builtin/blocktick/system/MergeWaitingBlocksSystem.java +++ b/src/com/hypixel/hytale/builtin/blocktick/system/MergeWaitingBlocksSystem.java @@ -15,6 +15,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import javax.annotation.Nonnull; public class MergeWaitingBlocksSystem extends RefSystem { + @Nonnull private static final ComponentType COMPONENT_TYPE = WorldChunk.getComponentType(); @Override @@ -27,9 +28,12 @@ public class MergeWaitingBlocksSystem extends RefSystem { @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { ChunkStore chunkStore = store.getExternalData(); - WorldChunk chunk = store.getComponent(ref, COMPONENT_TYPE); - int x = chunk.getX(); - int z = chunk.getZ(); + WorldChunk worldChunkComponent = store.getComponent(ref, COMPONENT_TYPE); + + assert worldChunkComponent != null; + + int x = worldChunkComponent.getX(); + int z = worldChunkComponent.getZ(); mergeTickingBlocks(chunkStore, x - 1, z); mergeTickingBlocks(chunkStore, x + 1, z); mergeTickingBlocks(chunkStore, x, z - 1); @@ -43,9 +47,10 @@ public class MergeWaitingBlocksSystem extends RefSystem { } public static void mergeTickingBlocks(@Nonnull ChunkStore store, int x, int z) { - BlockChunk blockChunk = store.getChunkComponent(ChunkUtil.indexChunk(x, z), BlockChunk.getComponentType()); - if (blockChunk != null) { - blockChunk.mergeTickingBlocks(); + long chunkIndex = ChunkUtil.indexChunk(x, z); + BlockChunk blockChunkComponent = store.getChunkComponent(chunkIndex, BlockChunk.getComponentType()); + if (blockChunkComponent != null) { + blockChunkComponent.mergeTickingBlocks(); } } } diff --git a/src/com/hypixel/hytale/builtin/buildertools/BuilderToolsPlugin.java b/src/com/hypixel/hytale/builtin/buildertools/BuilderToolsPlugin.java index 242323af..60fb6541 100644 --- a/src/com/hypixel/hytale/builtin/buildertools/BuilderToolsPlugin.java +++ b/src/com/hypixel/hytale/builtin/buildertools/BuilderToolsPlugin.java @@ -21,6 +21,7 @@ import com.hypixel.hytale.builtin.buildertools.commands.FlipCommand; import com.hypixel.hytale.builtin.buildertools.commands.GlobalMaskCommand; import com.hypixel.hytale.builtin.buildertools.commands.HollowCommand; import com.hypixel.hytale.builtin.buildertools.commands.HotbarSwitchCommand; +import com.hypixel.hytale.builtin.buildertools.commands.LayerCommand; import com.hypixel.hytale.builtin.buildertools.commands.MoveCommand; import com.hypixel.hytale.builtin.buildertools.commands.PasteCommand; import com.hypixel.hytale.builtin.buildertools.commands.Pos1Command; @@ -245,6 +246,7 @@ import com.hypixel.hytale.server.core.util.TargetUtil; import com.hypixel.hytale.server.core.util.TempAssetIdUtil; import com.hypixel.hytale.sneakythrow.consumer.ThrowableConsumer; import com.hypixel.hytale.sneakythrow.consumer.ThrowableTriConsumer; +import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2IntFunction; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntMaps; @@ -443,6 +445,7 @@ public class BuilderToolsPlugin extends JavaPlugin implements SelectionProvider, commandRegistry.registerCommand(new SetToolHistorySizeCommand()); commandRegistry.registerCommand(new ObjImportCommand()); commandRegistry.registerCommand(new ImageImportCommand()); + commandRegistry.registerCommand(new LayerCommand()); OpenCustomUIInteraction.registerBlockCustomPage( this, PrefabSpawnerState.PrefabSpawnerSettingsPage.class, @@ -885,7 +888,8 @@ public class BuilderToolsPlugin extends JavaPlugin implements SelectionProvider, EXTRUDE, UPDATE_SELECTION, WALLS, - HOLLOW; + HOLLOW, + LAYER; } public static class ActionEntry { @@ -2607,6 +2611,111 @@ public class BuilderToolsPlugin extends JavaPlugin implements SelectionProvider, ); } + public void layer( + int x, + int y, + int z, + @Nonnull List> layers, + int depth, + Vector3i direction, + WorldChunk chunk, + BlockSelection before, + BlockSelection after + ) { + int xModifier = direction.x == 1 ? -1 : (direction.x == -1 ? 1 : 0); + int yModifier = direction.y == 1 ? -1 : (direction.y == -1 ? 1 : 0); + int zModifier = direction.z == 1 ? -1 : (direction.z == -1 ? 1 : 0); + + for (int i = 0; i < depth; i++) { + if (chunk.getBlock(x + i * xModifier + xModifier, y + i * yModifier + yModifier, z + i * zModifier + zModifier) <= 0 + && this.attemptSetLayer(x, y, z, i, layers, chunk, before, after)) { + return; + } + } + } + + public void layer(@Nonnull List> layers, Vector3i direction, ComponentAccessor componentAccessor) { + if (this.selection == null) { + this.sendFeedback(Message.translation("server.builderTools.noSelection"), componentAccessor); + } else if (!this.selection.hasSelectionBounds()) { + this.sendFeedback(Message.translation("server.builderTools.noSelectionBounds"), componentAccessor); + } else { + int maxDepth = 0; + + for (Pair layer : layers) { + maxDepth += layer.left(); + } + + long start = System.nanoTime(); + Vector3i min = Vector3i.min(this.selection.getSelectionMin(), this.selection.getSelectionMax()); + Vector3i max = Vector3i.max(this.selection.getSelectionMin(), this.selection.getSelectionMax()); + int xMin = min.getX(); + int xMax = max.getX(); + int yMin = min.getY(); + int yMax = max.getY(); + int zMin = min.getZ(); + int zMax = max.getZ(); + BlockSelection before = new BlockSelection(); + int width = xMax - xMin; + int depth = zMax - zMin; + int halfWidth = width / 2; + int halfDepth = depth / 2; + before.setPosition(xMin + halfWidth, yMin, zMin + halfDepth); + before.setSelectionArea(min, max); + this.pushHistory(BuilderToolsPlugin.Action.LAYER, new BlockSelectionSnapshot(before)); + BlockSelection after = new BlockSelection(before); + World world = componentAccessor.getExternalData().getWorld(); + LocalCachedChunkAccessor accessor = LocalCachedChunkAccessor.atWorldCoords(world, xMin + halfWidth, zMin + halfDepth, Math.max(width, depth)); + + for (int x = xMin; x <= xMax; x++) { + for (int z = zMin; z <= zMax; z++) { + WorldChunk chunk = accessor.getChunk(ChunkUtil.indexChunkFromBlock(x, z)); + + for (int y = yMax; y >= yMin; y--) { + int currentBlock = chunk.getBlock(x, y, z); + int currentFluid = chunk.getFluidId(x, y, z); + if (currentBlock > 0 && (this.globalMask == null || !this.globalMask.isExcluded(accessor, x, y, z, min, max, currentBlock, currentFluid))) { + this.layer(x, y, z, layers, maxDepth, direction, chunk, before, after); + } + } + } + } + + after.placeNoReturn("Finished layer", this.player, BuilderToolsPlugin.FEEDBACK_CONSUMER, world, componentAccessor); + BuilderToolsPlugin.invalidateWorldMapForSelection(after, world); + long end = System.nanoTime(); + long diff = end - start; + BuilderToolsPlugin.get().getLogger().at(Level.FINE).log("Took: %dns (%dms) to execute layer", diff, TimeUnit.NANOSECONDS.toMillis(diff)); + this.sendUpdate(); + this.sendArea(); + } + } + + private boolean attemptSetLayer( + int x, int y, int z, int depth, List> layers, WorldChunk chunk, BlockSelection before, BlockSelection after + ) { + int currentDepth = 0; + + for (Pair layer : layers) { + currentDepth += layer.left(); + if (depth < currentDepth) { + int currentBlock = chunk.getBlock(x, y, z); + int currentBlockFiller = chunk.getFiller(x, y, z); + Holder holder = chunk.getBlockComponentHolder(x, y, z); + int rotation = chunk.getRotationIndex(x, y, z); + int supportValue = chunk.getSupportValue(x, y, z); + BlockPattern pattern = BlockPattern.parse(layer.right()); + int materialId = pattern.nextBlock(this.random); + Holder newHolder = BuilderToolsPlugin.createBlockComponent(chunk, x, y, z, materialId, currentBlock, holder, true); + before.addBlockAtWorldPos(x, y, z, currentBlock, rotation, currentBlockFiller, supportValue, holder); + after.addBlockAtWorldPos(x, y, z, materialId, rotation, 0, 0, newHolder); + return true; + } + } + + return false; + } + public int paste(@Nonnull Ref ref, int x, int y, int z, @Nonnull ComponentAccessor componentAccessor) { return this.paste(ref, x, y, z, false, componentAccessor); } diff --git a/src/com/hypixel/hytale/builtin/buildertools/commands/LayerCommand.java b/src/com/hypixel/hytale/builtin/buildertools/commands/LayerCommand.java new file mode 100644 index 00000000..55269d41 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/buildertools/commands/LayerCommand.java @@ -0,0 +1,78 @@ +package com.hypixel.hytale.builtin.buildertools.commands; + +import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin; +import com.hypixel.hytale.builtin.buildertools.PrototypePlayerBuilderToolSettings; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.protocol.GameMode; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.command.system.CommandContext; +import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg; +import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import it.unimi.dsi.fastutil.Pair; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; + +public class LayerCommand extends AbstractPlayerCommand { + private static Map directions = Map.of( + "up", Vector3i.UP, "down", Vector3i.DOWN, "north", Vector3i.NORTH, "south", Vector3i.SOUTH, "east", Vector3i.EAST, "west", Vector3i.WEST + ); + @Nonnull + private final RequiredArg layerDirectionArg = this.withRequiredArg("direction", "server.commands.layer.direction.desc", ArgTypes.STRING); + @Nonnull + private final RequiredArg>> layersArg = this.withListRequiredArg( + "layers", "server.commands.layer.layers.desc", ArgTypes.LAYER_ENTRY_TYPE + ); + + public LayerCommand() { + super("layer", "server.commands.layer.desc"); + this.setPermissionGroup(GameMode.Creative); + this.requirePermission("hytale.editor.selection.clipboard"); + } + + @Override + protected void execute( + @Nonnull CommandContext context, @Nonnull Store store, @Nonnull Ref ref, @Nonnull PlayerRef playerRef, @Nonnull World world + ) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); + + assert playerComponent != null; + + if (PrototypePlayerBuilderToolSettings.isOkayToDoCommandsOnSelection(ref, playerComponent, store)) { + String direction = this.layerDirectionArg.get(context).toLowerCase(); + List> layers = this.layersArg.get(context); + if (layers != null && direction != null) { + boolean directionValid = directions.containsKey(direction); + if (directionValid) { + BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> { + HeadRotation headRotationComponent = componentAccessor.getComponent(ref, HeadRotation.getComponentType()); + + assert headRotationComponent != null; + + Vector3i layerDirection = Vector3i.ZERO; + if (direction.equalsIgnoreCase("camera")) { + layerDirection = headRotationComponent.getAxisDirection(); + } else { + layerDirection = directions.get(direction); + } + + s.layer(layers, layerDirection, componentAccessor); + }); + } else { + context.sendMessage(Message.translation("server.commands.layer.directionInvalid").param("direction", direction)); + context.sendMessage(Message.translation("server.commands.help.useHelpToLearnMore").param("command", this.getFullyQualifiedName())); + } + } else { + context.sendMessage(Message.translation("server.commands.help.useHelpToLearnMore").param("command", this.getFullyQualifiedName())); + } + } + } +} diff --git a/src/com/hypixel/hytale/builtin/buildertools/imageimport/ImageImportPage.java b/src/com/hypixel/hytale/builtin/buildertools/imageimport/ImageImportPage.java index 428a1c16..8c89424c 100644 --- a/src/com/hypixel/hytale/builtin/buildertools/imageimport/ImageImportPage.java +++ b/src/com/hypixel/hytale/builtin/buildertools/imageimport/ImageImportPage.java @@ -14,6 +14,7 @@ import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime; import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType; import com.hypixel.hytale.protocol.packets.interface_.Page; import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage; import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection; @@ -259,7 +260,9 @@ public class ImageImportPage extends InteractiveCustomUIPage pickupItemHolder = ItemComponent.generatePickedUpItem(targetRef, commandBuffer, ref, itemEntityPosition); + if (pickupItemHolder != null) { + commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); + } + } else if (!remainder.equals(itemStack)) { + int quantity = itemStack.getQuantity() - remainder.getQuantity(); + itemComponent.setItemStack(remainder); + Holder pickupItemHolder = ItemComponent.generatePickedUpItem(targetRef, commandBuffer, ref, itemEntityPosition); + if (pickupItemHolder != null) { + commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); + } - ItemContainer itemContainer = playerComponent.getInventory().getContainerForItemPickup(item, playerSettings); - ItemStackTransaction transaction = itemContainer.addItemStack(itemStack); - ItemStack remainder = transaction.getRemainder(); - if (ItemStack.isEmpty(remainder)) { - itemComponent.setRemovedByPlayerPickup(true); - commandBuffer.removeEntity(targetRef, RemoveReason.REMOVE); - playerComponent.notifyPickupItem(ref, itemStack, itemEntityPosition, commandBuffer); - Holder pickupItemHolder = ItemComponent.generatePickedUpItem(targetRef, commandBuffer, ref, itemEntityPosition); - commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); - } else if (!remainder.equals(itemStack)) { - int quantity = itemStack.getQuantity() - remainder.getQuantity(); - itemComponent.setItemStack(remainder); - Holder pickupItemHolder = ItemComponent.generatePickedUpItem(targetRef, commandBuffer, ref, itemEntityPosition); - commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); - if (quantity > 0) { - playerComponent.notifyPickupItem(ref, itemStack.withQuantity(quantity), itemEntityPosition, commandBuffer); + if (quantity > 0) { + playerComponent.notifyPickupItem(ref, itemStack.withQuantity(quantity), itemEntityPosition, commandBuffer); + } } } } diff --git a/src/com/hypixel/hytale/builtin/buildertools/objimport/ObjImportPage.java b/src/com/hypixel/hytale/builtin/buildertools/objimport/ObjImportPage.java index 6fecf350..ff8026c0 100644 --- a/src/com/hypixel/hytale/builtin/buildertools/objimport/ObjImportPage.java +++ b/src/com/hypixel/hytale/builtin/buildertools/objimport/ObjImportPage.java @@ -6,6 +6,7 @@ import com.hypixel.hytale.builtin.buildertools.utils.PasteToolUtil; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.common.util.StringUtil; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; @@ -14,6 +15,7 @@ import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime; import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType; import com.hypixel.hytale.protocol.packets.interface_.Page; import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage; @@ -401,12 +403,14 @@ public class ObjImportPage extends InteractiveCustomUIPage ref, @Nonnull Store store) { if (this.objPath.isEmpty()) { this.setError("Please enter a path to an OBJ file"); + } else if (!this.objPath.toLowerCase().endsWith(".obj")) { + this.setError("File must be a .obj file"); } else { Path path = Paths.get(this.objPath); - if (!Files.exists(path)) { + if (!AssetModule.get().isWithinPackSubDir(path, "Server/Imports/Models")) { + this.setError("File must be within an asset pack's imports directory"); + } else if (!Files.exists(path)) { this.setError("File not found: " + this.objPath); - } else if (!this.objPath.toLowerCase().endsWith(".obj")) { - this.setError("File must be a .obj file"); } else { List blocks = this.parseBlockPattern(this.blockPattern); if (blocks == null) { @@ -577,8 +581,8 @@ public class ObjImportPage extends InteractiveCustomUIPage materials = MtlParser.parse(mtlPath); Path textureDir = mtlPath.getParent(); @@ -591,7 +595,11 @@ public class ObjImportPage extends InteractiveCustomUIPage { this.buildFileList(commandBuilder, eventBuilder); this.sendUpdate(commandBuilder, eventBuilder, false); } else { - Path file; - if (isSearchResult) { - file = this.browser.resolveSecure(selectedPath); - } else { - file = this.browser.resolveFromCurrent(selectedPath); - } - + Path baseDir = isSearchResult ? this.browser.getRoot() : this.browser.getRoot().resolve(this.browser.getCurrentDir().toString()); + Path file = PathUtil.resolvePathWithinDir(baseDir, selectedPath); if (file != null && !Files.isDirectory(file)) { this.handlePrefabSelection(ref, store, file, selectedPath); } else { diff --git a/src/com/hypixel/hytale/builtin/buildertools/scriptedbrushes/operations/sequential/LayerOperation.java b/src/com/hypixel/hytale/builtin/buildertools/scriptedbrushes/operations/sequential/LayerOperation.java index 192066cd..5ab44dcf 100644 --- a/src/com/hypixel/hytale/builtin/buildertools/scriptedbrushes/operations/sequential/LayerOperation.java +++ b/src/com/hypixel/hytale/builtin/buildertools/scriptedbrushes/operations/sequential/LayerOperation.java @@ -1,5 +1,6 @@ package com.hypixel.hytale.builtin.buildertools.scriptedbrushes.operations.sequential; +import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.BrushConfig; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.BrushConfigCommandExecutor; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.BrushConfigEditStore; @@ -9,13 +10,18 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; -import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; +import com.hypixel.hytale.math.util.ChunkUtil; +import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.server.core.asset.type.buildertool.config.BuilderTool; import com.hypixel.hytale.server.core.codec.LayerEntryCodec; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.inventory.ItemStack; import com.hypixel.hytale.server.core.prefab.selection.mask.BlockPattern; +import com.hypixel.hytale.server.core.universe.PlayerRef; +import com.hypixel.hytale.server.core.universe.world.accessor.BlockAccessor; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import it.unimi.dsi.fastutil.Pair; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -51,58 +57,50 @@ public class LayerOperation extends SequenceBrushOperation { int z, ComponentAccessor componentAccessor ) { - int maxDepth = 0; + Player playerComponent = componentAccessor.getComponent(ref, Player.getComponentType()); - for (LayerEntryCodec entry : this.layerArgs) { - maxDepth += entry.getDepth(); - } + assert playerComponent != null; + PlayerRef playerRefComponent = componentAccessor.getComponent(ref, PlayerRef.getComponentType()); + + assert playerRefComponent != null; + + BuilderToolsPlugin.BuilderState builderState = BuilderToolsPlugin.getState(playerComponent, playerRefComponent); if (edit.getBlock(x, y, z) <= 0) { return true; } else { Map toolArgs = this.getToolArgs(ref, componentAccessor); + List> layers = new ArrayList<>(); + int maxDepth = 0; - for (int depth = 0; depth < maxDepth; depth++) { - if (edit.getBlock(x, y + depth + 1, z) <= 0) { - int depthTestingAt = 0; - - for (LayerEntryCodec entry : this.layerArgs) { - depthTestingAt += entry.getDepth(); - if (depth < depthTestingAt) { - if (entry.isSkip()) { - return true; - } - - int blockId = this.resolveBlockId(entry, toolArgs, brushConfig); - if (blockId >= 0) { - edit.setBlock(x, y, z, blockId); - } - - return true; - } - } + for (LayerEntryCodec layer : this.layerArgs) { + if (!layer.isSkip()) { + maxDepth += layer.getDepth(); + layers.add(Pair.of(layer.getDepth(), this.resolveBlockPattern(layer, toolArgs, brushConfig))); } } + BlockAccessor chunk = edit.getAccessor().getChunk(ChunkUtil.indexChunkFromBlock(x, z)); + builderState.layer(x, y, z, layers, maxDepth, Vector3i.DOWN, (WorldChunk)chunk, edit.getBefore(), edit.getAfter()); return true; } } - private int resolveBlockId(LayerEntryCodec entry, @Nullable Map toolArgs, BrushConfig brushConfig) { + private String resolveBlockPattern(LayerEntryCodec entry, @Nullable Map toolArgs, BrushConfig brushConfig) { if (entry.isUseToolArg()) { if (toolArgs != null && toolArgs.containsKey(entry.getMaterial())) { if (toolArgs.get(entry.getMaterial()) instanceof BlockPattern blockPattern) { - return blockPattern.nextBlock(brushConfig.getRandom()); + return blockPattern.toString(); } else { brushConfig.setErrorFlag("Layer: Tool arg '" + entry.getMaterial() + "' is not a Block type"); - return -1; + return ""; } } else { brushConfig.setErrorFlag("Layer: Tool arg '" + entry.getMaterial() + "' not found"); - return -1; + return ""; } } else { - return BlockType.getAssetMap().getIndex(entry.getMaterial()); + return entry.getMaterial(); } } diff --git a/src/com/hypixel/hytale/builtin/buildertools/tooloperations/LayersOperation.java b/src/com/hypixel/hytale/builtin/buildertools/tooloperations/LayersOperation.java index 53bbd6f0..ad7e5153 100644 --- a/src/com/hypixel/hytale/builtin/buildertools/tooloperations/LayersOperation.java +++ b/src/com/hypixel/hytale/builtin/buildertools/tooloperations/LayersOperation.java @@ -2,13 +2,18 @@ package com.hypixel.hytale.builtin.buildertools.tooloperations; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolOnUseInteraction; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; -import com.hypixel.hytale.server.core.prefab.selection.mask.BlockPattern; +import com.hypixel.hytale.server.core.universe.world.accessor.BlockAccessor; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import it.unimi.dsi.fastutil.Pair; +import java.util.ArrayList; +import java.util.List; import javax.annotation.Nonnull; public class LayersOperation extends ToolOperation { @@ -18,17 +23,16 @@ public class LayersOperation extends ToolOperation { private final boolean enableLayerTwo; private final int layerThreeLength; private final boolean enableLayerThree; - private final BlockPattern layerOneBlockPattern; - private final BlockPattern layerTwoBlockPattern; - private final BlockPattern layerThreeBlockPattern; + private final String layerOneBlockPattern; + private final String layerTwoBlockPattern; + private final String layerThreeBlockPattern; private final int brushDensity; private final int maxDepthNecessary; private boolean failed; - private final int layerTwoDepthEnd; - private final int layerThreeDepthEnd; private final boolean skipLayerOne; private final boolean skipLayerTwo; private final boolean skipLayerThree; + private List> layers; public LayersOperation( @Nonnull Ref ref, @@ -72,17 +76,28 @@ public class LayersOperation extends ToolOperation { this.layerOneLength = (Integer)this.args.tool().get("bLayerOneLength"); this.layerTwoLength = (Integer)this.args.tool().get("eLayerTwoLength"); this.layerThreeLength = (Integer)this.args.tool().get("hLayerThreeLength"); - this.layerOneBlockPattern = (BlockPattern)this.args.tool().get("cLayerOneMaterial"); - this.layerTwoBlockPattern = (BlockPattern)this.args.tool().get("fLayerTwoMaterial"); - this.layerThreeBlockPattern = (BlockPattern)this.args.tool().get("iLayerThreeMaterial"); + this.layerOneBlockPattern = this.args.tool().get("cLayerOneMaterial").toString(); + this.layerTwoBlockPattern = this.args.tool().get("fLayerTwoMaterial").toString(); + this.layerThreeBlockPattern = this.args.tool().get("iLayerThreeMaterial").toString(); this.enableLayerTwo = (Boolean)this.args.tool().get("dEnableLayerTwo"); this.enableLayerThree = (Boolean)this.args.tool().get("gEnableLayerThree"); this.skipLayerOne = (Boolean)this.args.tool().getOrDefault("kSkipLayerOne", false); this.skipLayerTwo = (Boolean)this.args.tool().getOrDefault("lSkipLayerTwo", false); this.skipLayerThree = (Boolean)this.args.tool().getOrDefault("mSkipLayerThree", false); + this.layers = new ArrayList<>(); + if (!this.skipLayerOne) { + this.layers.add(Pair.of(this.layerOneLength, this.layerOneBlockPattern)); + } + + if (!this.skipLayerTwo && this.enableLayerTwo) { + this.layers.add(Pair.of(this.layerTwoLength, this.layerTwoBlockPattern)); + } + + if (!this.skipLayerThree && this.enableLayerThree) { + this.layers.add(Pair.of(this.layerThreeLength, this.layerThreeBlockPattern)); + } + this.maxDepthNecessary = this.layerOneLength + (this.enableLayerTwo ? this.layerTwoLength : 0) + (this.enableLayerThree ? this.layerThreeLength : 0); - this.layerTwoDepthEnd = this.layerOneLength + this.layerTwoLength; - this.layerThreeDepthEnd = this.layerTwoDepthEnd + this.layerThreeLength; if (this.enableLayerThree && !this.enableLayerTwo) { player.sendMessage(Message.translation("server.builderTools.layerOperation.layerTwoRequired")); this.failed = true; @@ -95,75 +110,13 @@ public class LayersOperation extends ToolOperation { return false; } else if (this.random.nextInt(100) > this.brushDensity) { return true; - } else { - int currentBlock = this.edit.getBlock(x, y, z); - if (currentBlock <= 0) { - return true; - } else { - if (this.depthDirection.x == 1) { - for (int i = 0; i < this.maxDepthNecessary; i++) { - if (this.edit.getBlock(x - i - 1, y, z) <= 0 && this.attemptSetBlock(x, y, z, i)) { - return true; - } - } - } else if (this.depthDirection.x == -1) { - for (int ix = 0; ix < this.maxDepthNecessary; ix++) { - if (this.edit.getBlock(x + ix + 1, y, z) <= 0 && this.attemptSetBlock(x, y, z, ix)) { - return true; - } - } - } else if (this.depthDirection.y == 1) { - for (int ixx = 0; ixx < this.maxDepthNecessary; ixx++) { - if (this.edit.getBlock(x, y - ixx - 1, z) <= 0 && this.attemptSetBlock(x, y, z, ixx)) { - return true; - } - } - } else if (this.depthDirection.y == -1) { - for (int ixxx = 0; ixxx < this.maxDepthNecessary; ixxx++) { - if (this.edit.getBlock(x, y + ixxx + 1, z) <= 0 && this.attemptSetBlock(x, y, z, ixxx)) { - return true; - } - } - } else if (this.depthDirection.z == 1) { - for (int ixxxx = 0; ixxxx < this.maxDepthNecessary; ixxxx++) { - if (this.edit.getBlock(x, y, z - ixxxx - 1) <= 0 && this.attemptSetBlock(x, y, z, ixxxx)) { - return true; - } - } - } else if (this.depthDirection.z == -1) { - for (int ixxxxx = 0; ixxxxx < this.maxDepthNecessary; ixxxxx++) { - if (this.edit.getBlock(x, y, z + ixxxxx + 1) <= 0 && this.attemptSetBlock(x, y, z, ixxxxx)) { - return true; - } - } - } - - return true; - } - } - } - - public boolean attemptSetBlock(int x, int y, int z, int depth) { - if (depth < this.layerOneLength) { - if (!this.skipLayerOne) { - this.edit.setBlock(x, y, z, this.layerOneBlockPattern.nextBlock(this.random)); - } - - return true; - } else if (this.enableLayerTwo && depth < this.layerTwoDepthEnd) { - if (!this.skipLayerTwo && !this.layerTwoBlockPattern.isEmpty()) { - this.edit.setBlock(x, y, z, this.layerTwoBlockPattern.nextBlock(this.random)); - } - - return true; - } else if (this.enableLayerThree && depth < this.layerThreeDepthEnd) { - if (!this.skipLayerThree && !this.layerThreeBlockPattern.isEmpty()) { - this.edit.setBlock(x, y, z, this.layerThreeBlockPattern.nextBlock(this.random)); - } - + } else if (this.edit.getBlock(x, y, z) <= 0) { return true; } else { - return false; + BlockAccessor chunk = this.edit.getAccessor().getChunk(ChunkUtil.indexChunkFromBlock(x, z)); + this.builderState + .layer(x, y, z, this.layers, this.maxDepthNecessary, this.depthDirection, (WorldChunk)chunk, this.edit.getBefore(), this.edit.getAfter()); + return true; } } } diff --git a/src/com/hypixel/hytale/builtin/commandmacro/EchoCommand.java b/src/com/hypixel/hytale/builtin/commandmacro/EchoCommand.java index bfcd8eab..e740212f 100644 --- a/src/com/hypixel/hytale/builtin/commandmacro/EchoCommand.java +++ b/src/com/hypixel/hytale/builtin/commandmacro/EchoCommand.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase; import javax.annotation.Nonnull; public class EchoCommand extends CommandBase { + @Nonnull private final RequiredArg messageArg = this.withRequiredArg("message", "server.commands.echos.message.desc", ArgTypes.STRING); public EchoCommand() { diff --git a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBase.java b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBase.java index ce5cb7a1..ec895e06 100644 --- a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBase.java +++ b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBase.java @@ -24,9 +24,15 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class MacroCommandBase extends AbstractAsyncCommand { + @Nonnull public static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + @Nonnull private static final Pattern regexBracketPattern = Pattern.compile("\\{(.*?)}"); + @Nonnull + private static final Pattern PATTERN = Pattern.compile("\\\\\\{"); + @Nonnull private final Map> arguments = new Object2ObjectOpenHashMap<>(); + @Nonnull private final List>> commandReplacements = new ObjectArrayList<>(); private final Map defaultValueStrings = new Object2ObjectOpenHashMap<>(); @@ -96,7 +102,7 @@ public class MacroCommandBase extends AbstractAsyncCommand { } } - command = command.replaceAll("\\\\\\{", "{"); + command = PATTERN.matcher(command).replaceAll("{"); commands[i] = command; this.commandReplacements.add(Pair.of(command, replacements)); } diff --git a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBuilder.java b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBuilder.java index affae38f..899e0736 100644 --- a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBuilder.java +++ b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandBuilder.java @@ -12,6 +12,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class MacroCommandBuilder implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( MacroCommandBuilder.class, MacroCommandBuilder::new, diff --git a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandParameter.java b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandParameter.java index ddd056d2..0e814bca 100644 --- a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandParameter.java +++ b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandParameter.java @@ -6,8 +6,10 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.EnumCodec; import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; import com.hypixel.hytale.server.core.command.system.arguments.types.ArgumentType; +import javax.annotation.Nonnull; public class MacroCommandParameter { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(MacroCommandParameter.class, MacroCommandParameter::new) .append(new KeyedCodec<>("Name", Codec.STRING, true), (macroParameter, name) -> macroParameter.name = name, macroParameter -> macroParameter.name) .add() diff --git a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandPlugin.java b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandPlugin.java index 0993f281..e8c6d6da 100644 --- a/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandPlugin.java +++ b/src/com/hypixel/hytale/builtin/commandmacro/MacroCommandPlugin.java @@ -13,6 +13,7 @@ import javax.annotation.Nonnull; public class MacroCommandPlugin extends JavaPlugin { private static MacroCommandPlugin instance; + @Nonnull private final Map macroCommandRegistrations = new Object2ObjectOpenHashMap<>(); public static MacroCommandPlugin get() { diff --git a/src/com/hypixel/hytale/builtin/commandmacro/WaitCommand.java b/src/com/hypixel/hytale/builtin/commandmacro/WaitCommand.java index 348fe1b4..0e71b7f8 100644 --- a/src/com/hypixel/hytale/builtin/commandmacro/WaitCommand.java +++ b/src/com/hypixel/hytale/builtin/commandmacro/WaitCommand.java @@ -14,10 +14,13 @@ import javax.annotation.Nonnull; public class WaitCommand extends AbstractAsyncCommand { private static final long MILLISECONDS_TO_SECONDS_MULTIPLIER = 1000L; + @Nonnull public static final Runnable EMPTY_RUNNABLE = () -> {}; + @Nonnull private final RequiredArg timeArg = this.withRequiredArg("time", "server.commands.wait.arg.time", ArgTypes.FLOAT) .addValidator(Validators.greaterThan(0.0F)) .addValidator(Validators.lessThan(1000.0F)); + @Nonnull private final FlagArg printArg = this.withFlagArg("print", "server.commands.wait.arg.print"); public WaitCommand() { diff --git a/src/com/hypixel/hytale/builtin/crafting/BenchRecipeRegistry.java b/src/com/hypixel/hytale/builtin/crafting/BenchRecipeRegistry.java index 86f5ead6..6f2cf69a 100644 --- a/src/com/hypixel/hytale/builtin/crafting/BenchRecipeRegistry.java +++ b/src/com/hypixel/hytale/builtin/crafting/BenchRecipeRegistry.java @@ -19,16 +19,22 @@ import javax.annotation.Nullable; public class BenchRecipeRegistry { private final String benchId; + @Nonnull private final Map> categoryMap = new Object2ObjectOpenHashMap<>(); + @Nonnull private final Map> itemToIncomingRecipe = new Object2ObjectOpenHashMap<>(); + @Nonnull private final Set uncategorizedRecipes = new ObjectOpenHashSet<>(); + @Nonnull private final Set allMaterialIds = new ObjectOpenHashSet<>(); + @Nonnull private final Set allMaterialResourceType = new ObjectOpenHashSet<>(); public BenchRecipeRegistry(String benchId) { this.benchId = benchId; } + @Nonnull public Iterable getIncomingRecipesForItem(@Nonnull String itemId) { Set recipes = this.itemToIncomingRecipe.get(itemId); return recipes == null ? Collections.emptySet() : recipes; @@ -88,7 +94,7 @@ public class BenchRecipeRegistry { this.extractMaterialFromRecipes(this.uncategorizedRecipes); } - private void extractMaterialFromRecipes(Set recipes) { + private void extractMaterialFromRecipes(@Nonnull Set recipes) { for (String recipeId : recipes) { CraftingRecipe recipe = CraftingRecipe.getAssetMap().getAsset(recipeId); if (recipe != null) { @@ -141,7 +147,7 @@ public class BenchRecipeRegistry { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o != null && this.getClass() == o.getClass()) { BenchRecipeRegistry that = (BenchRecipeRegistry)o; return Objects.equals(this.benchId, that.benchId) @@ -159,6 +165,7 @@ public class BenchRecipeRegistry { return Objects.hash(this.benchId, this.categoryMap, this.uncategorizedRecipes, this.allMaterialIds, this.allMaterialResourceType); } + @Nonnull @Override public String toString() { return "BenchRecipeRegistry{benchId='" diff --git a/src/com/hypixel/hytale/builtin/crafting/CraftingPlugin.java b/src/com/hypixel/hytale/builtin/crafting/CraftingPlugin.java index d7f1f144..e77b1bba 100644 --- a/src/com/hypixel/hytale/builtin/crafting/CraftingPlugin.java +++ b/src/com/hypixel/hytale/builtin/crafting/CraftingPlugin.java @@ -25,6 +25,7 @@ import com.hypixel.hytale.component.RemoveReason; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.RefSystem; +import com.hypixel.hytale.event.EventRegistry; import com.hypixel.hytale.protocol.BenchRequirement; import com.hypixel.hytale.protocol.BenchType; import com.hypixel.hytale.protocol.ItemResourceType; @@ -59,7 +60,9 @@ import javax.annotation.Nullable; public class CraftingPlugin extends JavaPlugin { private static CraftingPlugin instance; + @Nonnull private static final Map registries = new Object2ObjectOpenHashMap<>(); + @Nonnull private static final Map itemGeneratedRecipes = new Object2ObjectOpenHashMap<>(); private ComponentType craftingManagerComponentType; @@ -69,17 +72,17 @@ public class CraftingPlugin extends JavaPlugin { } @Nullable - public static Set getAvailableRecipesForCategory(String benchId, String benchCategoryId) { + public static Set getAvailableRecipesForCategory(@Nonnull String benchId, @Nonnull String benchCategoryId) { BenchRecipeRegistry benchRecipeRegistry = registries.get(benchId); return benchRecipeRegistry == null ? null : benchRecipeRegistry.getRecipesForCategory(benchCategoryId); } - public static boolean isValidCraftingMaterialForBench(BenchState benchState, ItemStack itemStack) { + public static boolean isValidCraftingMaterialForBench(@Nonnull BenchState benchState, @Nonnull ItemStack itemStack) { BenchRecipeRegistry benchRecipeRegistry = registries.get(benchState.getBench().getId()); return benchRecipeRegistry == null ? false : benchRecipeRegistry.isValidCraftingMaterial(itemStack); } - public static boolean isValidUpgradeMaterialForBench(BenchState benchState, ItemStack itemStack) { + public static boolean isValidUpgradeMaterialForBench(@Nonnull BenchState benchState, @Nonnull ItemStack itemStack) { BenchUpgradeRequirement nextLevelUpgradeMaterials = benchState.getNextLevelUpgradeMaterials(); if (nextLevelUpgradeMaterials == null) { return false; @@ -92,7 +95,7 @@ public class CraftingPlugin extends JavaPlugin { ItemResourceType[] resourceTypeId = itemStack.getItem().getResourceTypes(); if (resourceTypeId != null) { for (ItemResourceType resTypeId : resourceTypeId) { - if (resTypeId.id.equals(upgradeMaterial.getResourceTypeId())) { + if (resTypeId.id != null && resTypeId.id.equals(upgradeMaterial.getResourceTypeId())) { return true; } } @@ -118,10 +121,8 @@ public class CraftingPlugin extends JavaPlugin { ) ); ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); + EventRegistry eventRegistry = this.getEventRegistry(); this.craftingManagerComponentType = entityStoreRegistry.registerComponent(CraftingManager.class, CraftingManager::new); - entityStoreRegistry.registerSystem(new PlayerCraftingSystems.CraftingTickingSystem(this.craftingManagerComponentType)); - entityStoreRegistry.registerSystem(new PlayerCraftingSystems.CraftingHolderSystem(this.craftingManagerComponentType)); - entityStoreRegistry.registerSystem(new PlayerCraftingSystems.CraftingRefSystem(this.craftingManagerComponentType)); this.getCodecRegistry(Interaction.CODEC) .register("OpenBenchPage", OpenBenchPageInteraction.class, OpenBenchPageInteraction.CODEC) .register("OpenProcessingBench", OpenProcessingBenchInteraction.class, OpenProcessingBenchInteraction.CODEC); @@ -132,16 +133,21 @@ public class CraftingPlugin extends JavaPlugin { blockStateRegistry.registerBlockState(ProcessingBenchState.class, "processingBench", ProcessingBenchState.CODEC); blockStateRegistry.registerBlockState(BenchState.class, "crafting", BenchState.CODEC); Window.CLIENT_REQUESTABLE_WINDOW_TYPES.put(WindowType.PocketCrafting, FieldCraftingWindow::new); - this.getEventRegistry().register(LoadedAssetsEvent.class, CraftingRecipe.class, CraftingPlugin::onRecipeLoad); - this.getEventRegistry().register(RemovedAssetsEvent.class, CraftingRecipe.class, CraftingPlugin::onRecipeRemove); - this.getEventRegistry().register(LoadedAssetsEvent.class, Item.class, CraftingPlugin::onItemAssetLoad); - this.getEventRegistry().register(RemovedAssetsEvent.class, Item.class, CraftingPlugin::onItemAssetRemove); + eventRegistry.register(LoadedAssetsEvent.class, CraftingRecipe.class, CraftingPlugin::onRecipeLoad); + eventRegistry.register(RemovedAssetsEvent.class, CraftingRecipe.class, CraftingPlugin::onRecipeRemove); + eventRegistry.register(LoadedAssetsEvent.class, Item.class, CraftingPlugin::onItemAssetLoad); + eventRegistry.register(RemovedAssetsEvent.class, Item.class, CraftingPlugin::onItemAssetRemove); Interaction.CODEC.register("LearnRecipe", LearnRecipeInteraction.class, LearnRecipeInteraction.CODEC); CommandManager.get().registerSystemCommand(new RecipeCommand()); - entityStoreRegistry.registerSystem(new CraftingPlugin.PlayerAddedSystem()); + ComponentType playerComponentType = Player.getComponentType(); + ComponentType playerRefComponentType = PlayerRef.getComponentType(); + entityStoreRegistry.registerSystem(new PlayerCraftingSystems.CraftingTickingSystem(this.craftingManagerComponentType)); + entityStoreRegistry.registerSystem(new PlayerCraftingSystems.CraftingHolderSystem(playerComponentType, this.craftingManagerComponentType)); + entityStoreRegistry.registerSystem(new PlayerCraftingSystems.CraftingRefSystem(playerComponentType, this.craftingManagerComponentType)); + entityStoreRegistry.registerSystem(new CraftingPlugin.PlayerAddedSystem(playerComponentType, playerRefComponentType)); } - private static void onItemAssetLoad(LoadedAssetsEvent> event) { + private static void onItemAssetLoad(@Nonnull LoadedAssetsEvent> event) { List recipesToLoad = new ObjectArrayList<>(); for (Item item : event.getLoadedAssets().values()) { @@ -174,7 +180,7 @@ public class CraftingPlugin extends JavaPlugin { } } - private static void onRecipeLoad(LoadedAssetsEvent> event) { + private static void onRecipeLoad(@Nonnull LoadedAssetsEvent> event) { for (CraftingRecipe recipe : event.getLoadedAssets().values()) { for (BenchRecipeRegistry registry : registries.values()) { registry.removeRecipe(recipe.getId()); @@ -191,7 +197,7 @@ public class CraftingPlugin extends JavaPlugin { computeBenchRecipeRegistries(); } - private static void onRecipeRemove(RemovedAssetsEvent> event) { + private static void onRecipeRemove(@Nonnull RemovedAssetsEvent> event) { for (String removedRecipeId : event.getRemovedAssets()) { for (BenchRecipeRegistry registry : registries.values()) { registry.removeRecipe(removedRecipeId); @@ -322,11 +328,19 @@ public class CraftingPlugin extends JavaPlugin { } public static class PlayerAddedSystem extends RefSystem { - private static final Query QUERY = Archetype.of(Player.getComponentType(), PlayerRef.getComponentType()); + @Nonnull + private final Query query; + public PlayerAddedSystem( + @Nonnull ComponentType playerComponentType, @Nonnull ComponentType playerRefComponentType + ) { + this.query = Archetype.of(playerComponentType, playerRefComponentType); + } + + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } @Override diff --git a/src/com/hypixel/hytale/builtin/crafting/component/CraftingManager.java b/src/com/hypixel/hytale/builtin/crafting/component/CraftingManager.java index ab29b794..aaa9155a 100644 --- a/src/com/hypixel/hytale/builtin/crafting/component/CraftingManager.java +++ b/src/com/hypixel/hytale/builtin/crafting/component/CraftingManager.java @@ -49,6 +49,7 @@ import com.hypixel.hytale.server.core.inventory.container.filter.FilterType; import com.hypixel.hytale.server.core.inventory.transaction.ListTransaction; import com.hypixel.hytale.server.core.inventory.transaction.MaterialSlotTransaction; import com.hypixel.hytale.server.core.inventory.transaction.MaterialTransaction; +import com.hypixel.hytale.server.core.modules.entity.player.PlayerSettings; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.SoundUtil; import com.hypixel.hytale.server.core.universe.world.World; @@ -422,7 +423,18 @@ public class CraftingManager implements Component { } else { List itemStacks = getOutputItemStacks(craftingRecipe, quantity); Inventory inventory = playerComponent.getInventory(); - SimpleItemContainer.addOrDropItemStacks(componentAccessor, ref, inventory.getCombinedArmorHotbarStorage(), itemStacks); + PlayerSettings playerSettings = componentAccessor.getComponent(ref, PlayerSettings.getComponentType()); + if (playerSettings == null) { + playerSettings = PlayerSettings.defaults(); + } + + for (ItemStack itemStack : itemStacks) { + if (!ItemStack.isEmpty(itemStack)) { + SimpleItemContainer.addOrDropItemStack( + componentAccessor, ref, inventory.getContainerForItemPickup(itemStack.getItem(), playerSettings), itemStack + ); + } + } } } @@ -872,6 +884,7 @@ public class CraftingManager implements Component { this.timeSeconds = timeSeconds; } + @Nonnull @Override public String toString() { return "BenchUpgradingJob{window=" + this.window + ", timeSeconds=" + this.timeSeconds + "}"; diff --git a/src/com/hypixel/hytale/builtin/crafting/interaction/LearnRecipeInteraction.java b/src/com/hypixel/hytale/builtin/crafting/interaction/LearnRecipeInteraction.java index e9f4f743..e85b004e 100644 --- a/src/com/hypixel/hytale/builtin/crafting/interaction/LearnRecipeInteraction.java +++ b/src/com/hypixel/hytale/builtin/crafting/interaction/LearnRecipeInteraction.java @@ -24,6 +24,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class LearnRecipeInteraction extends SimpleInstantInteraction { + @Nonnull public static final KeyedCodec ITEM_ID = new KeyedCodec<>("ItemId", Codec.STRING); @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( @@ -35,7 +36,6 @@ public class LearnRecipeInteraction extends SimpleInstantInteraction { ) .add() .build(); - public static final Message MESSAGE_MODULES_LEARN_RECIPE_INVALID_ITEM = Message.translation("server.modules.learnrecipe.invalidItem"); @Nullable protected String itemId; diff --git a/src/com/hypixel/hytale/builtin/crafting/interaction/OpenBenchPageInteraction.java b/src/com/hypixel/hytale/builtin/crafting/interaction/OpenBenchPageInteraction.java index 956bc48e..be748414 100644 --- a/src/com/hypixel/hytale/builtin/crafting/interaction/OpenBenchPageInteraction.java +++ b/src/com/hypixel/hytale/builtin/crafting/interaction/OpenBenchPageInteraction.java @@ -30,17 +30,23 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class OpenBenchPageInteraction extends SimpleBlockInteraction { + @Nonnull public static final OpenBenchPageInteraction SIMPLE_CRAFTING = new OpenBenchPageInteraction( "*Simple_Crafting_Default", OpenBenchPageInteraction.PageType.SIMPLE_CRAFTING ); + @Nonnull public static final RootInteraction SIMPLE_CRAFTING_ROOT = new RootInteraction(SIMPLE_CRAFTING.getId(), SIMPLE_CRAFTING.getId()); + @Nonnull public static final OpenBenchPageInteraction DIAGRAM_CRAFTING = new OpenBenchPageInteraction( "*Diagram_Crafting_Default", OpenBenchPageInteraction.PageType.DIAGRAM_CRAFTING ); + @Nonnull public static final RootInteraction DIAGRAM_CRAFTING_ROOT = new RootInteraction(DIAGRAM_CRAFTING.getId(), DIAGRAM_CRAFTING.getId()); + @Nonnull public static final OpenBenchPageInteraction STRUCTURAL_CRAFTING = new OpenBenchPageInteraction( "*Structural_Crafting_Default", OpenBenchPageInteraction.PageType.STRUCTURAL_CRAFTING ); + @Nonnull public static final RootInteraction STRUCTURAL_CRAFTING_ROOT = new RootInteraction(STRUCTURAL_CRAFTING.getId(), STRUCTURAL_CRAFTING.getId()); @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( diff --git a/src/com/hypixel/hytale/builtin/crafting/interaction/OpenProcessingBenchInteraction.java b/src/com/hypixel/hytale/builtin/crafting/interaction/OpenProcessingBenchInteraction.java index 9d7653d9..e80f2fa0 100644 --- a/src/com/hypixel/hytale/builtin/crafting/interaction/OpenProcessingBenchInteraction.java +++ b/src/com/hypixel/hytale/builtin/crafting/interaction/OpenProcessingBenchInteraction.java @@ -33,6 +33,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class OpenProcessingBenchInteraction extends SimpleBlockInteraction { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( OpenProcessingBenchInteraction.class, OpenProcessingBenchInteraction::new, SimpleBlockInteraction.CODEC ) @@ -83,7 +84,7 @@ public class OpenProcessingBenchInteraction extends SimpleBlockInteraction { if (currentBlockType != null) { String interactionState = BlockAccessor.getCurrentInteractionState(currentBlockType); if (windows.isEmpty() && !"Processing".equals(interactionState) && !"ProcessCompleted".equals(interactionState)) { - world.setBlockInteractionState(pos, currentBlockType, "default"); + world.setBlockInteractionState(pos, benchState.getBaseBlockType(), benchState.getTierStateName()); } int soundEventIndexx = blockType.getBench().getLocalCloseSoundEventIndex(); diff --git a/src/com/hypixel/hytale/builtin/crafting/state/BenchState.java b/src/com/hypixel/hytale/builtin/crafting/state/BenchState.java index dc92c06f..c3784e24 100644 --- a/src/com/hypixel/hytale/builtin/crafting/state/BenchState.java +++ b/src/com/hypixel/hytale/builtin/crafting/state/BenchState.java @@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public class BenchState extends BlockState implements DestroyableBlockState { + @Nonnull public static BuilderCodec CODEC = BuilderCodec.builder(BenchState.class, BenchState::new, BlockState.BASE_CODEC) .appendInherited( new KeyedCodec<>("TierLevel", Codec.INTEGER), @@ -47,6 +48,7 @@ public class BenchState extends BlockState implements DestroyableBlockState { private int tierLevel = 1; protected ItemStack[] upgradeItems = ItemStack.EMPTY_ARRAY; protected Bench bench; + @Nonnull protected final Map windows = new ConcurrentHashMap<>(); public int getTierLevel() { @@ -71,7 +73,7 @@ public class BenchState extends BlockState implements DestroyableBlockState { } } - public void addUpgradeItems(List consumed) { + public void addUpgradeItems(@Nonnull List consumed) { consumed.addAll(Arrays.asList(this.upgradeItems)); this.upgradeItems = consumed.toArray(ItemStack[]::new); this.markNeedsSave(); @@ -111,6 +113,7 @@ public class BenchState extends BlockState implements DestroyableBlockState { this.getChunk().setBlockInteractionState(this.getBlockPosition(), this.getBaseBlockType(), this.getTierStateName()); } + @Nonnull public BlockType getBaseBlockType() { BlockType currentBlockType = this.getBlockType(); String baseBlockKey = currentBlockType.getDefaultStateKey(); @@ -122,6 +125,7 @@ public class BenchState extends BlockState implements DestroyableBlockState { return baseBlockType; } + @Nonnull public String getTierStateName() { return this.tierLevel > 1 ? "Tier" + this.tierLevel : "default"; } diff --git a/src/com/hypixel/hytale/builtin/crafting/state/ProcessingBenchState.java b/src/com/hypixel/hytale/builtin/crafting/state/ProcessingBenchState.java index e6fc1390..25fbd709 100644 --- a/src/com/hypixel/hytale/builtin/crafting/state/ProcessingBenchState.java +++ b/src/com/hypixel/hytale/builtin/crafting/state/ProcessingBenchState.java @@ -16,6 +16,7 @@ import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.event.EventPriority; import com.hypixel.hytale.logger.HytaleLogger; +import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.util.MathUtil; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; @@ -48,6 +49,7 @@ import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent; import com.hypixel.hytale.server.core.universe.world.SoundUtil; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.accessor.BlockAccessor; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.chunk.state.TickableBlockState; import com.hypixel.hytale.server.core.universe.world.meta.BlockState; import com.hypixel.hytale.server.core.universe.world.meta.state.DestroyableBlockState; @@ -70,8 +72,10 @@ import javax.annotation.Nullable; import org.bson.BsonDocument; public class ProcessingBenchState extends BenchState implements TickableBlockState, ItemContainerBlockState, DestroyableBlockState, PlacedByBlockState { + @Nonnull public static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); public static final boolean EXACT_RESOURCE_AMOUNTS = true; + @Nonnull public static final Codec CODEC = BuilderCodec.builder(ProcessingBenchState.class, ProcessingBenchState::new, BenchState.CODEC) .append(new KeyedCodec<>("InputContainer", ItemContainer.CODEC), (state, o) -> state.inputContainer = o, state -> state.inputContainer) .add() @@ -93,7 +97,9 @@ public class ProcessingBenchState extends BenchState implements TickableBlockSta private static final float EJECT_VELOCITY = 2.0F; private static final float EJECT_SPREAD_VELOCITY = 1.0F; private static final float EJECT_VERTICAL_VELOCITY = 3.25F; + @Nonnull public static final String PROCESSING = "Processing"; + @Nonnull public static final String PROCESS_COMPLETED = "ProcessCompleted"; private ProcessingBench processingBench; private ItemContainer inputContainer; @@ -104,7 +110,9 @@ public class ProcessingBenchState extends BenchState implements TickableBlockSta private float fuelTime; private int lastConsumedFuelTotal; private int nextExtra = -1; + @Nonnull private final Set processingSlots = new HashSet<>(); + @Nonnull private final Set processingFuelSlots = new HashSet<>(); @Nullable private String recipeId; @@ -766,7 +774,16 @@ public class ProcessingBenchState extends BenchState implements TickableBlockSta private void playSound(@Nonnull World world, int soundEventIndex, @Nonnull ComponentAccessor componentAccessor) { if (soundEventIndex != 0) { Vector3i pos = this.getBlockPosition(); - SoundUtil.playSoundEvent3d(soundEventIndex, SoundCategory.SFX, pos.x + 0.5, pos.y + 0.5, pos.z + 0.5, componentAccessor); + WorldChunk chunk = world.getChunk(ChunkUtil.indexChunkFromBlock(pos.x, pos.z)); + int rotationIndex = chunk.getRotationIndex(pos.x, pos.y, pos.z); + Vector3d soundPos = new Vector3d(); + BlockType blockType = this.getBlockType(); + if (blockType != null) { + blockType.getBlockCenter(rotationIndex, soundPos); + } + + soundPos.add(pos); + SoundUtil.playSoundEvent3d(soundEventIndex, SoundCategory.SFX, soundPos, componentAccessor); } } diff --git a/src/com/hypixel/hytale/builtin/crafting/system/PlayerCraftingSystems.java b/src/com/hypixel/hytale/builtin/crafting/system/PlayerCraftingSystems.java index 5ecc8c81..572f65d9 100644 --- a/src/com/hypixel/hytale/builtin/crafting/system/PlayerCraftingSystems.java +++ b/src/com/hypixel/hytale/builtin/crafting/system/PlayerCraftingSystems.java @@ -21,11 +21,14 @@ import javax.annotation.Nonnull; public class PlayerCraftingSystems { public static class CraftingHolderSystem extends HolderSystem { @Nonnull - private final ComponentType playerComponentType = Player.getComponentType(); + private final ComponentType playerComponentType; @Nonnull private final ComponentType craftingManagerComponentType; - public CraftingHolderSystem(@Nonnull ComponentType craftingManagerComponentType) { + public CraftingHolderSystem( + @Nonnull ComponentType playerComponentType, @Nonnull ComponentType craftingManagerComponentType + ) { + this.playerComponentType = playerComponentType; this.craftingManagerComponentType = craftingManagerComponentType; } @@ -54,19 +57,22 @@ public class PlayerCraftingSystems { } public static class CraftingRefSystem extends RefSystem { - @Nonnull - private final ComponentType playerComponentType = Player.getComponentType(); @Nonnull private final ComponentType craftingManagerComponentType; + @Nonnull + private final Query query; - public CraftingRefSystem(@Nonnull ComponentType craftingManagerComponentType) { + public CraftingRefSystem( + @Nonnull ComponentType playerComponentType, @Nonnull ComponentType craftingManagerComponentType + ) { this.craftingManagerComponentType = craftingManagerComponentType; + this.query = Query.and(playerComponentType, craftingManagerComponentType); } @Nonnull @Override public Query getQuery() { - return Query.and(this.playerComponentType, this.craftingManagerComponentType); + return this.query; } @Override @@ -79,7 +85,7 @@ public class PlayerCraftingSystems { public void onEntityRemove( @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - CraftingManager craftingManagerComponent = commandBuffer.getComponent(ref, CraftingManager.getComponentType()); + CraftingManager craftingManagerComponent = commandBuffer.getComponent(ref, this.craftingManagerComponentType); assert craftingManagerComponent != null; diff --git a/src/com/hypixel/hytale/builtin/crafting/window/BenchWindow.java b/src/com/hypixel/hytale/builtin/crafting/window/BenchWindow.java index e409ee96..7318dac6 100644 --- a/src/com/hypixel/hytale/builtin/crafting/window/BenchWindow.java +++ b/src/com/hypixel/hytale/builtin/crafting/window/BenchWindow.java @@ -7,8 +7,10 @@ import com.hypixel.hytale.builtin.crafting.state.BenchState; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.protocol.packets.window.WindowType; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.Bench; import com.hypixel.hytale.server.core.asset.type.gameplay.CraftingConfig; import com.hypixel.hytale.server.core.asset.type.item.config.Item; @@ -17,17 +19,21 @@ import com.hypixel.hytale.server.core.entity.entities.player.windows.MaterialCon import com.hypixel.hytale.server.core.entity.entities.player.windows.MaterialExtraResourcesSection; import com.hypixel.hytale.server.core.universe.world.SoundUtil; import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; public abstract class BenchWindow extends BlockWindow implements MaterialContainerWindow { private static final float CRAFTING_UPDATE_MIN_PERCENT = 0.05F; private static final long CRAFTING_UPDATE_INTERVAL_MS = 500L; + @Nonnull protected static final String BENCH_UPGRADING = "BenchUpgrading"; private float lastUpdatePercent; private long lastUpdateTimeMs; protected final Bench bench; + @Nonnull protected final BenchState benchState; + @Nonnull protected final JsonObject windowData = new JsonObject(); @Nonnull private final MaterialExtraResourcesSection extraResourcesSection = new MaterialExtraResourcesSection(); @@ -83,6 +89,8 @@ public abstract class BenchWindow extends BlockWindow implements MaterialContain @Override public void onClose0(@Nonnull Ref ref, @Nonnull ComponentAccessor componentAccessor) { + World world = componentAccessor.getExternalData().getWorld(); + this.setBlockInteractionState(this.benchState.getTierStateName(), world); CraftingManager craftingManagerComponent = componentAccessor.getComponent(ref, CraftingManager.getComponentType()); if (craftingManagerComponent != null) { if (craftingManagerComponent.clearBench(ref, componentAccessor) && this.bench.getFailedSoundEventIndex() != 0) { @@ -91,6 +99,16 @@ public abstract class BenchWindow extends BlockWindow implements MaterialContain } } + public void setBlockInteractionState(@Nonnull String state, @Nonnull World world) { + WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(this.x, this.z)); + if (worldChunk != null) { + BlockType blockType = worldChunk.getBlockType(this.x, this.y, this.z); + if (blockType != null) { + worldChunk.setBlockInteractionState(this.x, this.y, this.z, blockType, state, true); + } + } + } + public void updateCraftingJob(float percent) { this.windowData.addProperty("progress", percent); this.checkProgressInvalidate(percent); diff --git a/src/com/hypixel/hytale/builtin/crafting/window/CraftingWindow.java b/src/com/hypixel/hytale/builtin/crafting/window/CraftingWindow.java index 303305ad..2022ad43 100644 --- a/src/com/hypixel/hytale/builtin/crafting/window/CraftingWindow.java +++ b/src/com/hypixel/hytale/builtin/crafting/window/CraftingWindow.java @@ -9,19 +9,15 @@ import com.hypixel.hytale.builtin.crafting.state.BenchState; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; -import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.protocol.packets.window.CraftRecipeAction; import com.hypixel.hytale.protocol.packets.window.WindowType; -import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.CraftingBench; import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig; import com.hypixel.hytale.server.core.asset.type.item.config.CraftingRecipe; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.SoundUtil; -import com.hypixel.hytale.server.core.universe.world.World; -import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.util.Set; import javax.annotation.Nonnull; @@ -102,23 +98,11 @@ public abstract class CraftingWindow extends BenchWindow { @Override public void onClose0(@Nonnull Ref ref, @Nonnull ComponentAccessor componentAccessor) { super.onClose0(ref, componentAccessor); - World world = componentAccessor.getExternalData().getWorld(); - this.setBlockInteractionState(this.benchState.getTierStateName(), world); if (this.bench.getLocalCloseSoundEventIndex() != 0) { SoundUtil.playSoundEvent2d(ref, this.bench.getLocalCloseSoundEventIndex(), SoundCategory.UI, componentAccessor); } } - public void setBlockInteractionState(@Nonnull String state, @Nonnull World world) { - WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(this.x, this.z)); - if (worldChunk != null) { - BlockType blockType = worldChunk.getBlockType(this.x, this.y, this.z); - if (blockType != null) { - worldChunk.setBlockInteractionState(this.x, this.y, this.z, blockType, state, true); - } - } - } - public static boolean craftSimpleItem( @Nonnull Store store, @Nonnull Ref ref, @Nonnull CraftingManager craftingManager, @Nonnull CraftRecipeAction action ) { diff --git a/src/com/hypixel/hytale/builtin/crafting/window/DiagramCraftingWindow.java b/src/com/hypixel/hytale/builtin/crafting/window/DiagramCraftingWindow.java index f2ff8ae0..b3510dfa 100644 --- a/src/com/hypixel/hytale/builtin/crafting/window/DiagramCraftingWindow.java +++ b/src/com/hypixel/hytale/builtin/crafting/window/DiagramCraftingWindow.java @@ -44,6 +44,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class DiagramCraftingWindow extends CraftingWindow implements ItemContainerWindow { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); private String category; private String itemCategory; diff --git a/src/com/hypixel/hytale/builtin/crafting/window/ProcessingBenchWindow.java b/src/com/hypixel/hytale/builtin/crafting/window/ProcessingBenchWindow.java index c5c7c379..139ea46b 100644 --- a/src/com/hypixel/hytale/builtin/crafting/window/ProcessingBenchWindow.java +++ b/src/com/hypixel/hytale/builtin/crafting/window/ProcessingBenchWindow.java @@ -38,10 +38,12 @@ public class ProcessingBenchWindow extends BenchWindow implements ItemContainerW private int maxFuel; private float progress; private boolean active; + @Nonnull private final Set processingSlots = new HashSet<>(); + @Nonnull private final Set processingFuelSlots = new HashSet<>(); - public ProcessingBenchWindow(ProcessingBenchState benchState) { + public ProcessingBenchWindow(@Nonnull ProcessingBenchState benchState) { super(WindowType.Processing, benchState); ProcessingBench processingBench = (ProcessingBench)this.blockType.getBench(); CraftingRecipe recipe = benchState.getRecipe(); @@ -132,7 +134,7 @@ public class ProcessingBenchWindow extends BenchWindow implements ItemContainerW } } - public void setProcessingSlots(Set slots) { + public void setProcessingSlots(@Nonnull Set slots) { if (!this.processingSlots.equals(slots)) { this.processingSlots.clear(); this.processingSlots.addAll(slots); @@ -147,7 +149,7 @@ public class ProcessingBenchWindow extends BenchWindow implements ItemContainerW } } - public void setProcessingFuelSlots(Set slots) { + public void setProcessingFuelSlots(@Nonnull Set slots) { if (!this.processingFuelSlots.equals(slots)) { this.processingFuelSlots.clear(); this.processingFuelSlots.addAll(slots); diff --git a/src/com/hypixel/hytale/builtin/crafting/window/SimpleCraftingWindow.java b/src/com/hypixel/hytale/builtin/crafting/window/SimpleCraftingWindow.java index 58b7b929..b3fe6aa8 100644 --- a/src/com/hypixel/hytale/builtin/crafting/window/SimpleCraftingWindow.java +++ b/src/com/hypixel/hytale/builtin/crafting/window/SimpleCraftingWindow.java @@ -22,7 +22,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; public class SimpleCraftingWindow extends CraftingWindow implements MaterialContainerWindow { - public SimpleCraftingWindow(BenchState benchState) { + public SimpleCraftingWindow(@Nonnull BenchState benchState) { super(WindowType.BasicCrafting, benchState); } @@ -42,12 +42,19 @@ public class SimpleCraftingWindow extends CraftingWindow implements MaterialCont CraftingRecipe craftRecipe = CraftingRecipe.getAssetMap().getAsset(recipeId); if (craftRecipe == null) { PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType()); - playerRef.getPacketHandler().disconnect("Attempted to craft unknown recipe!"); + if (playerRef != null) { + playerRef.getPacketHandler().disconnect("Attempted to craft unknown recipe!"); + } + return; } - Player player = store.getComponent(ref, Player.getComponentType()); - CombinedItemContainer combined = player.getInventory().getCombinedBackpackStorageHotbar(); + Player playerComponent = store.getComponent(ref, Player.getComponentType()); + if (playerComponent == null) { + return; + } + + CombinedItemContainer combined = playerComponent.getInventory().getCombinedBackpackStorageHotbar(); CombinedItemContainer playerAndContainerInventory = new CombinedItemContainer(combined, this.getExtraResourcesSection().getItemContainer()); boolean accepted; if (craftRecipe.getTimeSeconds() > 0.0F) { diff --git a/src/com/hypixel/hytale/builtin/crafting/window/StructuralCraftingWindow.java b/src/com/hypixel/hytale/builtin/crafting/window/StructuralCraftingWindow.java index 64b029e5..62c2dd59 100644 --- a/src/com/hypixel/hytale/builtin/crafting/window/StructuralCraftingWindow.java +++ b/src/com/hypixel/hytale/builtin/crafting/window/StructuralCraftingWindow.java @@ -11,7 +11,6 @@ import com.hypixel.hytale.event.EventRegistration; import com.hypixel.hytale.math.util.MathUtil; import com.hypixel.hytale.protocol.BenchRequirement; import com.hypixel.hytale.protocol.ItemSoundEvent; -import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.protocol.packets.window.ChangeBlockAction; import com.hypixel.hytale.protocol.packets.window.CraftRecipeAction; import com.hypixel.hytale.protocol.packets.window.SelectSlotAction; @@ -21,8 +20,6 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.Structur import com.hypixel.hytale.server.core.asset.type.item.config.BlockGroup; import com.hypixel.hytale.server.core.asset.type.item.config.CraftingRecipe; import com.hypixel.hytale.server.core.asset.type.item.config.Item; -import com.hypixel.hytale.server.core.asset.type.itemsound.config.ItemSoundSet; -import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.windows.ItemContainerWindow; import com.hypixel.hytale.server.core.inventory.Inventory; @@ -45,15 +42,19 @@ import javax.annotation.Nullable; public class StructuralCraftingWindow extends CraftingWindow implements ItemContainerWindow { private static final int MAX_OPTIONS = 64; + @Nonnull private final SimpleItemContainer inputContainer; + @Nonnull private final SimpleItemContainer optionsContainer; + @Nonnull private final CombinedItemContainer combinedItemContainer; + @Nonnull private final Int2ObjectMap optionSlotToRecipeMap = new Int2ObjectOpenHashMap<>(); private int selectedSlot; @Nullable private EventRegistration inventoryRegistration; - public StructuralCraftingWindow(BenchState benchState) { + public StructuralCraftingWindow(@Nonnull BenchState benchState) { super(WindowType.StructuralCrafting, benchState); this.inputContainer = new SimpleItemContainer((short)1); this.inputContainer.registerChangeEvent(e -> this.updateRecipes()); @@ -76,7 +77,7 @@ public class StructuralCraftingWindow extends CraftingWindow implements ItemCont } } - private static void sortRecipes(ObjectList matching, StructuralCraftingBench structuralBench) { + private static void sortRecipes(@Nonnull ObjectList matching, @Nonnull StructuralCraftingBench structuralBench) { matching.sort((a, b) -> { boolean aHasHeaderCategory = hasHeaderCategory(structuralBench, a); boolean bHasHeaderCategory = hasHeaderCategory(structuralBench, b); @@ -91,7 +92,7 @@ public class StructuralCraftingWindow extends CraftingWindow implements ItemCont }); } - private static boolean hasHeaderCategory(StructuralCraftingBench bench, CraftingRecipe recipe) { + private static boolean hasHeaderCategory(@Nonnull StructuralCraftingBench bench, @Nonnull CraftingRecipe recipe) { for (BenchRequirement requirement : recipe.getBenchRequirement()) { if (requirement.type == bench.getType() && requirement.id.equals(bench.getId()) && requirement.categories != null) { for (String category : requirement.categories) { @@ -105,7 +106,7 @@ public class StructuralCraftingWindow extends CraftingWindow implements ItemCont return false; } - private static int getSortingPriority(StructuralCraftingBench bench, CraftingRecipe recipe) { + private static int getSortingPriority(@Nonnull StructuralCraftingBench bench, @Nonnull CraftingRecipe recipe) { int priority = Integer.MAX_VALUE; for (BenchRequirement requirement : recipe.getBenchRequirement()) { @@ -122,61 +123,50 @@ public class StructuralCraftingWindow extends CraftingWindow implements ItemCont @Override public void handleAction(@Nonnull Ref ref, @Nonnull Store store, @Nonnull WindowAction action) { - CraftingManager craftingManager = store.getComponent(ref, CraftingManager.getComponentType()); - switch (action) { - case SelectSlotAction selectAction: - int newSlot = MathUtil.clamp(selectAction.slot, 0, this.optionsContainer.getCapacity()); - if (newSlot != this.selectedSlot) { - this.selectedSlot = newSlot; - this.windowData.addProperty("selected", this.selectedSlot); - this.invalidate(); - } - break; - case CraftRecipeAction craftAction: - ItemStack output = this.optionsContainer.getItemStack((short)this.selectedSlot); - if (output != null) { - int quantity = craftAction.quantity; - String recipeId = this.optionSlotToRecipeMap.get(this.selectedSlot); - if (recipeId == null) { - return; + CraftingManager craftingManagerComponent = store.getComponent(ref, CraftingManager.getComponentType()); + if (craftingManagerComponent != null) { + switch (action) { + case SelectSlotAction selectAction: + int newSlot = MathUtil.clamp(selectAction.slot, 0, this.optionsContainer.getCapacity()); + if (newSlot != this.selectedSlot) { + this.selectedSlot = newSlot; + this.windowData.addProperty("selected", this.selectedSlot); + this.invalidate(); } - - CraftingRecipe recipe = CraftingRecipe.getAssetMap().getAsset(recipeId); - if (recipe == null) { - return; - } - - MaterialQuantity primaryOutput = recipe.getPrimaryOutput(); - String primaryOutputItemId = primaryOutput.getItemId(); - if (primaryOutputItemId != null) { - Item primaryOutputItem = Item.getAssetMap().getAsset(primaryOutputItemId); - if (primaryOutputItem != null) { - this.playCraftSound(ref, store, primaryOutputItem); + break; + case CraftRecipeAction craftAction: + ItemStack output = this.optionsContainer.getItemStack((short)this.selectedSlot); + if (output != null) { + int quantity = craftAction.quantity; + String recipeId = this.optionSlotToRecipeMap.get(this.selectedSlot); + if (recipeId == null) { + return; } + + CraftingRecipe recipe = CraftingRecipe.getAssetMap().getAsset(recipeId); + if (recipe == null) { + return; + } + + MaterialQuantity primaryOutput = recipe.getPrimaryOutput(); + String primaryOutputItemId = primaryOutput.getItemId(); + if (primaryOutputItemId != null) { + Item primaryOutputItem = Item.getAssetMap().getAsset(primaryOutputItemId); + if (primaryOutputItem != null) { + SoundUtil.playItemSoundEvent(ref, store, primaryOutputItem, ItemSoundEvent.Drop); + } + } + + craftingManagerComponent.queueCraft(ref, store, this, 0, recipe, quantity, this.inputContainer, CraftingManager.InputRemovalType.ORDERED); + this.invalidate(); } - - craftingManager.queueCraft(ref, store, this, 0, recipe, quantity, this.inputContainer, CraftingManager.InputRemovalType.ORDERED); - this.invalidate(); - } - break; - case ChangeBlockAction changeBlockAction: - if (((StructuralCraftingBench)this.bench).shouldAllowBlockGroupCycling()) { - this.changeBlockType(ref, changeBlockAction.down, store); - } - break; - default: - } - } - - private void playCraftSound(Ref ref, Store store, Item item) { - ItemSoundSet soundSet = ItemSoundSet.getAssetMap().getAsset(item.getItemSoundSetIndex()); - if (soundSet != null) { - String dragSound = soundSet.getSoundEventIds().get(ItemSoundEvent.Drop); - if (dragSound != null) { - int dragSoundIndex = SoundEvent.getAssetMap().getIndex(dragSound); - if (dragSoundIndex != 0) { - SoundUtil.playSoundEvent2d(ref, dragSoundIndex, SoundCategory.UI, store); - } + break; + case ChangeBlockAction changeBlockAction: + if (((StructuralCraftingBench)this.bench).shouldAllowBlockGroupCycling()) { + this.changeBlockType(ref, changeBlockAction.down, store); + } + break; + default: } } } @@ -207,7 +197,7 @@ public class StructuralCraftingWindow extends CraftingWindow implements ItemCont Item desiredItem = Item.getAssetMap().getAsset(next); if (desiredItem != null) { this.inputContainer.replaceItemStackInSlot((short)0, item, new ItemStack(next, item.getQuantity())); - this.playCraftSound(ref, store, desiredItem); + SoundUtil.playItemSoundEvent(ref, store, desiredItem, ItemSoundEvent.Drop); } } } diff --git a/src/com/hypixel/hytale/builtin/creativehub/CreativeHubPlugin.java b/src/com/hypixel/hytale/builtin/creativehub/CreativeHubPlugin.java index c663142c..f02046b0 100644 --- a/src/com/hypixel/hytale/builtin/creativehub/CreativeHubPlugin.java +++ b/src/com/hypixel/hytale/builtin/creativehub/CreativeHubPlugin.java @@ -43,6 +43,7 @@ public class CreativeHubPlugin extends JavaPlugin { @Nonnull private static final Message MESSAGE_HUB_RETURN_HINT = Message.translation("server.creativehub.portal.returnHint"); private static CreativeHubPlugin instance; + @Nonnull private final Map activeHubInstances = new ConcurrentHashMap<>(); private ComponentType creativeHubEntityConfigComponentType; @@ -92,7 +93,7 @@ public class CreativeHubPlugin extends JavaPlugin { return universe.loadWorld(permanentWorldName); } else { Path assetPath = InstancesPlugin.getInstanceAssetPath(instanceAssetName); - Path worldPath = universe.getPath().resolve("worlds").resolve(permanentWorldName); + Path worldPath = universe.validateWorldPath(permanentWorldName); return WorldConfig.load(assetPath.resolve("instance.bson")) .thenApplyAsync( SneakyThrow.sneakyFunction( @@ -211,7 +212,7 @@ public class CreativeHubPlugin extends JavaPlugin { World parentWorld = Universe.get().getWorld(hubEntityConfig.getParentHubWorldUuid()); if (parentWorld != null) { World hubInstance = get().getActiveHubInstance(parentWorld); - if (hubInstance == null || !world.equals(hubInstance)) { + if (!world.equals(hubInstance)) { PlayerRef playerRef = holder.getComponent(PlayerRef.getComponentType()); if (playerRef != null) { world.execute(() -> playerRef.sendMessage(MESSAGE_HUB_RETURN_HINT)); diff --git a/src/com/hypixel/hytale/builtin/creativehub/command/HubCommand.java b/src/com/hypixel/hytale/builtin/creativehub/command/HubCommand.java index cad6df71..282e87ab 100644 --- a/src/com/hypixel/hytale/builtin/creativehub/command/HubCommand.java +++ b/src/com/hypixel/hytale/builtin/creativehub/command/HubCommand.java @@ -35,14 +35,14 @@ public class HubCommand extends AbstractPlayerCommand { protected void execute( @Nonnull CommandContext context, @Nonnull Store store, @Nonnull Ref ref, @Nonnull PlayerRef playerRef, @Nonnull World world ) { - World parentWorld = this.findParentHubWorld(store, ref); + World parentWorld = findParentHubWorld(store, ref); if (parentWorld == null) { playerRef.sendMessage(MESSAGE_NOT_IN_HUB_WORLD); } else { CreativeHubWorldConfig hubConfig = CreativeHubWorldConfig.get(parentWorld.getWorldConfig()); if (hubConfig != null && hubConfig.getStartupInstance() != null) { World currentHub = CreativeHubPlugin.get().getActiveHubInstance(parentWorld); - if (currentHub != null && world.equals(currentHub)) { + if (world.equals(currentHub)) { playerRef.sendMessage(MESSAGE_ALREADY_IN_HUB); } else { ISpawnProvider spawnProvider = parentWorld.getWorldConfig().getSpawnProvider(); @@ -57,7 +57,7 @@ public class HubCommand extends AbstractPlayerCommand { } @Nullable - private World findParentHubWorld(@Nonnull Store store, @Nonnull Ref ref) { + private static World findParentHubWorld(@Nonnull Store store, @Nonnull Ref ref) { CreativeHubEntityConfig hubEntityConfig = store.getComponent(ref, CreativeHubEntityConfig.getComponentType()); if (hubEntityConfig != null && hubEntityConfig.getParentHubWorldUuid() != null) { World parentWorld = Universe.get().getWorld(hubEntityConfig.getParentHubWorldUuid()); diff --git a/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubEntityConfig.java b/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubEntityConfig.java index c1c8e0f5..04663d83 100644 --- a/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubEntityConfig.java +++ b/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubEntityConfig.java @@ -13,6 +13,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class CreativeHubEntityConfig implements Component { + @Nonnull public static final String ID = "CreativeHub"; @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(CreativeHubEntityConfig.class, CreativeHubEntityConfig::new) diff --git a/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubWorldConfig.java b/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubWorldConfig.java index 87e3cd5c..cec3360c 100644 --- a/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubWorldConfig.java +++ b/src/com/hypixel/hytale/builtin/creativehub/config/CreativeHubWorldConfig.java @@ -8,6 +8,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class CreativeHubWorldConfig { + @Nonnull public static final String ID = "CreativeHub"; @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(CreativeHubWorldConfig.class, CreativeHubWorldConfig::new) diff --git a/src/com/hypixel/hytale/builtin/creativehub/interactions/HubPortalInteraction.java b/src/com/hypixel/hytale/builtin/creativehub/interactions/HubPortalInteraction.java index 7233ef0f..ba5a5265 100644 --- a/src/com/hypixel/hytale/builtin/creativehub/interactions/HubPortalInteraction.java +++ b/src/com/hypixel/hytale/builtin/creativehub/interactions/HubPortalInteraction.java @@ -39,7 +39,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class HubPortalInteraction extends SimpleInstantInteraction { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( HubPortalInteraction.class, HubPortalInteraction::new, SimpleInstantInteraction.CODEC ) @@ -76,6 +78,9 @@ public class HubPortalInteraction extends SimpleInstantInteraction { @Override protected void firstRun(@Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler) { CommandBuffer commandBuffer = context.getCommandBuffer(); + + assert commandBuffer != null; + Ref ref = context.getEntity(); Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType()); if (playerComponent != null && !playerComponent.isWaitingForClientReady()) { @@ -85,7 +90,7 @@ public class HubPortalInteraction extends SimpleInstantInteraction { Universe universe = Universe.get(); World targetWorld = universe.getWorld(this.worldName); if (targetWorld != null) { - this.teleportToLoadedWorld(ref, commandBuffer, targetWorld, playerComponent); + teleportToLoadedWorld(ref, commandBuffer, targetWorld, playerComponent); } else { CompletableFuture worldFuture; if (this.instanceTemplate != null) { @@ -101,13 +106,13 @@ public class HubPortalInteraction extends SimpleInstantInteraction { }); } - this.teleportToLoadingWorld(ref, commandBuffer, worldFuture, currentWorld, playerComponent); + teleportToLoadingWorld(ref, commandBuffer, worldFuture, currentWorld, playerComponent); } } } } - private void teleportToLoadedWorld( + private static void teleportToLoadedWorld( @Nonnull Ref playerRef, @Nonnull ComponentAccessor componentAccessor, @Nonnull World targetWorld, @@ -131,7 +136,7 @@ public class HubPortalInteraction extends SimpleInstantInteraction { componentAccessor.addComponent(playerRef, Teleport.getComponentType(), teleportComponent); } - private void teleportToLoadingWorld( + private static void teleportToLoadingWorld( @Nonnull Ref playerRef, @Nonnull ComponentAccessor componentAccessor, @Nonnull CompletableFuture worldFuture, @@ -139,61 +144,64 @@ public class HubPortalInteraction extends SimpleInstantInteraction { @Nonnull Player playerComponent ) { TransformComponent transformComponent = componentAccessor.getComponent(playerRef, TransformComponent.getComponentType()); - - assert transformComponent != null; - - Transform originalPosition = transformComponent.getTransform().clone(); - PlayerRef playerRefComponent = componentAccessor.getComponent(playerRef, PlayerRef.getComponentType()); - - assert playerRefComponent != null; - - Map perWorldData = playerComponent.getPlayerConfigData().getPerWorldData(); - UUIDComponent uuidComponent = componentAccessor.getComponent(playerRef, UUIDComponent.getComponentType()); - - assert uuidComponent != null; - - UUID playerUUID = uuidComponent.getUuid(); - CreativeHubEntityConfig hubEntityConfig = componentAccessor.getComponent(playerRef, CreativeHubEntityConfig.getComponentType()); - originalWorld.execute(playerRefComponent::removeFromStore); - worldFuture.orTimeout(1L, TimeUnit.MINUTES).thenCompose(world -> { - PlayerWorldData worldData = perWorldData.get(world.getName()); - if (worldData != null && worldData.getLastPosition() != null) { - return world.addPlayer(playerRefComponent, worldData.getLastPosition(), Boolean.TRUE, Boolean.FALSE); + if (transformComponent == null) { + LOGGER.at(Level.SEVERE).log("Cannot teleport player %s to permanent world - missing TransformComponent", playerRef); + } else { + Transform originalPosition = transformComponent.getTransform().clone(); + PlayerRef playerRefComponent = componentAccessor.getComponent(playerRef, PlayerRef.getComponentType()); + if (playerRefComponent == null) { + LOGGER.at(Level.SEVERE).log("Cannot teleport player %s to permanent world - missing PlayerRef component", playerRef); } else { - ISpawnProvider spawnProvider = world.getWorldConfig().getSpawnProvider(); - Transform spawnPoint = spawnProvider != null ? spawnProvider.getSpawnPoint(world, playerUUID) : null; - return world.addPlayer(playerRefComponent, spawnPoint, Boolean.TRUE, Boolean.FALSE); - } - }).whenComplete((ret, ex) -> { - if (ex != null) { - LOGGER.at(Level.SEVERE).withCause(ex).log("Failed to teleport %s to permanent world", playerRefComponent.getUsername()); - } - - if (ret == null) { - if (originalWorld.isAlive()) { - originalWorld.addPlayer(playerRefComponent, originalPosition, Boolean.TRUE, Boolean.FALSE); + Map perWorldData = playerComponent.getPlayerConfigData().getPerWorldData(); + UUIDComponent uuidComponent = componentAccessor.getComponent(playerRef, UUIDComponent.getComponentType()); + if (uuidComponent == null) { + LOGGER.at(Level.SEVERE).log("Cannot teleport player %s to permanent world - missing UUIDComponent", playerRef); } else { - if (hubEntityConfig != null && hubEntityConfig.getParentHubWorldUuid() != null) { - World parentWorld = Universe.get().getWorld(hubEntityConfig.getParentHubWorldUuid()); - if (parentWorld != null) { - CreativeHubWorldConfig parentHubConfig = CreativeHubWorldConfig.get(parentWorld.getWorldConfig()); - if (parentHubConfig != null && parentHubConfig.getStartupInstance() != null) { - World hubInstance = CreativeHubPlugin.get().getOrSpawnHubInstance(parentWorld, parentHubConfig, new Transform()); - hubInstance.addPlayer(playerRefComponent, null, Boolean.TRUE, Boolean.FALSE); - return; + UUID playerUUID = uuidComponent.getUuid(); + CreativeHubEntityConfig hubEntityConfig = componentAccessor.getComponent(playerRef, CreativeHubEntityConfig.getComponentType()); + originalWorld.execute(playerRefComponent::removeFromStore); + worldFuture.orTimeout(1L, TimeUnit.MINUTES).thenCompose(world -> { + PlayerWorldData worldData = perWorldData.get(world.getName()); + if (worldData != null && worldData.getLastPosition() != null) { + return world.addPlayer(playerRefComponent, worldData.getLastPosition(), Boolean.TRUE, Boolean.FALSE); + } else { + ISpawnProvider spawnProvider = world.getWorldConfig().getSpawnProvider(); + Transform spawnPoint = spawnProvider != null ? spawnProvider.getSpawnPoint(world, playerUUID) : null; + return world.addPlayer(playerRefComponent, spawnPoint, Boolean.TRUE, Boolean.FALSE); + } + }).whenComplete((ret, ex) -> { + if (ex != null) { + LOGGER.at(Level.SEVERE).withCause(ex).log("Failed to teleport %s to permanent world", playerRefComponent.getUsername()); + } + + if (ret == null) { + if (originalWorld.isAlive()) { + originalWorld.addPlayer(playerRefComponent, originalPosition, Boolean.TRUE, Boolean.FALSE); + } else { + if (hubEntityConfig != null && hubEntityConfig.getParentHubWorldUuid() != null) { + World parentWorld = Universe.get().getWorld(hubEntityConfig.getParentHubWorldUuid()); + if (parentWorld != null) { + CreativeHubWorldConfig parentHubConfig = CreativeHubWorldConfig.get(parentWorld.getWorldConfig()); + if (parentHubConfig != null && parentHubConfig.getStartupInstance() != null) { + World hubInstance = CreativeHubPlugin.get().getOrSpawnHubInstance(parentWorld, parentHubConfig, new Transform()); + hubInstance.addPlayer(playerRefComponent, null, Boolean.TRUE, Boolean.FALSE); + return; + } + } + } + + World defaultWorld = Universe.get().getDefaultWorld(); + if (defaultWorld != null) { + defaultWorld.addPlayer(playerRefComponent, null, Boolean.TRUE, Boolean.FALSE); + } else { + LOGGER.at(Level.SEVERE).log("No fallback world available for %s, disconnecting", playerRefComponent.getUsername()); + playerRefComponent.getPacketHandler().disconnect("Failed to teleport - no world available"); + } } } - } - - World defaultWorld = Universe.get().getDefaultWorld(); - if (defaultWorld != null) { - defaultWorld.addPlayer(playerRefComponent, null, Boolean.TRUE, Boolean.FALSE); - } else { - LOGGER.at(Level.SEVERE).log("No fallback world available for %s, disconnecting", playerRefComponent.getUsername()); - playerRefComponent.getPacketHandler().disconnect("Failed to teleport - no world available"); - } + }); } } - }); + } } } diff --git a/src/com/hypixel/hytale/builtin/deployables/DeployablesPlugin.java b/src/com/hypixel/hytale/builtin/deployables/DeployablesPlugin.java index 91349936..7e895017 100644 --- a/src/com/hypixel/hytale/builtin/deployables/DeployablesPlugin.java +++ b/src/com/hypixel/hytale/builtin/deployables/DeployablesPlugin.java @@ -25,6 +25,7 @@ import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Int import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import javax.annotation.Nonnull; public class DeployablesPlugin extends JavaPlugin { private static DeployablesPlugin instance; @@ -33,7 +34,7 @@ public class DeployablesPlugin extends JavaPlugin { private ComponentType deployableProjectileShooterComponentType; private ComponentType deployableProjectileComponentType; - public DeployablesPlugin(JavaPluginInit init) { + public DeployablesPlugin(@Nonnull JavaPluginInit init) { super(init); } diff --git a/src/com/hypixel/hytale/builtin/deployables/DeployablesUtils.java b/src/com/hypixel/hytale/builtin/deployables/DeployablesUtils.java index 4b066caf..87c92397 100644 --- a/src/com/hypixel/hytale/builtin/deployables/DeployablesUtils.java +++ b/src/com/hypixel/hytale/builtin/deployables/DeployablesUtils.java @@ -47,6 +47,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class DeployablesUtils { + @Nonnull private static final String DEPLOYABLE_MAX_STAT_MODIFIER = "DEPLOYABLE_MAX"; @Nonnull @@ -122,16 +123,18 @@ public class DeployablesUtils { int statIndex = EntityStatType.getAssetMap().getIndex(statEntry.getKey()); EntityStatValue stat = entityStatMapComponent.get(statIndex); if (stat != null) { - EntityStatType asset = EntityStatType.getAssetMap().getAsset(statIndex); - StaticModifier modifier = new StaticModifier( - Modifier.ModifierTarget.MAX, StaticModifier.CalculationType.ADDITIVE, statConfig.getMax() - asset.getMax() - ); - entityStatMapComponent.putModifier(statIndex, "DEPLOYABLE_MAX", modifier); - float initialValue = statConfig.getInitial(); - if (initialValue == Float.MAX_VALUE) { - entityStatMapComponent.maximizeStatValue(statIndex); - } else { - entityStatMapComponent.setStatValue(statIndex, initialValue); + EntityStatType statType = EntityStatType.getAssetMap().getAsset(statIndex); + if (statType != null) { + StaticModifier modifier = new StaticModifier( + Modifier.ModifierTarget.MAX, StaticModifier.CalculationType.ADDITIVE, statConfig.getMax() - statType.getMax() + ); + entityStatMapComponent.putModifier(statIndex, "DEPLOYABLE_MAX", modifier); + float initialValue = statConfig.getInitial(); + if (initialValue == Float.MAX_VALUE) { + entityStatMapComponent.maximizeStatValue(statIndex); + } else { + entityStatMapComponent.setStatValue(statIndex, initialValue); + } } } } diff --git a/src/com/hypixel/hytale/builtin/deployables/component/DeployableComponent.java b/src/com/hypixel/hytale/builtin/deployables/component/DeployableComponent.java index ccb639bc..98966570 100644 --- a/src/com/hypixel/hytale/builtin/deployables/component/DeployableComponent.java +++ b/src/com/hypixel/hytale/builtin/deployables/component/DeployableComponent.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class DeployableComponent implements Component { @Nonnull @@ -26,7 +27,8 @@ public class DeployableComponent implements Component { private UUID ownerUUID; private Instant spawnInstant; private float timeSinceLastAttack; - private Vector3f debugColor = null; + @Nullable + private Vector3f debugColor; private boolean firstTickRan; private String spawnFace; @@ -113,6 +115,7 @@ public class DeployableComponent implements Component { this.flags.put(key, value); } + @Nonnull public Vector3f getDebugColor() { if (this.debugColor == null) { ThreadLocalRandom random = ThreadLocalRandom.current(); diff --git a/src/com/hypixel/hytale/builtin/deployables/component/DeployableOwnerComponent.java b/src/com/hypixel/hytale/builtin/deployables/component/DeployableOwnerComponent.java index 3a373226..d48903a5 100644 --- a/src/com/hypixel/hytale/builtin/deployables/component/DeployableOwnerComponent.java +++ b/src/com/hypixel/hytale/builtin/deployables/component/DeployableOwnerComponent.java @@ -28,6 +28,7 @@ public class DeployableOwnerComponent implements Component { private final Object2IntMap deployableCountPerId = new Object2IntOpenHashMap<>(); @Nonnull private final List> deployablesForDestruction = new ObjectArrayList<>(); + @Nonnull private final List>> tempDestructionList = new ObjectArrayList<>(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/deployables/component/DeployableProjectileShooterComponent.java b/src/com/hypixel/hytale/builtin/deployables/component/DeployableProjectileShooterComponent.java index e56dab90..12659bde 100644 --- a/src/com/hypixel/hytale/builtin/deployables/component/DeployableProjectileShooterComponent.java +++ b/src/com/hypixel/hytale/builtin/deployables/component/DeployableProjectileShooterComponent.java @@ -14,7 +14,9 @@ import java.util.UUID; import javax.annotation.Nonnull; public class DeployableProjectileShooterComponent implements Component { + @Nonnull protected final List> projectiles = new ObjectArrayList<>(); + @Nonnull protected final List> projectilesForRemoval = new ObjectArrayList<>(); protected Ref activeTarget; @@ -33,10 +35,12 @@ public class DeployableProjectileShooterComponent implements Component {}); } + @Nonnull public List> getProjectiles() { return this.projectiles; } + @Nonnull public List> getProjectilesForRemoval() { return this.projectilesForRemoval; } diff --git a/src/com/hypixel/hytale/builtin/deployables/config/DeployableAoeConfig.java b/src/com/hypixel/hytale/builtin/deployables/config/DeployableAoeConfig.java index 76447299..c0a23e9f 100644 --- a/src/com/hypixel/hytale/builtin/deployables/config/DeployableAoeConfig.java +++ b/src/com/hypixel/hytale/builtin/deployables/config/DeployableAoeConfig.java @@ -26,8 +26,10 @@ import java.time.Duration; import java.time.Instant; import java.util.function.Consumer; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class DeployableAoeConfig extends DeployableConfig { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DeployableAoeConfig.class, DeployableAoeConfig::new, DeployableConfig.BASE_CODEC ) @@ -119,6 +121,7 @@ public class DeployableAoeConfig extends DeployableConfig { protected boolean attackEnemies = true; protected DeployableAoeConfig.Shape shape = DeployableAoeConfig.Shape.Sphere; protected float height = 1.0F; + @Nullable protected DamageCause processedDamageCause; protected DeployableAoeConfig() { @@ -133,46 +136,49 @@ public class DeployableAoeConfig extends DeployableConfig { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Vector3d position = archetypeChunk.getComponent(index, TransformComponent.getComponentType()).getPosition(); - World world = store.getExternalData().getWorld(); - Ref entityRef = archetypeChunk.getReferenceTo(index); - float radius = this.getRadius(store, deployableComponent.getSpawnInstant()); - this.handleDebugGraphics(world, deployableComponent.getDebugColor(), position, radius * 2.0F); - switch (deployableComponent.getFlag(DeployableComponent.DeployableFlag.STATE)) { - case 0: - deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 1); - break; - case 1: - deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 2); - playAnimation(store, entityRef, this, "Grow"); - break; - case 2: - if (radius >= this.endRadius) { - deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 3); - playAnimation(store, entityRef, this, "Looping"); - } - } + TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + if (transformComponent != null) { + Vector3d position = transformComponent.getPosition(); + World world = store.getExternalData().getWorld(); + Ref entityRef = archetypeChunk.getReferenceTo(index); + float radius = this.getRadius(store, deployableComponent.getSpawnInstant()); + this.handleDebugGraphics(world, deployableComponent.getDebugColor(), position, radius * 2.0F); + switch (deployableComponent.getFlag(DeployableComponent.DeployableFlag.STATE)) { + case 0: + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 1); + break; + case 1: + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 2); + playAnimation(store, entityRef, this, "Grow"); + break; + case 2: + if (radius >= this.endRadius) { + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 3); + playAnimation(store, entityRef, this, "Looping"); + } + } - Ref deployableRef = archetypeChunk.getReferenceTo(index); - if (deployableComponent.incrementTimeSinceLastAttack(dt) > this.damageInterval) { - deployableComponent.setTimeSinceLastAttack(0.0F); - this.handleDetection(store, commandBuffer, deployableRef, deployableComponent, position, radius, DamageCause.PHYSICAL); - } + Ref deployableRef = archetypeChunk.getReferenceTo(index); + if (deployableComponent.incrementTimeSinceLastAttack(dt) > this.damageInterval) { + deployableComponent.setTimeSinceLastAttack(0.0F); + this.handleDetection(store, commandBuffer, deployableRef, deployableComponent, position, radius, DamageCause.PHYSICAL); + } - super.tick(deployableComponent, dt, index, archetypeChunk, store, commandBuffer); + super.tick(deployableComponent, dt, index, archetypeChunk, store, commandBuffer); + } } protected void handleDetection( - final Store store, - final CommandBuffer commandBuffer, - final Ref deployableRef, - DeployableComponent deployableComponent, - Vector3d position, + @Nonnull final Store store, + @Nonnull final CommandBuffer commandBuffer, + @Nonnull final Ref deployableRef, + @Nonnull DeployableComponent deployableComponent, + @Nonnull Vector3d position, float radius, - final DamageCause damageCause + @Nonnull final DamageCause damageCause ) { var attackConsumer = new Consumer>() { - public void accept(Ref entityStoreRef) { + public void accept(@Nonnull Ref entityStoreRef) { if (entityStoreRef != deployableRef) { DeployableAoeConfig.this.attackTarget(entityStoreRef, deployableRef, damageCause, commandBuffer); DeployableAoeConfig.this.applyEffectToTarget(store, entityStoreRef); @@ -198,7 +204,12 @@ public class DeployableAoeConfig extends DeployableConfig { } } - protected void attackTarget(Ref targetRef, Ref ownerRef, DamageCause damageCause, CommandBuffer commandBuffer) { + protected void attackTarget( + @Nonnull Ref targetRef, + @Nonnull Ref ownerRef, + @Nonnull DamageCause damageCause, + @Nonnull CommandBuffer commandBuffer + ) { if (!(this.damageAmount <= 0.0F)) { Damage damageEntry = new Damage(new Damage.EntitySource(ownerRef), damageCause, this.damageAmount); if (targetRef.equals(ownerRef)) { @@ -209,15 +220,15 @@ public class DeployableAoeConfig extends DeployableConfig { } } - protected void applyEffectToTarget(Store store, Ref targetRef) { + protected void applyEffectToTarget(@Nonnull Store store, @Nonnull Ref targetRef) { if (this.effectsToApply != null) { - EffectControllerComponent effectController = store.getComponent(targetRef, EffectControllerComponent.getComponentType()); - if (effectController != null) { + EffectControllerComponent effectControllerComponent = store.getComponent(targetRef, EffectControllerComponent.getComponentType()); + if (effectControllerComponent != null) { for (String effect : this.effectsToApply) { if (effect != null) { EntityEffect effectAsset = EntityEffect.getAssetMap().getAsset(effect); if (effectAsset != null) { - effectController.addEffect(targetRef, effectAsset, store); + effectControllerComponent.addEffect(targetRef, effectAsset, store); } } } @@ -225,12 +236,12 @@ public class DeployableAoeConfig extends DeployableConfig { } } - protected boolean canAttackEntity(Ref target, DeployableComponent deployable) { - boolean isOwner = target.equals(deployable.getOwner()); + protected boolean canAttackEntity(@Nonnull Ref targetRef, @Nonnull DeployableComponent deployable) { + boolean isOwner = targetRef.equals(deployable.getOwner()); return !isOwner || this.attackOwner; } - protected float getRadius(Store store, Instant startInstant) { + protected float getRadius(@Nonnull Store store, @Nonnull Instant startInstant) { if (!(this.radiusChangeTime <= 0.0F) && !(this.endRadius < 0.0F)) { float radiusDiff = this.endRadius - this.startRadius; float increment = radiusDiff / this.radiusChangeTime; @@ -247,6 +258,7 @@ public class DeployableAoeConfig extends DeployableConfig { } } + @Nullable protected DamageCause getDamageCause() { if (this.processedDamageCause == null) { this.processedDamageCause = DamageCause.getAssetMap().getAsset(this.damageCause); diff --git a/src/com/hypixel/hytale/builtin/deployables/config/DeployableConfig.java b/src/com/hypixel/hytale/builtin/deployables/config/DeployableConfig.java index 32acdc59..e9cd1cf7 100644 --- a/src/com/hypixel/hytale/builtin/deployables/config/DeployableConfig.java +++ b/src/com/hypixel/hytale/builtin/deployables/config/DeployableConfig.java @@ -27,7 +27,9 @@ import java.util.Map; import javax.annotation.Nonnull; public abstract class DeployableConfig implements NetworkSerializable { + @Nonnull public static final CodecMapCodec CODEC = new CodecMapCodec<>("Type"); + @Nonnull public static final BuilderCodec BASE_CODEC = BuilderCodec.abstractBuilder(DeployableConfig.class) .appendInherited(new KeyedCodec<>("Id", Codec.STRING), (o, i) -> o.id = i, o -> o.id, (o, p) -> o.id = p.id) .documentation("Used to identify this deployable for uses such as MaxLiveCount") @@ -192,7 +194,7 @@ public abstract class DeployableConfig implements NetworkSerializable store, @Nonnull Ref ref, @Nonnull DeployableConfig config, @Nonnull String animationSetKey ) { - EntityStore externalData = store.getExternalData(); NetworkId networkIdComponent = store.getComponent(ref, NetworkId.getComponentType()); - DeployablesUtils.playAnimation(store, networkIdComponent.getId(), ref, config, AnimationSlot.Action, null, animationSetKey); + if (networkIdComponent != null) { + DeployablesUtils.playAnimation(store, networkIdComponent.getId(), ref, config, AnimationSlot.Action, null, animationSetKey); + } } protected static void stopAnimation(@Nonnull Store store, @Nonnull ArchetypeChunk archetypeChunk, int index) { - EntityStore externalData = store.getExternalData(); Ref ref = archetypeChunk.getReferenceTo(index); - if (ref != null && ref.isValid()) { + if (ref.isValid()) { NetworkId networkIdComponent = archetypeChunk.getComponent(index, NetworkId.getComponentType()); - DeployablesUtils.stopAnimation(store, networkIdComponent.getId(), ref, AnimationSlot.Action); + if (networkIdComponent != null) { + DeployablesUtils.stopAnimation(store, networkIdComponent.getId(), ref, AnimationSlot.Action); + } } } @@ -347,6 +351,7 @@ public abstract class DeployableConfig implements NetworkSerializable CODEC = BuilderCodec.builder( DeployableConfig.StatConfig.class, DeployableConfig.StatConfig::new ) diff --git a/src/com/hypixel/hytale/builtin/deployables/config/DeployableSpawner.java b/src/com/hypixel/hytale/builtin/deployables/config/DeployableSpawner.java index fce62376..e7a80d42 100644 --- a/src/com/hypixel/hytale/builtin/deployables/config/DeployableSpawner.java +++ b/src/com/hypixel/hytale/builtin/deployables/config/DeployableSpawner.java @@ -10,8 +10,10 @@ import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.codec.validation.Validators; import com.hypixel.hytale.math.vector.Vector3d; +import javax.annotation.Nonnull; public class DeployableSpawner implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( DeployableSpawner.class, DeployableSpawner::new, Codec.STRING, (t, k) -> t.id = k, t -> t.id, (asset, data) -> asset.data = data, asset -> asset.data ) diff --git a/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapConfig.java b/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapConfig.java index 4b844338..ff63d7b4 100644 --- a/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapConfig.java +++ b/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapConfig.java @@ -24,6 +24,7 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; public class DeployableTrapConfig extends DeployableAoeConfig { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DeployableTrapConfig.class, DeployableTrapConfig::new, DeployableAoeConfig.CODEC ) @@ -62,66 +63,69 @@ public class DeployableTrapConfig extends DeployableAoeConfig { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Vector3d pos = archetypeChunk.getComponent(index, TransformComponent.getComponentType()).getPosition(); - World world = store.getExternalData().getWorld(); - Ref entityRef = archetypeChunk.getReferenceTo(index); - if (!deployableComponent.getOwner().isValid()) { - world.execute(() -> { - if (entityRef.isValid()) { - DespawnComponent despawn = store.ensureAndGetComponent(entityRef, DespawnComponent.getComponentType()); - WorldTimeResource timeManager = commandBuffer.getResource(WorldTimeResource.getResourceType()); - despawn.setDespawn(timeManager.getGameTime()); - } - }); - } else { - float radius = this.getRadius(store, deployableComponent.getSpawnInstant()); - this.handleDebugGraphics(world, deployableComponent.getDebugColor(), pos, radius * 2.0F); - switch (deployableComponent.getFlag(DeployableComponent.DeployableFlag.STATE)) { - case 0: - deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 1); - break; - case 1: - deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 2); - playAnimation(store, entityRef, this, "Grow"); - break; - case 2: - if (radius >= this.endRadius) { - deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 3); - playAnimation(store, entityRef, this, "Looping"); + TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + if (transformComponent != null) { + Vector3d pos = transformComponent.getPosition(); + World world = store.getExternalData().getWorld(); + Ref entityRef = archetypeChunk.getReferenceTo(index); + if (!deployableComponent.getOwner().isValid()) { + world.execute(() -> { + if (entityRef.isValid()) { + DespawnComponent despawn = store.ensureAndGetComponent(entityRef, DespawnComponent.getComponentType()); + WorldTimeResource timeManager = commandBuffer.getResource(WorldTimeResource.getResourceType()); + despawn.setDespawn(timeManager.getGameTime()); } - } + }); + } else { + float radius = this.getRadius(store, deployableComponent.getSpawnInstant()); + this.handleDebugGraphics(world, deployableComponent.getDebugColor(), pos, radius * 2.0F); + switch (deployableComponent.getFlag(DeployableComponent.DeployableFlag.STATE)) { + case 0: + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 1); + break; + case 1: + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 2); + playAnimation(store, entityRef, this, "Grow"); + break; + case 2: + if (radius >= this.endRadius) { + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 3); + playAnimation(store, entityRef, this, "Looping"); + } + } - Ref trapRef = archetypeChunk.getReferenceTo(index); - deployableComponent.setTimeSinceLastAttack(deployableComponent.getTimeSinceLastAttack() + dt); - if (deployableComponent.getTimeSinceLastAttack() > this.damageInterval && this.isLive(store, deployableComponent)) { - deployableComponent.setTimeSinceLastAttack(0.0F); - this.handleDetection(store, commandBuffer, trapRef, deployableComponent, pos, radius, DamageCause.PHYSICAL); + Ref trapRef = archetypeChunk.getReferenceTo(index); + deployableComponent.setTimeSinceLastAttack(deployableComponent.getTimeSinceLastAttack() + dt); + if (deployableComponent.getTimeSinceLastAttack() > this.damageInterval && this.isLive(store, deployableComponent)) { + deployableComponent.setTimeSinceLastAttack(0.0F); + this.handleDetection(store, commandBuffer, trapRef, deployableComponent, pos, radius, DamageCause.PHYSICAL); + } } } } @Override protected void handleDetection( - final Store store, - final CommandBuffer commandBuffer, - final Ref deployableRef, - final DeployableComponent deployableComponent, - Vector3d position, + @Nonnull final Store store, + @Nonnull final CommandBuffer commandBuffer, + @Nonnull final Ref deployableRef, + @Nonnull final DeployableComponent deployableComponent, + @Nonnull Vector3d position, float radius, - final DamageCause damageCause + @Nonnull final DamageCause damageCause ) { World world = store.getExternalData().getWorld(); var consumer = new Consumer>() { - public void accept(Ref entityStoreRef) { - if (entityStoreRef != deployableRef) { - if (store.getComponent(entityStoreRef, DeployableComponent.getComponentType()) == null) { - DeployableTrapConfig.this.attackTarget(entityStoreRef, deployableRef, damageCause, commandBuffer); + public void accept(@Nonnull Ref ref) { + if (ref != deployableRef) { + if (store.getComponent(ref, DeployableComponent.getComponentType()) == null) { + DeployableTrapConfig.this.attackTarget(ref, deployableRef, damageCause, commandBuffer); if (DeployableTrapConfig.this.destroyOnTriggered && deployableComponent.getFlag(DeployableComponent.DeployableFlag.TRIGGERED) == 0) { DeployableTrapConfig.this.onTriggered(store, deployableRef); deployableComponent.setFlag(DeployableComponent.DeployableFlag.TRIGGERED, 1); } - DeployableTrapConfig.this.applyEffectToTarget(store, entityStoreRef); + DeployableTrapConfig.this.applyEffectToTarget(store, ref); } } } diff --git a/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapSpawnerConfig.java b/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapSpawnerConfig.java index cfd70aae..11d9db74 100644 --- a/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapSpawnerConfig.java +++ b/src/com/hypixel/hytale/builtin/deployables/config/DeployableTrapSpawnerConfig.java @@ -23,6 +23,7 @@ import java.time.temporal.ChronoUnit; import javax.annotation.Nonnull; public class DeployableTrapSpawnerConfig extends DeployableTrapConfig { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DeployableTrapSpawnerConfig.class, DeployableTrapSpawnerConfig::new, DeployableTrapConfig.CODEC ) @@ -85,7 +86,7 @@ public class DeployableTrapSpawnerConfig extends DeployableTrapConfig { playAnimation(store, entityRef, this, "Deploy"); } - private void tickDeployAnimationState(Store store, DeployableComponent component, Ref entityRef) { + private void tickDeployAnimationState(@Nonnull Store store, @Nonnull DeployableComponent component, @Nonnull Ref entityRef) { component.setFlag(DeployableComponent.DeployableFlag.STATE, 2); playAnimation(store, entityRef, this, "Deploy"); } @@ -102,34 +103,43 @@ public class DeployableTrapSpawnerConfig extends DeployableTrapConfig { @Nonnull Store store, @Nonnull DeployableComponent component, @Nonnull Ref entityRef, - CommandBuffer commandBuffer, + @Nonnull CommandBuffer commandBuffer, float dt ) { - Vector3d position = store.getComponent(entityRef, TransformComponent.getComponentType()).getPosition(); - float radius = this.getRadius(store, component.getSpawnInstant()); - component.setTimeSinceLastAttack(component.getTimeSinceLastAttack() + dt); - if (component.getTimeSinceLastAttack() > this.damageInterval && this.isLive(store, component)) { - component.setTimeSinceLastAttack(0.0F); - this.handleDetection(store, commandBuffer, entityRef, component, position, radius, DamageCause.PHYSICAL); + TransformComponent transformComponent = store.getComponent(entityRef, TransformComponent.getComponentType()); + if (transformComponent != null) { + Vector3d position = transformComponent.getPosition(); + float radius = this.getRadius(store, component.getSpawnInstant()); + component.setTimeSinceLastAttack(component.getTimeSinceLastAttack() + dt); + if (component.getTimeSinceLastAttack() > this.damageInterval && this.isLive(store, component)) { + component.setTimeSinceLastAttack(0.0F); + this.handleDetection(store, commandBuffer, entityRef, component, position, radius, DamageCause.PHYSICAL); + } } } private void tickTriggeredState( - CommandBuffer commandBuffer, @Nonnull Store store, @Nonnull DeployableComponent component, @Nonnull Ref entityRef + @Nonnull CommandBuffer commandBuffer, + @Nonnull Store store, + @Nonnull DeployableComponent component, + @Nonnull Ref entityRef ) { - component.setFlag(DeployableComponent.DeployableFlag.STATE, 5); - Vector3d parentPosition = store.getComponent(entityRef, TransformComponent.getComponentType()).getPosition(); - Ref parentOwner = store.getComponent(entityRef, DeployableComponent.getComponentType()).getOwner(); - World world = store.getExternalData().getWorld(); - if (this.deployableSpawners != null) { - for (DeployableSpawner spawner : this.deployableSpawners) { - if (spawner != null) { - DeployableConfig config = spawner.getConfig(); - Vector3d[] positionOffsets = spawner.getPositionOffsets(); + TransformComponent transformComponent = store.getComponent(entityRef, TransformComponent.getComponentType()); + if (transformComponent != null) { + component.setFlag(DeployableComponent.DeployableFlag.STATE, 5); + Vector3d parentPosition = transformComponent.getPosition(); + Ref parentOwner = component.getOwner(); + World world = store.getExternalData().getWorld(); + if (this.deployableSpawners != null) { + for (DeployableSpawner spawner : this.deployableSpawners) { + if (spawner != null) { + DeployableConfig config = spawner.getConfig(); + Vector3d[] positionOffsets = spawner.getPositionOffsets(); - for (Vector3d offset : positionOffsets) { - Vector3f childPosition = Vector3d.add(parentPosition, offset).toVector3f(); - world.execute(() -> DeployablesUtils.spawnDeployable(commandBuffer, store, config, parentOwner, childPosition, new Vector3f(), "UP")); + for (Vector3d offset : positionOffsets) { + Vector3f childPosition = Vector3d.add(parentPosition, offset).toVector3f(); + world.execute(() -> DeployablesUtils.spawnDeployable(commandBuffer, store, config, parentOwner, childPosition, new Vector3f(), "UP")); + } } } } @@ -143,6 +153,9 @@ public class DeployableTrapSpawnerConfig extends DeployableTrapConfig { @Override protected void onTriggered(@Nonnull Store store, @Nonnull Ref ref) { - store.getComponent(ref, DeployableComponent.getComponentType()).setFlag(DeployableComponent.DeployableFlag.STATE, 4); + DeployableComponent deployableComponent = store.getComponent(ref, DeployableComponent.getComponentType()); + if (deployableComponent != null) { + deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 4); + } } } diff --git a/src/com/hypixel/hytale/builtin/deployables/config/DeployableTurretConfig.java b/src/com/hypixel/hytale/builtin/deployables/config/DeployableTurretConfig.java index 66838cd5..11b5577b 100644 --- a/src/com/hypixel/hytale/builtin/deployables/config/DeployableTurretConfig.java +++ b/src/com/hypixel/hytale/builtin/deployables/config/DeployableTurretConfig.java @@ -264,7 +264,10 @@ public class DeployableTurretConfig extends DeployableConfig { DeployableProjectileShooterComponent shooterComponent = store.getComponent(ref, DeployableProjectileShooterComponent.getComponentType()); Vector3d spawnPos = Vector3d.ZERO.clone(); if (this.projectileSpawnOffsets != null) { - spawnPos.add(this.projectileSpawnOffsets.get(component.getSpawnFace())); + Vector3d spawnOffset = this.projectileSpawnOffsets.get(component.getSpawnFace()); + if (spawnOffset != null) { + spawnPos.add(spawnOffset); + } } if (shooterComponent == null) { @@ -359,19 +362,24 @@ public class DeployableTurretConfig extends DeployableConfig { Vector3d rootPos = transformComponent.getPosition(); Vector3d projectileSpawnPos = Vector3d.ZERO.clone(); if (this.projectileSpawnOffsets != null) { - projectileSpawnPos = this.projectileSpawnOffsets.get(component.getSpawnFace()).clone(); + projectileSpawnPos = this.projectileSpawnOffsets.getOrDefault(component.getSpawnFace(), Vector3d.ZERO).clone(); } projectileSpawnPos.add(fwdDirection.clone().normalize()); projectileSpawnPos.add(rootPos); - UUID uuid = store.getComponent(ref, UUIDComponent.getComponentType()).getUuid(); - shooterComponent.spawnProjectile(ref, commandBuffer, this.projectileConfig, uuid, projectileSpawnPos, fwdDirection.clone()); + UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType()); + if (uuidComponent != null) { + UUID uuid = uuidComponent.getUuid(); + shooterComponent.spawnProjectile(ref, commandBuffer, this.projectileConfig, uuid, projectileSpawnPos, fwdDirection.clone()); + } + playAnimation(store, ref, this, "Shoot"); component.setTimeSinceLastAttack(0.0F); } } } + @Nonnull private Vector3d calculatedTargetPosition(@Nonnull Vector3d original) { return Vector3d.add(original.clone(), this.targetOffset); } @@ -411,8 +419,12 @@ public class DeployableTurretConfig extends DeployableConfig { return false; } else { BlockType blockType = BlockType.getAssetMap().getAsset(id); - BlockMaterial material = blockType.getMaterial(); - return material == BlockMaterial.Empty ? false : blockType.getOpacity() != Opacity.Transparent; + if (blockType == null) { + return false; + } else { + BlockMaterial material = blockType.getMaterial(); + return material != null && material != BlockMaterial.Empty ? blockType.getOpacity() != Opacity.Transparent : false; + } } }, attackerPos.x, attackerPos.y, attackerPos.z, direction.x, direction.y, direction.z, distance); if (blockPosition == null) { @@ -457,44 +469,46 @@ public class DeployableTurretConfig extends DeployableConfig { shooterComponent.getProjectilesForRemoval().add(projectileRef); } else { TransformComponent projTransformComponent = store.getComponent(projectileRef, TransformComponent.getComponentType()); - - assert projTransformComponent != null; - - Vector3d projPos = projTransformComponent.getPosition(); - AtomicReference hit = new AtomicReference<>(Boolean.FALSE); - DeployableProjectileComponent dProjComponent = store.getComponent(projectileRef, DeployableProjectileComponent.getComponentType()); - - assert dProjComponent != null; - - Vector3d prevPos = dProjComponent.getPreviousTickPosition(); - Vector3d increment = new Vector3d((projPos.x - prevPos.x) * 0.1F, (projPos.y - prevPos.y) * 0.1F, (projPos.z - prevPos.z) * 0.1F); - - for (int j = 0; j < 10; j++) { - if (!hit.get()) { - Vector3d scanPos = dProjComponent.getPreviousTickPosition().clone(); - scanPos.x = scanPos.x + increment.x * j; - scanPos.y = scanPos.y + increment.y * j; - scanPos.z = scanPos.z + increment.z * j; - if (this.getDebugVisuals()) { - DebugUtils.addSphere(store.getExternalData().getWorld(), scanPos, new Vector3f(1.0F, 1.0F, 1.0F), 0.1F, 5.0F); - } - - for (Ref targetEntityRef : TargetUtil.getAllEntitiesInSphere(scanPos, 0.1, store)) { - if (hit.get()) { - return; - } - - this.projectileHit(targetEntityRef, projectileRef, shooterComponent, store, commandBuffer); - hit.set(Boolean.TRUE); - } - } - } - - dProjComponent.setPreviousTickPosition(projPos); - if (!hit.get()) { - StandardPhysicsProvider physics = store.getComponent(projectileRef, StandardPhysicsProvider.getComponentType()); - if (physics != null && physics.getState() != StandardPhysicsProvider.STATE.ACTIVE) { + if (projTransformComponent == null) { + shooterComponent.getProjectilesForRemoval().add(projectileRef); + } else { + Vector3d projPos = projTransformComponent.getPosition(); + AtomicReference hit = new AtomicReference<>(Boolean.FALSE); + DeployableProjectileComponent deployableProjectileComponent = store.getComponent(projectileRef, DeployableProjectileComponent.getComponentType()); + if (deployableProjectileComponent == null) { shooterComponent.getProjectilesForRemoval().add(projectileRef); + } else { + Vector3d prevPos = deployableProjectileComponent.getPreviousTickPosition(); + Vector3d increment = new Vector3d((projPos.x - prevPos.x) * 0.1F, (projPos.y - prevPos.y) * 0.1F, (projPos.z - prevPos.z) * 0.1F); + + for (int j = 0; j < 10; j++) { + if (!hit.get()) { + Vector3d scanPos = deployableProjectileComponent.getPreviousTickPosition().clone(); + scanPos.x = scanPos.x + increment.x * j; + scanPos.y = scanPos.y + increment.y * j; + scanPos.z = scanPos.z + increment.z * j; + if (this.getDebugVisuals()) { + DebugUtils.addSphere(store.getExternalData().getWorld(), scanPos, new Vector3f(1.0F, 1.0F, 1.0F), 0.1F, 5.0F); + } + + for (Ref targetEntityRef : TargetUtil.getAllEntitiesInSphere(scanPos, 0.1, store)) { + if (hit.get()) { + return; + } + + this.projectileHit(targetEntityRef, projectileRef, shooterComponent, store, commandBuffer); + hit.set(Boolean.TRUE); + } + } + } + + deployableProjectileComponent.setPreviousTickPosition(projPos); + if (!hit.get()) { + StandardPhysicsProvider physicsComponent = store.getComponent(projectileRef, StandardPhysicsProvider.getComponentType()); + if (physicsComponent != null && physicsComponent.getState() != StandardPhysicsProvider.STATE.ACTIVE) { + shooterComponent.getProjectilesForRemoval().add(projectileRef); + } + } } } } @@ -541,6 +555,7 @@ public class DeployableTurretConfig extends DeployableConfig { knockbackComponent.setDuration(this.projectileKnockback.getDuration()); } + @Nonnull @Override public String toString() { return "DeployableTurretConfig{}" + super.toString(); diff --git a/src/com/hypixel/hytale/builtin/deployables/interaction/SpawnDeployableFromRaycastInteraction.java b/src/com/hypixel/hytale/builtin/deployables/interaction/SpawnDeployableFromRaycastInteraction.java index a64af8a8..214c031c 100644 --- a/src/com/hypixel/hytale/builtin/deployables/interaction/SpawnDeployableFromRaycastInteraction.java +++ b/src/com/hypixel/hytale/builtin/deployables/interaction/SpawnDeployableFromRaycastInteraction.java @@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.ints.Int2FloatMap.Entry; import it.unimi.dsi.fastutil.objects.Object2FloatMap; import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class SpawnDeployableFromRaycastInteraction extends SimpleInstantInteraction { @Nonnull @@ -62,6 +63,7 @@ public class SpawnDeployableFromRaycastInteraction extends SimpleInstantInteract .afterDecode(SpawnDeployableFromRaycastInteraction::processConfig) .build(); protected Object2FloatMap unknownEntityStats; + @Nullable protected Int2FloatMap entityStats; protected float maxPlacementDistance; private DeployableConfig config; diff --git a/src/com/hypixel/hytale/builtin/deployables/system/DeployablesSystem.java b/src/com/hypixel/hytale/builtin/deployables/system/DeployablesSystem.java index 15f1670f..61928edf 100644 --- a/src/com/hypixel/hytale/builtin/deployables/system/DeployablesSystem.java +++ b/src/com/hypixel/hytale/builtin/deployables/system/DeployablesSystem.java @@ -29,7 +29,9 @@ import it.unimi.dsi.fastutil.objects.ObjectList; import javax.annotation.Nonnull; public class DeployablesSystem { - private static void spawnParticleEffect(Ref sourceRef, CommandBuffer commandBuffer, Vector3d position, ModelParticle particle) { + private static void spawnParticleEffect( + @Nonnull Ref sourceRef, @Nonnull CommandBuffer commandBuffer, @Nonnull Vector3d position, @Nonnull ModelParticle particle + ) { Vector3f particlePositionOffset = particle.getPositionOffset(); Direction particleRotationOffset = particle.getRotationOffset(); Vector3d particlePosition = new Vector3d(position.x, position.y, position.z); @@ -66,8 +68,13 @@ public class DeployablesSystem { } @Override - public void tick(float dt, int index, ArchetypeChunk archetypeChunk, Store store, CommandBuffer commandBuffer) { + public void tick( + float dt, int index, ArchetypeChunk archetypeChunk, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer + ) { DeployableOwnerComponent deployableOwnerComponent = archetypeChunk.getComponent(index, DeployableOwnerComponent.getComponentType()); + + assert deployableOwnerComponent != null; + deployableOwnerComponent.tick(commandBuffer); } } @@ -79,7 +86,9 @@ public class DeployablesSystem { Ref ownerRef = deployableComponent.getOwner(); if (ownerRef != null && ownerRef.isValid()) { DeployableOwnerComponent deployableOwnerComponent = ownerRef.getStore().getComponent(ownerRef, DeployableOwnerComponent.getComponentType()); - deployableOwnerComponent.deRegisterDeployable(deployableConfig.getId(), ref); + if (deployableOwnerComponent != null) { + deployableOwnerComponent.deRegisterDeployable(deployableConfig.getId(), ref); + } } } @@ -93,24 +102,30 @@ public class DeployablesSystem { @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { DeployableComponent deployableComponent = store.getComponent(ref, DeployableComponent.getComponentType()); - DeployableConfig deployableConfig = deployableComponent.getConfig(); - Vector3d position = store.getComponent(ref, TransformComponent.getComponentType()).getPosition(); - Ref ownerRef = deployableComponent.getOwner(); - int soundIndex = deployableConfig.getDeploySoundEventIndex(); - SoundUtil.playSoundEvent3d(null, soundIndex, position, commandBuffer); - ModelParticle[] particles = deployableConfig.getSpawnParticles(); - if (particles != null) { - for (ModelParticle particle : particles) { - DeployablesSystem.spawnParticleEffect(ref, commandBuffer, position, particle); + + assert deployableComponent != null; + + TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); + if (transformComponent != null) { + DeployableConfig deployableConfig = deployableComponent.getConfig(); + Vector3d position = transformComponent.getPosition(); + Ref ownerRef = deployableComponent.getOwner(); + int soundIndex = deployableConfig.getDeploySoundEventIndex(); + SoundUtil.playSoundEvent3d(null, soundIndex, position, commandBuffer); + ModelParticle[] particles = deployableConfig.getSpawnParticles(); + if (particles != null) { + for (ModelParticle particle : particles) { + DeployablesSystem.spawnParticleEffect(ref, commandBuffer, position, particle); + } } - } - if (ownerRef.isValid()) { - DeployableOwnerComponent deployableOwnerComponent = ownerRef.getStore().getComponent(ownerRef, DeployableOwnerComponent.getComponentType()); + if (ownerRef.isValid()) { + DeployableOwnerComponent deployableOwnerComponent = ownerRef.getStore().getComponent(ownerRef, DeployableOwnerComponent.getComponentType()); - assert deployableOwnerComponent != null; + assert deployableOwnerComponent != null; - deployableOwnerComponent.registerDeployable(ownerRef, deployableComponent, deployableConfig.getId(), ref, store); + deployableOwnerComponent.registerDeployable(ownerRef, deployableComponent, deployableConfig.getId(), ref, store); + } } } @@ -119,8 +134,15 @@ public class DeployablesSystem { @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { DeployableComponent deployableComponent = store.getComponent(ref, DeployableComponent.getComponentType()); + + assert deployableComponent != null; + + TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); + + assert transformComponent != null; + DeployableConfig deployableConfig = deployableComponent.getConfig(); - Vector3d position = store.getComponent(ref, TransformComponent.getComponentType()).getPosition(); + Vector3d position = transformComponent.getPosition(); int despawnSoundIndex = deployableConfig.getDespawnSoundEventIndex(); int dieSoundIndex = deployableConfig.getDieSoundEventIndex(); if (dieSoundIndex != 0) { @@ -152,9 +174,14 @@ public class DeployablesSystem { } @Override - public void tick(float dt, int index, ArchetypeChunk archetypeChunk, Store store, CommandBuffer commandBuffer) { - DeployableComponent comp = archetypeChunk.getComponent(index, DeployableComponent.getComponentType()); - comp.tick(dt, index, archetypeChunk, store, commandBuffer); + public void tick( + float dt, int index, ArchetypeChunk archetypeChunk, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer + ) { + DeployableComponent deployableComponent = archetypeChunk.getComponent(index, DeployableComponent.getComponentType()); + + assert deployableComponent != null; + + deployableComponent.tick(dt, index, archetypeChunk, store, commandBuffer); } } } diff --git a/src/com/hypixel/hytale/builtin/fluid/FluidCommand.java b/src/com/hypixel/hytale/builtin/fluid/FluidCommand.java index 769b5241..04858212 100644 --- a/src/com/hypixel/hytale/builtin/fluid/FluidCommand.java +++ b/src/com/hypixel/hytale/builtin/fluid/FluidCommand.java @@ -27,7 +27,8 @@ import com.hypixel.hytale.server.core.util.TargetUtil; import javax.annotation.Nonnull; public class FluidCommand extends AbstractCommandCollection { - private static final SingleArgumentType FLUID_ARG = new AssetArgumentType("Fluid", Fluid.class, ""); + @Nonnull + private static final SingleArgumentType FLUID_ARG = new AssetArgumentType("Fluid", Fluid.class, "server.commands.fluid.fluidArgType.desc"); public FluidCommand() { super("fluid", "server.commands.fluid.desc"); @@ -42,7 +43,9 @@ public class FluidCommand extends AbstractCommandCollection { @Nonnull private static final Message MESSAGE_COMMANDS_NO_SECTION_COMPONENT = Message.translation("server.commands.noSectionComponent"); @Nonnull - private final OptionalArg targetOffset = this.withOptionalArg("offset", "", ArgTypes.RELATIVE_BLOCK_POSITION); + private final OptionalArg targetOffset = this.withOptionalArg( + "offset", "server.commands.fluid.get.offset.desc", ArgTypes.RELATIVE_BLOCK_POSITION + ); public GetCommand() { super("get", "server.commands.fluid.get.desc"); @@ -94,11 +97,13 @@ public class FluidCommand extends AbstractCommandCollection { @Nonnull private static final Message MESSAGE_COMMANDS_NO_SECTION_COMPONENT = Message.translation("server.commands.noSectionComponent"); @Nonnull - private final RequiredArg fluid = this.withRequiredArg("fluid", "", FluidCommand.FLUID_ARG); + private final RequiredArg fluid = this.withRequiredArg("fluid", "server.commands.fluid.set.fluid.desc", FluidCommand.FLUID_ARG); @Nonnull - private final RequiredArg level = this.withRequiredArg("level", "", ArgTypes.INTEGER); + private final RequiredArg level = this.withRequiredArg("level", "server.commands.fluid.set.level.desc", ArgTypes.INTEGER); @Nonnull - private final OptionalArg targetOffset = this.withOptionalArg("offset", "", ArgTypes.RELATIVE_BLOCK_POSITION); + private final OptionalArg targetOffset = this.withOptionalArg( + "offset", "server.commands.fluid.set.offset.desc", ArgTypes.RELATIVE_BLOCK_POSITION + ); public SetCommand() { super("set", "server.commands.fluid.set.desc"); @@ -163,13 +168,15 @@ public class FluidCommand extends AbstractCommandCollection { @Nonnull private static final Message MESSAGE_COMMANDS_ERRORS_PLAYER_NOT_LOOKING_AT_BLOCK = Message.translation("server.commands.errors.playerNotLookingAtBlock"); @Nonnull - private final RequiredArg radius = this.withRequiredArg("radius", "", ArgTypes.INTEGER); + private final RequiredArg radius = this.withRequiredArg("radius", "server.commands.fluid.setradius.radius.desc", ArgTypes.INTEGER); @Nonnull - private final RequiredArg fluid = this.withRequiredArg("fluid", "", FluidCommand.FLUID_ARG); + private final RequiredArg fluid = this.withRequiredArg("fluid", "server.commands.fluid.setradius.fluid.desc", FluidCommand.FLUID_ARG); @Nonnull - private final RequiredArg level = this.withRequiredArg("level", "", ArgTypes.INTEGER); + private final RequiredArg level = this.withRequiredArg("level", "server.commands.fluid.setradius.level.desc", ArgTypes.INTEGER); @Nonnull - private final OptionalArg targetOffset = this.withOptionalArg("offset", "", ArgTypes.RELATIVE_BLOCK_POSITION); + private final OptionalArg targetOffset = this.withOptionalArg( + "offset", "server.commands.fluid.setradius.offset.desc", ArgTypes.RELATIVE_BLOCK_POSITION + ); public SetRadiusCommand() { super("setradius", "server.commands.fluid.setradius.desc"); @@ -209,38 +216,50 @@ public class FluidCommand extends AbstractCommandCollection { int maxCY = ChunkUtil.chunkCoordinate(maxY); int minCZ = ChunkUtil.chunkCoordinate(minZ); int maxCZ = ChunkUtil.chunkCoordinate(maxZ); - Integer finalLevel = level; + byte levelByteValue = level.byteValue(); for (int cx = minCX; cx <= maxCX; cx++) { for (int cz = minCZ; cz <= maxCZ; cz++) { - int relMinX = MathUtil.clamp(minX - ChunkUtil.minBlock(cx), 0, 32); - int relMaxX = MathUtil.clamp(maxX - ChunkUtil.minBlock(cx), 0, 32); - int relMinZ = MathUtil.clamp(minZ - ChunkUtil.minBlock(cz), 0, 32); - int relMaxZ = MathUtil.clamp(maxZ - ChunkUtil.minBlock(cz), 0, 32); + int minBlockX = ChunkUtil.minBlock(cx); + int minBlockZ = ChunkUtil.minBlock(cz); + int relMinX = MathUtil.clamp(minX - minBlockX, 0, 32); + int relMaxX = MathUtil.clamp(maxX - minBlockX, 0, 32); + int relMinZ = MathUtil.clamp(minZ - minBlockZ, 0, 32); + int relMaxZ = MathUtil.clamp(maxZ - minBlockZ, 0, 32); for (int cy = minCY; cy <= maxCY; cy++) { - chunkStore.getChunkSectionReferenceAsync(cx, cy, cz).thenAcceptAsync(section -> { - Store sectionStore = section.getStore(); - FluidSection fluidSection = sectionStore.getComponent((Ref)section, FluidSection.getComponentType()); - if (fluidSection != null) { - int relMinY = MathUtil.clamp(minY - ChunkUtil.minBlock(fluidSection.getY()), 0, 32); - int relMaxY = MathUtil.clamp(maxY - ChunkUtil.minBlock(fluidSection.getY()), 0, 32); - ChunkSection sectionComp = sectionStore.getComponent((Ref)section, ChunkSection.getComponentType()); - WorldChunk worldChunk = sectionStore.getComponent(sectionComp.getChunkColumnReference(), WorldChunk.getComponentType()); + chunkStore.getChunkSectionReferenceAsync(cx, cy, cz) + .thenAcceptAsync( + section -> { + Store sectionStore = section.getStore(); + FluidSection fluidSectionComponent = sectionStore.getComponent((Ref)section, FluidSection.getComponentType()); + if (fluidSectionComponent != null) { + ChunkSection chunkSectionComponent = sectionStore.getComponent((Ref)section, ChunkSection.getComponentType()); + if (chunkSectionComponent != null) { + WorldChunk worldChunkComponent = sectionStore.getComponent( + chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType() + ); + if (worldChunkComponent != null) { + int relMinY = MathUtil.clamp(minY - ChunkUtil.minBlock(fluidSectionComponent.getY()), 0, 32); + int relMaxY = MathUtil.clamp(maxY - ChunkUtil.minBlock(fluidSectionComponent.getY()), 0, 32); - for (int y = relMinY; y < relMaxY; y++) { - for (int z = relMinZ; z < relMaxZ; z++) { - for (int x = relMinX; x < relMaxX; x++) { - int index = ChunkUtil.indexBlock(x, y, z); - fluidSection.setFluid(index, fluid, finalLevel.byteValue()); - worldChunk.setTicking(pos.x, pos.y, pos.z, true); + for (int y = relMinY; y < relMaxY; y++) { + for (int z = relMinZ; z < relMaxZ; z++) { + for (int x = relMinX; x < relMaxX; x++) { + int blockIndex = ChunkUtil.indexBlock(x, y, z); + fluidSectionComponent.setFluid(blockIndex, fluid, levelByteValue); + worldChunkComponent.setTicking(pos.x, pos.y, pos.z, true); + } + } + } + + worldChunkComponent.markNeedsSaving(); + } } } - } - - worldChunk.markNeedsSaving(); - } - }, world); + }, + world + ); } } } diff --git a/src/com/hypixel/hytale/builtin/fluid/FluidPlugin.java b/src/com/hypixel/hytale/builtin/fluid/FluidPlugin.java index b1040165..dba4dc24 100644 --- a/src/com/hypixel/hytale/builtin/fluid/FluidPlugin.java +++ b/src/com/hypixel/hytale/builtin/fluid/FluidPlugin.java @@ -3,6 +3,8 @@ package com.hypixel.hytale.builtin.fluid; import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap; import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap; import com.hypixel.hytale.codec.lookup.Priority; +import com.hypixel.hytale.component.ComponentRegistryProxy; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.event.EventPriority; import com.hypixel.hytale.logger.HytaleLogger; @@ -11,6 +13,7 @@ import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.fluid.DefaultFluidTicker; import com.hypixel.hytale.server.core.asset.type.fluid.FiniteFluidTicker; +import com.hypixel.hytale.server.core.asset.type.fluid.FireFluidTicker; import com.hypixel.hytale.server.core.asset.type.fluid.Fluid; import com.hypixel.hytale.server.core.asset.type.fluid.FluidTicker; import com.hypixel.hytale.server.core.plugin.JavaPlugin; @@ -19,6 +22,7 @@ import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk; import com.hypixel.hytale.server.core.universe.world.chunk.ChunkColumn; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection; +import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection; import com.hypixel.hytale.server.core.universe.world.events.ChunkPreLoadProcessEvent; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; @@ -28,6 +32,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class FluidPlugin extends JavaPlugin { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); private static FluidPlugin instance; @@ -42,76 +47,93 @@ public class FluidPlugin extends JavaPlugin { @Override protected void setup() { + ComponentRegistryProxy chunkStoreRegistry = this.getChunkStoreRegistry(); FluidTicker.CODEC.register(Priority.DEFAULT, "Default", DefaultFluidTicker.class, DefaultFluidTicker.CODEC); + FluidTicker.CODEC.register("Fire", FireFluidTicker.class, FireFluidTicker.CODEC); FluidTicker.CODEC.register("Finite", FiniteFluidTicker.class, FiniteFluidTicker.CODEC); - this.getChunkStoreRegistry().registerSystem(new FluidSystems.EnsureFluidSection()); - this.getChunkStoreRegistry().registerSystem(new FluidSystems.MigrateFromColumn()); - this.getChunkStoreRegistry().registerSystem(new FluidSystems.SetupSection()); - this.getChunkStoreRegistry().registerSystem(new FluidSystems.LoadPacketGenerator()); - this.getChunkStoreRegistry().registerSystem(new FluidSystems.ReplicateChanges()); - this.getChunkStoreRegistry().registerSystem(new FluidSystems.Ticking()); + ComponentType chunkSectionComponentType = ChunkSection.getComponentType(); + ComponentType fluidSectionComponentType = FluidSection.getComponentType(); + ComponentType chunkColumnComponentType = ChunkColumn.getComponentType(); + ComponentType blockChunkComponentType = BlockChunk.getComponentType(); + ComponentType worldChunkComponentType = WorldChunk.getComponentType(); + chunkStoreRegistry.registerSystem(new FluidSystems.EnsureFluidSection(chunkSectionComponentType, fluidSectionComponentType)); + chunkStoreRegistry.registerSystem(new FluidSystems.MigrateFromColumn(chunkColumnComponentType, blockChunkComponentType, fluidSectionComponentType)); + chunkStoreRegistry.registerSystem(new FluidSystems.SetupSection(chunkSectionComponentType, fluidSectionComponentType)); + chunkStoreRegistry.registerSystem(new FluidSystems.LoadPacketGenerator(chunkColumnComponentType, fluidSectionComponentType)); + chunkStoreRegistry.registerSystem(new FluidSystems.ReplicateChanges(chunkSectionComponentType, fluidSectionComponentType, worldChunkComponentType)); + chunkStoreRegistry.registerSystem(new FluidSystems.Ticking(chunkSectionComponentType, fluidSectionComponentType, blockChunkComponentType)); this.getEventRegistry().registerGlobal(EventPriority.FIRST, ChunkPreLoadProcessEvent.class, FluidPlugin::onChunkPreProcess); this.getCommandRegistry().registerCommand(new FluidCommand()); } private static void onChunkPreProcess(@Nonnull ChunkPreLoadProcessEvent event) { if (event.isNewlyGenerated()) { - WorldChunk wc = event.getChunk(); + WorldChunk worldChunk = event.getChunk(); Holder holder = event.getHolder(); - ChunkColumn column = holder.getComponent(ChunkColumn.getComponentType()); - if (column != null) { - BlockChunk blockChunk = holder.getComponent(BlockChunk.getComponentType()); - if (blockChunk != null) { + ChunkColumn chunkColumnComponent = holder.getComponent(ChunkColumn.getComponentType()); + if (chunkColumnComponent != null) { + BlockChunk blockChunkComponent = holder.getComponent(BlockChunk.getComponentType()); + if (blockChunkComponent != null) { IndexedLookupTableAssetMap fluidMap = Fluid.getAssetMap(); BlockTypeAssetMap blockMap = BlockType.getAssetMap(); - Holder[] sections = column.getSectionHolders(); + Holder[] sections = chunkColumnComponent.getSectionHolders(); if (sections != null) { for (int i = 0; i < sections.length && i < 10; i++) { Holder section = sections[i]; - FluidSection fluid = section.getComponent(FluidSection.getComponentType()); - if (fluid != null && !fluid.isEmpty()) { - BlockSection blockSection = section.ensureAndGetComponent(BlockSection.getComponentType()); + FluidSection fluidSectionComponent = section.getComponent(FluidSection.getComponentType()); + if (fluidSectionComponent != null && !fluidSectionComponent.isEmpty()) { + BlockSection blockSectionComponent = section.ensureAndGetComponent(BlockSection.getComponentType()); for (int idx = 0; idx < 32768; idx++) { - int fluidId = fluid.getFluidId(idx); + int fluidId = fluidSectionComponent.getFluidId(idx); if (fluidId != 0) { Fluid fluidType = fluidMap.getAsset(fluidId); if (fluidType == null) { LOGGER.at(Level.WARNING) - .log("Invalid fluid found in chunk section: %d, %d %d with id %d", fluid.getX(), fluid.getY(), fluid.getZ(), fluid); - fluid.setFluid(idx, 0, (byte)0); + .log( + "Invalid fluid found in chunk section: %d, %d %d with id %d", + fluidSectionComponent.getX(), + fluidSectionComponent.getY(), + fluidSectionComponent.getZ(), + fluidSectionComponent + ); + fluidSectionComponent.setFluid(idx, 0, (byte)0); } else { FluidTicker ticker = fluidType.getTicker(); - if (FluidTicker.isSolid(blockMap.getAsset(blockSection.get(idx)))) { - fluid.setFluid(idx, 0, (byte)0); + if (FluidTicker.isSolid(blockMap.getAsset(blockSectionComponent.get(idx)))) { + fluidSectionComponent.setFluid(idx, 0, (byte)0); } else { if (!ticker.canDemote()) { - int x = ChunkUtil.minBlock(fluid.getX()) + ChunkUtil.xFromIndex(idx); - int y = ChunkUtil.minBlock(fluid.getY()) + ChunkUtil.yFromIndex(idx); - int z = ChunkUtil.minBlock(fluid.getZ()) + ChunkUtil.zFromIndex(idx); + int x = ChunkUtil.minBlock(fluidSectionComponent.getX()) + ChunkUtil.xFromIndex(idx); + int y = ChunkUtil.minBlock(fluidSectionComponent.getY()) + ChunkUtil.yFromIndex(idx); + int z = ChunkUtil.minBlock(fluidSectionComponent.getZ()) + ChunkUtil.zFromIndex(idx); boolean canSpread = ChunkUtil.isBorderBlock(x, z) - || fluid.getFluidId(x - 1, y, z) == 0 && !FluidTicker.isSolid(blockMap.getAsset(blockSection.get(x - 1, y, z))) - || fluid.getFluidId(x + 1, y, z) == 0 && !FluidTicker.isSolid(blockMap.getAsset(blockSection.get(x + 1, y, z))) - || fluid.getFluidId(x, y, z - 1) == 0 && !FluidTicker.isSolid(blockMap.getAsset(blockSection.get(x, y, z - 1))) - || fluid.getFluidId(x, y, z + 1) == 0 && !FluidTicker.isSolid(blockMap.getAsset(blockSection.get(x, y, z + 1))); + || fluidSectionComponent.getFluidId(x - 1, y, z) == 0 + && !FluidTicker.isSolid(blockMap.getAsset(blockSectionComponent.get(x - 1, y, z))) + || fluidSectionComponent.getFluidId(x + 1, y, z) == 0 + && !FluidTicker.isSolid(blockMap.getAsset(blockSectionComponent.get(x + 1, y, z))) + || fluidSectionComponent.getFluidId(x, y, z - 1) == 0 + && !FluidTicker.isSolid(blockMap.getAsset(blockSectionComponent.get(x, y, z - 1))) + || fluidSectionComponent.getFluidId(x, y, z + 1) == 0 + && !FluidTicker.isSolid(blockMap.getAsset(blockSectionComponent.get(x, y, z + 1))); if (y > 0) { if (ChunkUtil.chunkCoordinate(y) == ChunkUtil.chunkCoordinate(y - 1)) { - canSpread |= fluid.getFluidId(x, y - 1, z) == 0 - && !FluidTicker.isSolid(blockMap.getAsset(blockSection.get(x, y - 1, z))); + canSpread |= fluidSectionComponent.getFluidId(x, y - 1, z) == 0 + && !FluidTicker.isSolid(blockMap.getAsset(blockSectionComponent.get(x, y - 1, z))); } else { FluidSection fluidSection2 = sections[i - 1].getComponent(FluidSection.getComponentType()); canSpread |= fluidSection2.getFluidId(x, y - 1, z) == 0 - && !FluidTicker.isSolid(blockMap.getAsset(blockChunk.getBlock(x, y - 1, z))); + && !FluidTicker.isSolid(blockMap.getAsset(blockChunkComponent.getBlock(x, y - 1, z))); } } if (!canSpread) { - blockSection.setTicking(idx, false); + blockSectionComponent.setTicking(idx, false); continue; } } - blockSection.setTicking(idx, true); + blockSectionComponent.setTicking(idx, true); } } } @@ -119,32 +141,32 @@ public class FluidPlugin extends JavaPlugin { } } - int tickingBlocks = blockChunk.getTickingBlocksCount(); + int tickingBlocks = blockChunkComponent.getTickingBlocksCount(); if (tickingBlocks != 0) { - FluidPlugin.PreprocesorAccessor accessor = new FluidPlugin.PreprocesorAccessor(wc, blockChunk, sections); + FluidPlugin.PreprocesorAccessor accessor = new FluidPlugin.PreprocesorAccessor(worldChunk, blockChunkComponent, sections); do { - blockChunk.preTick(Instant.MIN); + blockChunkComponent.preTick(Instant.MIN); for (int ix = 0; ix < sections.length; ix++) { Holder section = sections[ix]; - FluidSection fluidSection = section.getComponent(FluidSection.getComponentType()); - if (fluidSection != null && !fluidSection.isEmpty()) { - BlockSection blockSection = section.ensureAndGetComponent(BlockSection.getComponentType()); - fluidSection.preload(wc.getX(), ix, wc.getZ()); - accessor.blockSection = blockSection; - blockSection.forEachTicking( + FluidSection fluidSectionComponent = section.getComponent(FluidSection.getComponentType()); + if (fluidSectionComponent != null && !fluidSectionComponent.isEmpty()) { + BlockSection blockSectionComponent = section.ensureAndGetComponent(BlockSection.getComponentType()); + fluidSectionComponent.preload(worldChunk.getX(), ix, worldChunk.getZ()); + accessor.blockSection = blockSectionComponent; + blockSectionComponent.forEachTicking( accessor, - fluidSection, + fluidSectionComponent, ix, (preprocesorAccessor, fluidSection1, xx, yx, zx, block) -> { int fluidId = fluidSection1.getFluidId(xx, yx, zx); if (fluidId == 0) { return BlockTickStrategy.IGNORED; } else { - Fluid fluid = Fluid.getAssetMap().getAsset(fluidId); int blockX = fluidSection1.getX() << 5 | xx; int blockZ = fluidSection1.getZ() << 5 | zx; + Fluid fluid = Fluid.getAssetMap().getAsset(fluidId); return fluid.getTicker() .process( preprocesorAccessor.worldChunk.getWorld(), @@ -164,11 +186,11 @@ public class FluidPlugin extends JavaPlugin { } } - tickingBlocks = blockChunk.getTickingBlocksCount(); + tickingBlocks = blockChunkComponent.getTickingBlocksCount(); accessor.tick++; } while (tickingBlocks != 0 && accessor.tick <= 100L); - blockChunk.mergeTickingBlocks(); + blockChunkComponent.mergeTickingBlocks(); } } } @@ -177,13 +199,16 @@ public class FluidPlugin extends JavaPlugin { } public static class PreprocesorAccessor implements FluidTicker.Accessor { + @Nonnull private final WorldChunk worldChunk; + @Nonnull private final BlockChunk blockChunk; + @Nonnull private final Holder[] sections; public long tick; public BlockSection blockSection; - public PreprocesorAccessor(WorldChunk worldChunk, BlockChunk blockChunk, Holder[] sections) { + public PreprocesorAccessor(@Nonnull WorldChunk worldChunk, @Nonnull BlockChunk blockChunk, @Nonnull Holder[] sections) { this.worldChunk = worldChunk; this.blockChunk = blockChunk; this.sections = sections; diff --git a/src/com/hypixel/hytale/builtin/fluid/FluidState.java b/src/com/hypixel/hytale/builtin/fluid/FluidState.java index 8bc2fb6c..1b104862 100644 --- a/src/com/hypixel/hytale/builtin/fluid/FluidState.java +++ b/src/com/hypixel/hytale/builtin/fluid/FluidState.java @@ -7,6 +7,7 @@ import javax.annotation.Nonnull; public record FluidState(int fluidLevel, byte verticalFill) { public static int SOURCE_LEVEL = 0; public static final int FULL_LEVEL = 8; + @Nonnull public static final FluidState[] FLUID_STATES = generateFluidStates(8); public FluidState(int fluidLevel, int verticalFill) { diff --git a/src/com/hypixel/hytale/builtin/fluid/FluidSystems.java b/src/com/hypixel/hytale/builtin/fluid/FluidSystems.java index 58f91fd7..bf70935c 100644 --- a/src/com/hypixel/hytale/builtin/fluid/FluidSystems.java +++ b/src/com/hypixel/hytale/builtin/fluid/FluidSystems.java @@ -4,6 +4,7 @@ import com.hypixel.hytale.builtin.blocktick.system.ChunkBlockTickSystem; import com.hypixel.hytale.component.AddReason; import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.RemoveReason; @@ -56,11 +57,20 @@ public class FluidSystems { public static class EnsureFluidSection extends HolderSystem { @Nonnull - private static final Query QUERY = Query.and(ChunkSection.getComponentType(), Query.not(FluidSection.getComponentType())); + private final ComponentType fluidSectionComponentType; + @Nonnull + private final Query query; + + public EnsureFluidSection( + @Nonnull ComponentType chunkSectionComponentType, @Nonnull ComponentType fluidSectionComponentType + ) { + this.fluidSectionComponentType = fluidSectionComponentType; + this.query = Query.and(chunkSectionComponentType, Query.not(fluidSectionComponentType)); + } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - holder.addComponent(FluidSection.getComponentType(), new FluidSection()); + holder.addComponent(this.fluidSectionComponentType, new FluidSection()); } @Override @@ -70,7 +80,7 @@ public class FluidSystems { @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } @Nonnull @@ -81,6 +91,18 @@ public class FluidSystems { } public static class LoadPacketGenerator extends ChunkStore.LoadFuturePacketDataQuerySystem { + @Nonnull + private final ComponentType chunkColumnComponentType; + @Nonnull + private final ComponentType fluidSectionComponentType; + + public LoadPacketGenerator( + @Nonnull ComponentType chunkColumnComponentType, @Nonnull ComponentType fluidSectionComponentType + ) { + this.chunkColumnComponentType = chunkColumnComponentType; + this.fluidSectionComponentType = fluidSectionComponentType; + } + public void fetch( int index, @Nonnull ArchetypeChunk archetypeChunk, @@ -89,12 +111,12 @@ public class FluidSystems { PlayerRef query, @Nonnull List> results ) { - ChunkColumn chunkColumnComponent = archetypeChunk.getComponent(index, ChunkColumn.getComponentType()); + ChunkColumn chunkColumnComponent = archetypeChunk.getComponent(index, this.chunkColumnComponentType); assert chunkColumnComponent != null; for (Ref sectionRef : chunkColumnComponent.getSections()) { - FluidSection fluidSectionComponent = commandBuffer.getComponent(sectionRef, FluidSection.getComponentType()); + FluidSection fluidSectionComponent = commandBuffer.getComponent(sectionRef, this.fluidSectionComponentType); if (fluidSectionComponent != null) { results.add(fluidSectionComponent.getCachedPacket().exceptionally(throwable -> { if (throwable != null) { @@ -107,39 +129,59 @@ public class FluidSystems { } } + @Nonnull @Override public Query getQuery() { - return ChunkColumn.getComponentType(); + return this.chunkColumnComponentType; } } public static class MigrateFromColumn extends ChunkColumnMigrationSystem { @Nonnull - private final Query QUERY = Query.and(ChunkColumn.getComponentType(), BlockChunk.getComponentType()); + private final ComponentType chunkColumnComponentType; @Nonnull - private final Set> DEPENDENCIES = Set.of(new SystemDependency<>(Order.BEFORE, LegacyModule.MigrateLegacySections.class)); + private final ComponentType blockChunkComponentType; + @Nonnull + private final ComponentType fluidSectionComponentType; + @Nonnull + private final Query query; + @Nonnull + private final Set> dependencies = Set.of(new SystemDependency<>(Order.BEFORE, LegacyModule.MigrateLegacySections.class)); + + public MigrateFromColumn( + @Nonnull ComponentType chunkColumnComponentType, + @Nonnull ComponentType blockChunkComponentType, + @Nonnull ComponentType fluidSectionComponentType + ) { + this.chunkColumnComponentType = chunkColumnComponentType; + this.blockChunkComponentType = blockChunkComponentType; + this.fluidSectionComponentType = fluidSectionComponentType; + this.query = Query.and(chunkColumnComponentType, blockChunkComponentType); + } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - ChunkColumn chunkColumnComponent = holder.getComponent(ChunkColumn.getComponentType()); + ChunkColumn chunkColumnComponent = holder.getComponent(this.chunkColumnComponentType); assert chunkColumnComponent != null; - BlockChunk blockChunkComponent = holder.getComponent(BlockChunk.getComponentType()); + BlockChunk blockChunkComponent = holder.getComponent(this.blockChunkComponentType); assert blockChunkComponent != null; Holder[] sections = chunkColumnComponent.getSectionHolders(); - BlockSection[] legacySections = blockChunkComponent.getMigratedSections(); - if (legacySections != null) { - for (int i = 0; i < sections.length; i++) { - Holder section = sections[i]; - BlockSection paletteSection = legacySections[i]; - if (section != null && paletteSection != null) { - FluidSection fluid = paletteSection.takeMigratedFluid(); - if (fluid != null) { - section.putComponent(FluidSection.getComponentType(), fluid); - blockChunkComponent.markNeedsSaving(); + if (sections != null) { + BlockSection[] legacySections = blockChunkComponent.getMigratedSections(); + if (legacySections != null) { + for (int i = 0; i < sections.length; i++) { + Holder section = sections[i]; + BlockSection paletteSection = legacySections[i]; + if (section != null && paletteSection != null) { + FluidSection fluid = paletteSection.takeMigratedFluid(); + if (fluid != null) { + section.putComponent(this.fluidSectionComponentType, fluid); + blockChunkComponent.markNeedsSaving(); + } } } } @@ -153,19 +195,36 @@ public class FluidSystems { @Nonnull @Override public Query getQuery() { - return this.QUERY; + return this.query; } @Nonnull @Override public Set> getDependencies() { - return this.DEPENDENCIES; + return this.dependencies; } } public static class ReplicateChanges extends EntityTickingSystem implements RunWhenPausedSystem { @Nonnull - private static final Query QUERY = Query.and(ChunkSection.getComponentType(), FluidSection.getComponentType()); + private final ComponentType chunkSectionComponentType; + @Nonnull + private final ComponentType fluidSectionComponentType; + @Nonnull + private final ComponentType worldChunkComponentType; + @Nonnull + private final Query query; + + public ReplicateChanges( + @Nonnull ComponentType chunkSectionComponentType, + @Nonnull ComponentType fluidSectionComponentType, + @Nonnull ComponentType worldChunkComponentType + ) { + this.chunkSectionComponentType = chunkSectionComponentType; + this.fluidSectionComponentType = fluidSectionComponentType; + this.worldChunkComponentType = worldChunkComponentType; + this.query = Query.and(chunkSectionComponentType, fluidSectionComponentType); + } @Override public boolean isParallel(int archetypeChunkSize, int taskCount) { @@ -180,18 +239,18 @@ public class FluidSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType()); + FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, this.fluidSectionComponentType); assert fluidSectionComponent != null; IntOpenHashSet changes = fluidSectionComponent.getAndClearChangedPositions(); if (!changes.isEmpty()) { - ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType()); + ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, this.chunkSectionComponentType); assert chunkSectionComponent != null; World world = commandBuffer.getExternalData().getWorld(); - WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType()); + WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), this.worldChunkComponentType); int sectionY = chunkSectionComponent.getY(); world.execute(() -> { if (worldChunkComponent != null && worldChunkComponent.getWorld() != null) { @@ -276,7 +335,7 @@ public class FluidSystems { @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } @Nonnull @@ -288,17 +347,29 @@ public class FluidSystems { public static class SetupSection extends HolderSystem { @Nonnull - private static final Query QUERY = Query.and(ChunkSection.getComponentType(), FluidSection.getComponentType()); + private final ComponentType chunkSectionComponentType; @Nonnull - private static final Set> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, FluidSystems.MigrateFromColumn.class)); + private final ComponentType fluidSectionComponentType; + @Nonnull + private final Query query; + @Nonnull + private final Set> dependencies = Set.of(new SystemDependency<>(Order.AFTER, FluidSystems.MigrateFromColumn.class)); + + public SetupSection( + @Nonnull ComponentType chunkSectionComponentType, @Nonnull ComponentType fluidSectionComponentType + ) { + this.chunkSectionComponentType = chunkSectionComponentType; + this.fluidSectionComponentType = fluidSectionComponentType; + this.query = Query.and(chunkSectionComponentType, fluidSectionComponentType); + } @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - ChunkSection chunkSectionComponent = holder.getComponent(ChunkSection.getComponentType()); + ChunkSection chunkSectionComponent = holder.getComponent(this.chunkSectionComponentType); assert chunkSectionComponent != null; - FluidSection fluidSectionComponent = holder.getComponent(FluidSection.getComponentType()); + FluidSection fluidSectionComponent = holder.getComponent(this.fluidSectionComponentType); assert fluidSectionComponent != null; @@ -312,24 +383,41 @@ public class FluidSystems { @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } @Nonnull @Override public Set> getDependencies() { - return DEPENDENCIES; + return this.dependencies; } } public static class Ticking extends EntityTickingSystem { @Nonnull - private static final Query QUERY = Query.and(FluidSection.getComponentType(), ChunkSection.getComponentType()); + private final ComponentType chunkSectionComponentType; @Nonnull - private static final Set> DEPENDENCIES = Set.of( + private final ComponentType fluidSectionComponentType; + @Nonnull + private final ComponentType blockChunkComponentType; + @Nonnull + private final Query query; + @Nonnull + private final Set> dependencies = Set.of( new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class), new SystemDependency<>(Order.BEFORE, ChunkBlockTickSystem.Ticking.class) ); + public Ticking( + @Nonnull ComponentType chunkSectionComponentType, + @Nonnull ComponentType fluidSectionComponentType, + @Nonnull ComponentType blockChunkComponentType + ) { + this.chunkSectionComponentType = chunkSectionComponentType; + this.fluidSectionComponentType = fluidSectionComponentType; + this.blockChunkComponentType = blockChunkComponentType; + this.query = Query.and(fluidSectionComponentType, chunkSectionComponentType); + } + @Override public boolean isParallel(int archetypeChunkSize, int taskCount) { return EntityTickingSystem.useParallel(archetypeChunkSize, taskCount); @@ -343,36 +431,35 @@ public class FluidSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, ChunkSection.getComponentType()); + ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, this.chunkSectionComponentType); assert chunkSectionComponent != null; - FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, FluidSection.getComponentType()); + FluidSection fluidSectionComponent = archetypeChunk.getComponent(index, this.fluidSectionComponentType); assert fluidSectionComponent != null; Ref chunkRef = chunkSectionComponent.getChunkColumnReference(); - BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType()); - - assert blockChunkComponent != null; - - BlockSection blockSection = blockChunkComponent.getSectionAtIndex(fluidSectionComponent.getY()); - if (blockSection != null) { - if (blockSection.getTickingBlocksCountCopy() != 0) { - FluidTicker.CachedAccessor accessor = FluidTicker.CachedAccessor.of(commandBuffer, fluidSectionComponent, blockSection, 5); - blockSection.forEachTicking(accessor, commandBuffer, fluidSectionComponent.getY(), (accessor1, commandBuffer1, x, y, z, block) -> { - FluidSection fluidSection1 = accessor1.selfFluidSection; - BlockSection blockSection1 = accessor1.selfBlockSection; - int fluidId = fluidSection1.getFluidId(x, y, z); - if (fluidId == 0) { - return BlockTickStrategy.IGNORED; - } else { - Fluid fluid = Fluid.getAssetMap().getAsset(fluidId); - int blockX = fluidSection1.getX() << 5 | x; - int blockZ = fluidSection1.getZ() << 5 | z; - return fluid.getTicker().tick(commandBuffer1, accessor1, fluidSection1, blockSection1, fluid, fluidId, blockX, y, blockZ); - } - }); + BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, this.blockChunkComponentType); + if (blockChunkComponent != null) { + BlockSection blockSection = blockChunkComponent.getSectionAtIndex(fluidSectionComponent.getY()); + if (blockSection != null) { + if (blockSection.getTickingBlocksCountCopy() != 0) { + FluidTicker.CachedAccessor accessor = FluidTicker.CachedAccessor.of(commandBuffer, fluidSectionComponent, blockSection, 5); + blockSection.forEachTicking(accessor, commandBuffer, fluidSectionComponent.getY(), (accessor1, commandBuffer1, x, y, z, block) -> { + FluidSection fluidSection1 = accessor1.selfFluidSection; + BlockSection blockSection1 = accessor1.selfBlockSection; + int fluidId = fluidSection1.getFluidId(x, y, z); + if (fluidId == 0) { + return BlockTickStrategy.IGNORED; + } else { + int blockX = fluidSection1.getX() << 5 | x; + int blockZ = fluidSection1.getZ() << 5 | z; + Fluid fluid = Fluid.getAssetMap().getAsset(fluidId); + return fluid.getTicker().tick(commandBuffer1, accessor1, fluidSection1, blockSection1, fluid, fluidId, blockX, y, blockZ); + } + }); + } } } } @@ -380,13 +467,13 @@ public class FluidSystems { @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } @Nonnull @Override public Set> getDependencies() { - return DEPENDENCIES; + return this.dependencies; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/BlockMask.java b/src/com/hypixel/hytale/builtin/hytalegenerator/BlockMask.java index ba125386..e360558a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/BlockMask.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/BlockMask.java @@ -8,7 +8,9 @@ import javax.annotation.Nonnull; public class BlockMask { private MaterialSet skippedBlocks = new MaterialSet(); private MaterialSet defaultMask = new MaterialSet(); + @Nonnull private final List sourceBlocks = new ArrayList<>(0); + @Nonnull private final List destinationBlocks = new ArrayList<>(0); public boolean canPlace(@Nonnull Material material) { @@ -19,7 +21,7 @@ public class BlockMask { return !this.skippedBlocks.test(materialHash); } - public boolean canReplace(Material source, Material destination) { + public boolean canReplace(@Nonnull Material source, @Nonnull Material destination) { return this.canReplace(source.hashMaterialIds(), destination.hashMaterialIds()); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/FutureUtils.java b/src/com/hypixel/hytale/builtin/hytalegenerator/FutureUtils.java index 91be0d02..767cdb2b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/FutureUtils.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/FutureUtils.java @@ -5,6 +5,7 @@ import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; public class FutureUtils { + @Nonnull public static CompletableFuture allOf(@Nonnull List> tasks) { return CompletableFuture.allOf(tasks.toArray(new CompletableFuture[tasks.size()])); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/LoggerUtil.java b/src/com/hypixel/hytale/builtin/hytalegenerator/LoggerUtil.java index f9be9a82..1774ab0b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/LoggerUtil.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/LoggerUtil.java @@ -5,6 +5,7 @@ import java.util.logging.Logger; import javax.annotation.Nonnull; public class LoggerUtil { + @Nonnull public static final String HYTALE_GENERATOR_NAME = "HytaleGenerator"; public static Logger getLogger() { @@ -22,4 +23,11 @@ public class LoggerUtil { msg = msg + ExceptionUtil.toStringWithStack(e); logger.severe(msg); } + + @Nonnull + public static String nsToMsDecimal(long ns) { + long ms = ns / 1000000L; + long decimal = (ns - ms * 1000000L) / 1000L; + return ms + "." + decimal; + } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/MaterialSet.java b/src/com/hypixel/hytale/builtin/hytalegenerator/MaterialSet.java index e820d53e..5bee90f2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/MaterialSet.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/MaterialSet.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.ints.IntSets; import java.util.List; import java.util.function.Predicate; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class MaterialSet implements Predicate { private final boolean isInclusive; @@ -46,7 +47,7 @@ public class MaterialSet implements Predicate { } } - public boolean test(Material value) { + public boolean test(@Nullable Material value) { if (value == null) { return false; } else { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/ReusableList.java b/src/com/hypixel/hytale/builtin/hytalegenerator/ReusableList.java index cb1ff6ed..3a1c8346 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/ReusableList.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/ReusableList.java @@ -2,9 +2,11 @@ package com.hypixel.hytale.builtin.hytalegenerator; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ReusableList { + @Nonnull private final List data = new ArrayList<>(0); private int softSize = 0; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/AssetManager.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/AssetManager.java index 1c957445..290e091b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/AssetManager.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/AssetManager.java @@ -88,6 +88,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.density.VectorWarpDensi import com.hypixel.hytale.builtin.hytalegenerator.assets.density.XOverrideDensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.XValueDensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.YOverrideDensityAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.density.YSampledDensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.YValueDensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.ZOverrideDensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.ZValueDensityAsset; @@ -110,6 +111,9 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.density.positions.retur import com.hypixel.hytale.builtin.hytalegenerator.assets.environmentproviders.ConstantEnvironmentProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.environmentproviders.DensityDelimitedEnvironmentProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.environmentproviders.EnvironmentProviderAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.DecimalConstantsFrameworkAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.FrameworkAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.PositionsFrameworkAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.materialproviders.ConstantMaterialProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.materialproviders.DownwardDepthMaterialProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.materialproviders.DownwardSpaceMaterialProviderAsset; @@ -161,9 +165,11 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.pointgenerators.MeshPoi import com.hypixel.hytale.builtin.hytalegenerator.assets.pointgenerators.PointGeneratorAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.AnchorPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.BaseHeightPositionProviderAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.BoundPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.CachedPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.FieldFunctionOccurrencePositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.FieldFunctionPositionProviderAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.FrameworkPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.ImportedPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.ListPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.Mesh2DPositionProviderAsset; @@ -171,7 +177,6 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.Mesh3 import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.OffsetPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.PositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.SimpleHorizontalPositionProviderAsset; -import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.SpherePositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.UnionPositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.propassignments.AssignmentsAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.propassignments.ConstantAssignmentsAsset; @@ -215,8 +220,6 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.vectorproviders.Importe import com.hypixel.hytale.builtin.hytalegenerator.assets.vectorproviders.VectorProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.WorldStructureAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.basic.BasicWorldStructureAsset; -import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.mapcontentfield.BaseHeightContentFieldAsset; -import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.mapcontentfield.ContentFieldAsset; import com.hypixel.hytale.common.util.ExceptionUtil; import com.hypixel.hytale.event.EventRegistry; import com.hypixel.hytale.logger.HytaleLogger; @@ -264,7 +267,7 @@ public class AssetManager { for (BlockMaskAsset value : event.getLoadedAssets().values()) { this.blockMaskAssets.put(value.getId(), value); - this.logger.at(Level.FINE).log("Loaded BlockMask asset " + value.toString()); + this.logger.at(Level.FINE).log("Loaded BlockMask asset " + value); } this.triggerReloadListeners(); @@ -275,7 +278,7 @@ public class AssetManager { for (DensityAsset value : event.getLoadedAssets().values()) { this.densityAssets.put(value.getId(), value); - this.logger.at(Level.FINE).log("Loaded Density asset " + value.toString()); + this.logger.at(Level.FINE).log("Loaded Density asset " + value); } this.triggerReloadListeners(); @@ -462,7 +465,9 @@ public class AssetManager { DensityAsset.CODEC.register("Exported", ExportedDensityAsset.class, ExportedDensityAsset.CODEC); DensityAsset.CODEC.register("Terrain", TerrainDensityAsset.class, TerrainDensityAsset.CODEC); DensityAsset.CODEC.register("DistanceToBiomeEdge", DistanceToBiomeEdgeDensityAsset.class, DistanceToBiomeEdgeDensityAsset.CODEC); - ContentFieldAsset.CODEC.register("BaseHeight", BaseHeightContentFieldAsset.class, BaseHeightContentFieldAsset.CODEC); + DensityAsset.CODEC.register("YSampled", YSampledDensityAsset.class, YSampledDensityAsset.CODEC); + FrameworkAsset.CODEC.register("DecimalConstants", DecimalConstantsFrameworkAsset.class, DecimalConstantsFrameworkAsset.CODEC); + FrameworkAsset.CODEC.register("Positions", PositionsFrameworkAsset.class, PositionsFrameworkAsset.CODEC); TerrainAsset.CODEC.register("DAOTerrain", DensityTerrainAsset.class, DensityTerrainAsset.CODEC); NoiseAsset.CODEC.register("Simplex", SimplexNoiseAsset.class, SimplexNoiseAsset.CODEC); NoiseAsset.CODEC.register("Cell", CellNoiseAsset.class, CellNoiseAsset.CODEC); @@ -505,7 +510,8 @@ public class AssetManager { PositionProviderAsset.CODEC.register("BaseHeight", BaseHeightPositionProviderAsset.class, BaseHeightPositionProviderAsset.CODEC); PositionProviderAsset.CODEC.register("Imported", ImportedPositionProviderAsset.class, ImportedPositionProviderAsset.CODEC); PositionProviderAsset.CODEC.register("Anchor", AnchorPositionProviderAsset.class, AnchorPositionProviderAsset.CODEC); - PositionProviderAsset.CODEC.register("Sphere", SpherePositionProviderAsset.class, SpherePositionProviderAsset.CODEC); + PositionProviderAsset.CODEC.register("Bound", BoundPositionProviderAsset.class, BoundPositionProviderAsset.CODEC); + PositionProviderAsset.CODEC.register("Framework", FrameworkPositionProviderAsset.class, FrameworkPositionProviderAsset.CODEC); PointGeneratorAsset.CODEC.register("Mesh", MeshPointGeneratorAsset.class, MeshPointGeneratorAsset.CODEC); AssignmentsAsset.CODEC.register("FieldFunction", FieldFunctionAssignmentsAsset.class, FieldFunctionAssignmentsAsset.CODEC); AssignmentsAsset.CODEC.register("Sandwich", SandwichAssignmentsAsset.class, SandwichAssignmentsAsset.CODEC); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/SettingsAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/SettingsAsset.java index 637118f5..7d2c46a6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/SettingsAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/SettingsAsset.java @@ -12,6 +12,7 @@ import java.util.List; import javax.annotation.Nonnull; public class SettingsAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( SettingsAsset.class, SettingsAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/biomes/BiomeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/biomes/BiomeAsset.java index 9465a3cd..50ababd0 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/biomes/BiomeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/biomes/BiomeAsset.java @@ -30,6 +30,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProv import com.hypixel.hytale.builtin.hytalegenerator.propdistributions.Assignments; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.builtin.hytalegenerator.tintproviders.TintProvider; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; @@ -38,8 +39,10 @@ import com.hypixel.hytale.codec.validation.ValidatorCache; import javax.annotation.Nonnull; public class BiomeAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull public static final ValidatorCache VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(BiomeAsset::getAssetStore)); private static AssetStore> STORE; + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( BiomeAsset.class, BiomeAsset::new, @@ -94,6 +97,7 @@ public class BiomeAsset implements JsonAssetWithMap> getAssetStore() { if (STORE == null) { STORE = AssetRegistry.getAssetStore(BiomeAsset.class); @@ -122,26 +126,29 @@ public class BiomeAsset implements JsonAssetWithMap materialProvider = this.materialProviderAsset - .build(new MaterialProviderAsset.Argument(parentSeed, materialCache, referenceBundle)); - Density density = this.terrainAsset.buildDensity(parentSeed, referenceBundle); - EnvironmentProvider environments = EnvironmentProvider.noEnvironmentProvider(); + .build(new MaterialProviderAsset.Argument(parentSeed, materialCache, referenceBundle, workerId)); + Density density = this.terrainAsset.buildDensity(parentSeed, referenceBundle, workerId); + EnvironmentProvider provider = EnvironmentProvider.noEnvironmentProvider(); if (this.environmentProviderAsset != null) { - environments = this.environmentProviderAsset.build(new EnvironmentProviderAsset.Argument(parentSeed, materialCache, referenceBundle)); + provider = this.environmentProviderAsset.build(new EnvironmentProviderAsset.Argument(parentSeed, materialCache, referenceBundle, workerId)); } TintProvider tints = TintProvider.noTintProvider(); if (this.tintProviderAsset != null) { - tints = this.tintProviderAsset.build(new TintProviderAsset.Argument(parentSeed, materialCache, referenceBundle)); + tints = this.tintProviderAsset.build(new TintProviderAsset.Argument(parentSeed, materialCache, referenceBundle, workerId)); } - SimpleBiome biome = new SimpleBiome(this.biomeName, density, materialProvider, environments, tints); + SimpleBiome biome = new SimpleBiome(this.biomeName, density, materialProvider, provider, tints); for (PropRuntimeAsset fieldAsset : this.propRuntimeAssets) { if (!fieldAsset.isSkip()) { - PositionProvider positionProvider = fieldAsset.buildPositionProvider(parentSeed, referenceBundle); - Assignments distribution = fieldAsset.buildPropDistribution(parentSeed, materialCache, fieldAsset.getRuntime(), referenceBundle); + PositionProvider positionProvider = fieldAsset.buildPositionProvider(parentSeed, referenceBundle, workerId); + Assignments distribution = fieldAsset.buildPropDistribution(parentSeed, materialCache, fieldAsset.getRuntime(), referenceBundle, workerId); PropField field = new PropField(fieldAsset.getRuntime(), distribution, positionProvider); biome.addPropFieldTo(field); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskAsset.java index 084830ee..3a783ce0 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskAsset.java @@ -18,7 +18,9 @@ import java.util.Map; import javax.annotation.Nonnull; public class BlockMaskAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull private static final Map exportedNodes = new HashMap<>(); + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( BlockMaskAsset.class, BlockMaskAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskEntryAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskEntryAsset.java index f8f4bc04..d9cbef94 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskEntryAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/blockmask/BlockMaskEntryAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.codec.KeyedCodec; import javax.annotation.Nonnull; public class BlockMaskEntryAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( BlockMaskEntryAsset.class, BlockMaskEntryAsset::new, @@ -35,10 +36,12 @@ public class BlockMaskEntryAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( MaterialSetAsset.class, MaterialSetAsset::new, @@ -39,8 +41,9 @@ public class MaterialSetAsset implements JsonAssetWithMap materials = new ArrayList<>(this.materialAssets.length); + List materials = new ObjectArrayList<>(this.materialAssets.length); for (MaterialAsset materialAsset : this.materialAssets) { if (materialAsset != null) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/bounds/DecimalBounds3dAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/bounds/DecimalBounds3dAsset.java new file mode 100644 index 00000000..ff121b6e --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/bounds/DecimalBounds3dAsset.java @@ -0,0 +1,44 @@ +package com.hypixel.hytale.builtin.hytalegenerator.assets.bounds; + +import com.hypixel.hytale.assetstore.AssetExtraInfo; +import com.hypixel.hytale.assetstore.codec.AssetBuilderCodec; +import com.hypixel.hytale.assetstore.map.DefaultAssetMap; +import com.hypixel.hytale.assetstore.map.JsonAssetWithMap; +import com.hypixel.hytale.builtin.hytalegenerator.bounds.Bounds3d; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.math.vector.Vector3d; +import javax.annotation.Nonnull; + +public class DecimalBounds3dAsset implements JsonAssetWithMap> { + @Nonnull + public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( + DecimalBounds3dAsset.class, + DecimalBounds3dAsset::new, + Codec.STRING, + (asset, id) -> asset.id = id, + config -> config.id, + (config, data) -> config.data = data, + config -> config.data + ) + .append(new KeyedCodec<>("PointA", Vector3d.CODEC, true), (t, value) -> t.pointA = value, t -> t.pointA) + .add() + .append(new KeyedCodec<>("PointB", Vector3d.CODEC, true), (t, value) -> t.pointB = value, t -> t.pointB) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + private Vector3d pointA = new Vector3d(); + private Vector3d pointB = new Vector3d(); + + @Nonnull + public Bounds3d build() { + Bounds3d bounds = new Bounds3d(this.pointA, this.pointB); + bounds.correct(); + return bounds; + } + + public String getId() { + return this.id; + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/bounds/IntegerBounds3dAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/bounds/IntegerBounds3dAsset.java new file mode 100644 index 00000000..a18251ee --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/bounds/IntegerBounds3dAsset.java @@ -0,0 +1,44 @@ +package com.hypixel.hytale.builtin.hytalegenerator.assets.bounds; + +import com.hypixel.hytale.assetstore.AssetExtraInfo; +import com.hypixel.hytale.assetstore.codec.AssetBuilderCodec; +import com.hypixel.hytale.assetstore.map.DefaultAssetMap; +import com.hypixel.hytale.assetstore.map.JsonAssetWithMap; +import com.hypixel.hytale.builtin.hytalegenerator.bounds.Bounds3i; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.math.vector.Vector3i; +import javax.annotation.Nonnull; + +public class IntegerBounds3dAsset implements JsonAssetWithMap> { + @Nonnull + public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( + IntegerBounds3dAsset.class, + IntegerBounds3dAsset::new, + Codec.STRING, + (asset, id) -> asset.id = id, + config -> config.id, + (config, data) -> config.data = data, + config -> config.data + ) + .append(new KeyedCodec<>("PointA", Vector3i.CODEC, true), (t, value) -> t.pointA = value, t -> t.pointA) + .add() + .append(new KeyedCodec<>("PointB", Vector3i.CODEC, true), (t, value) -> t.pointB = value, t -> t.pointB) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + private Vector3i pointA = new Vector3i(); + private Vector3i pointB = new Vector3i(); + + @Nonnull + public Bounds3i build() { + Bounds3i bounds = new Bounds3i(this.pointA, this.pointB); + bounds.correct(); + return bounds; + } + + public String getId() { + return this.id; + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CeilingCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CeilingCurveAsset.java index e37d9215..1a6337f1 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CeilingCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CeilingCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class CeilingCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(CeilingCurveAsset.class, CeilingCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curve", CurveAsset.CODEC, true), (t, k) -> t.curveAsset = k, k -> k.curveAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ClampCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ClampCurveAsset.java index 516b5e58..d2ef9c67 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ClampCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ClampCurveAsset.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class ClampCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(ClampCurveAsset.class, ClampCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curve", CurveAsset.CODEC, false), (t, k) -> t.curveAsset = k, k -> k.curveAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ConstantCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ConstantCurveAsset.java index fafeb95b..6e5f08c3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ConstantCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ConstantCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class ConstantCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantCurveAsset.class, ConstantCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CurveAsset.java index c287d03f..5ad424ba 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/CurveAsset.java @@ -17,13 +17,19 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class CurveAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull private static final CurveAsset[] EMPTY_INPUTS = new CurveAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(CurveAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(CurveAsset.class) .append(new KeyedCodec<>("ExportAs", Codec.STRING, false), (t, k) -> t.exportName = k, t -> t.exportName) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceExponentialCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceExponentialCurveAsset.java index d2bf961d..a5787a8d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceExponentialCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceExponentialCurveAsset.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class DistanceExponentialCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DistanceExponentialCurveAsset.class, DistanceExponentialCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceSCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceSCurveAsset.java index 030563c6..db831709 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceSCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/DistanceSCurveAsset.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class DistanceSCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DistanceSCurveAsset.class, DistanceSCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/FloorCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/FloorCurveAsset.java index a5e22c77..2992fa63 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/FloorCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/FloorCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class FloorCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(FloorCurveAsset.class, FloorCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curve", CurveAsset.CODEC, true), (t, k) -> t.curveAsset = k, k -> k.curveAsset) .add() @@ -14,7 +15,7 @@ public class FloorCurveAsset extends CurveAsset { .add() .build(); private CurveAsset curveAsset = new ConstantCurveAsset(); - private double limit = 0.0; + private double limit; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ImportedCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ImportedCurveAsset.java index 2e37c435..ea19f99a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ImportedCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/ImportedCurveAsset.java @@ -5,8 +5,10 @@ import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.logger.HytaleLogger; import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; +import javax.annotation.Nonnull; public class ImportedCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedCurveAsset.class, ImportedCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/InverterCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/InverterCurveAsset.java index 0853e163..4317c476 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/InverterCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/InverterCurveAsset.java @@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class InverterCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( InverterCurveAsset.class, InverterCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MaxCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MaxCurveAsset.java index 0771e4ee..0f272a4b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MaxCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MaxCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class MaxCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(MaxCurveAsset.class, MaxCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curves", new ArrayCodec<>(CurveAsset.CODEC, CurveAsset[]::new), true), (t, k) -> t.curveAssets = k, k -> k.curveAssets) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MinCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MinCurveAsset.java index fb0f1618..15089aa5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MinCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MinCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class MinCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(MinCurveAsset.class, MinCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curves", new ArrayCodec<>(CurveAsset.CODEC, CurveAsset[]::new), true), (t, k) -> t.curveAssets = k, k -> k.curveAssets) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MultiplierCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MultiplierCurveAsset.java index c691c0dd..22c3b2c5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MultiplierCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/MultiplierCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class MultiplierCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( MultiplierCurveAsset.class, MultiplierCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/NotCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/NotCurveAsset.java index 87c94758..4af29b8c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/NotCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/NotCurveAsset.java @@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class NotCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(NotCurveAsset.class, NotCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curve", CurveAsset.CODEC, true), (t, k) -> t.curveAsset = k, k -> k.curveAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothCeilingCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothCeilingCurveAsset.java index 0a2db0b2..81dfe0a3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothCeilingCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothCeilingCurveAsset.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class SmoothCeilingCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothCeilingCurveAsset.class, SmoothCeilingCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothClampCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothClampCurveAsset.java index 8681225c..960e03b9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothClampCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothClampCurveAsset.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class SmoothClampCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothClampCurveAsset.class, SmoothClampCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothFloorCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothFloorCurveAsset.java index f550c72b..58df3e9d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothFloorCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothFloorCurveAsset.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class SmoothFloorCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothFloorCurveAsset.class, SmoothFloorCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMaxCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMaxCurveAsset.java index adc71a68..d6970f63 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMaxCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMaxCurveAsset.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class SmoothMaxCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothMaxCurveAsset.class, SmoothMaxCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMinCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMinCurveAsset.java index 8e7245c0..8f34fd38 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMinCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SmoothMinCurveAsset.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class SmoothMinCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothMinCurveAsset.class, SmoothMinCurveAsset::new, CurveAsset.ABSTRACT_CODEC ) @@ -22,7 +23,7 @@ public class SmoothMinCurveAsset extends CurveAsset { .build(); private CurveAsset curveAAsset = new ConstantCurveAsset(); private CurveAsset curveBAsset = new ConstantCurveAsset(); - private double range = 0.0; + private double range; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SumCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SumCurveAsset.java index c3fd5b1b..c3f47f06 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SumCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/SumCurveAsset.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class SumCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(SumCurveAsset.class, SumCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curves", new ArrayCodec<>(CurveAsset.CODEC, CurveAsset[]::new), true), (t, k) -> t.curveAssets = k, k -> k.curveAssets) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/NodeFunctionYOutAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/NodeFunctionYOutAsset.java index 6855ca23..5f793f87 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/NodeFunctionYOutAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/NodeFunctionYOutAsset.java @@ -15,6 +15,7 @@ import java.util.HashSet; import javax.annotation.Nonnull; public class NodeFunctionYOutAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( NodeFunctionYOutAsset.class, NodeFunctionYOutAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/PointYOutAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/PointYOutAsset.java index ad53d432..598376b8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/PointYOutAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/legacy/PointYOutAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector2d; import javax.annotation.Nonnull; public class PointYOutAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( PointYOutAsset.class, PointYOutAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/ManualCurveAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/ManualCurveAsset.java index 80c003ca..1746e803 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/ManualCurveAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/ManualCurveAsset.java @@ -12,6 +12,7 @@ import java.util.HashSet; import javax.annotation.Nonnull; public class ManualCurveAsset extends CurveAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(ManualCurveAsset.class, ManualCurveAsset::new, CurveAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Points", new ArrayCodec<>(PointInOutAsset.CODEC, PointInOutAsset[]::new), true), (t, k) -> t.nodes = k, t -> t.nodes) .addValidator((LegacyValidator)((v, r) -> { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/PointInOutAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/PointInOutAsset.java index 590c7653..6c8f710b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/PointInOutAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/curves/manual/PointInOutAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector2d; import javax.annotation.Nonnull; public class PointInOutAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( PointInOutAsset.class, PointInOutAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeDoubleAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeDoubleAsset.java index 94068493..44306c9a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeDoubleAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeDoubleAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.KeyedCodec; import javax.annotation.Nonnull; public class RangeDoubleAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( RangeDoubleAsset.class, RangeDoubleAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeIntAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeIntAsset.java index 0c84417e..b22c6b08 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeIntAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/delimiters/RangeIntAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.KeyedCodec; import javax.annotation.Nonnull; public class RangeIntAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( RangeIntAsset.class, RangeIntAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AbsDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AbsDensityAsset.java index 7c2e4856..f5845234 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AbsDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AbsDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class AbsDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(AbsDensityAsset.class, AbsDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .build(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeConstantAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeConstantAsset.java index 478878dc..329bc2f9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeConstantAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeConstantAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class AmplitudeConstantAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AmplitudeConstantAsset.class, AmplitudeConstantAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeDensityAsset.java index 4c488134..b5ef4d11 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AmplitudeDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class AmplitudeDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AmplitudeDensityAsset.class, AmplitudeDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AnchorDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AnchorDensityAsset.java index cdd51a33..78fb9592 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AnchorDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AnchorDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class AnchorDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AnchorDensityAsset.class, AnchorDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AngleDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AngleDensityAsset.java index 4346a227..a57ad559 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AngleDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AngleDensityAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class AngleDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AngleDensityAsset.class, AngleDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -29,7 +30,7 @@ public class AngleDensityAsset extends DensityAsset { .build(); private VectorProviderAsset vectorProviderAsset = new ConstantVectorProviderAsset(); private Vector3d vector = new Vector3d(); - private boolean isAxis = false; + private boolean isAxis; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AxisDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AxisDensityAsset.java index 64badebe..2783ca2f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AxisDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/AxisDensityAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class AxisDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(AxisDensityAsset.class, AxisDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curve", CurveAsset.CODEC, true), (t, k) -> t.distanceCurveAsset = k, k -> k.distanceCurveAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/BaseHeightDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/BaseHeightDensityAsset.java index 43fe0076..3e9770fe 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/BaseHeightDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/BaseHeightDensityAsset.java @@ -1,17 +1,16 @@ package com.hypixel.hytale.builtin.hytalegenerator.assets.density; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.DecimalConstantsFrameworkAsset; import com.hypixel.hytale.builtin.hytalegenerator.density.Density; import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.BaseHeightDensity; import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.ConstantValueDensity; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; -import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.BaseHeightReference; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; -import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class BaseHeightDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( BaseHeightDensityAsset.class, BaseHeightDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -29,16 +28,12 @@ public class BaseHeightDensityAsset extends DensityAsset { if (this.isSkipped()) { return new ConstantValueDensity(0.0); } else { - BaseHeightReference heightDataLayer = argument.referenceBundle.getLayerWithName(this.baseHeightName, BaseHeightReference.class); - if (heightDataLayer == null) { - HytaleLogger.getLogger() - .atConfig() - .log("Couldn't find height data layer with name \"" + this.baseHeightName + "\", using a zero-constant Density node."); - return new ConstantValueDensity(0.0); - } else { - BiDouble2DoubleFunction yFunction = heightDataLayer.getHeightFunction(); - return new BaseHeightDensity(yFunction, this.isDistance); + Double baseHeight = DecimalConstantsFrameworkAsset.Entries.get(this.baseHeightName, argument.referenceBundle); + if (baseHeight == null) { + baseHeight = 0.0; } + + return new BaseHeightDensity(baseHeight, this.isDistance); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/Cache2dDensityAsset_Deprecated.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/Cache2dDensityAsset_Deprecated.java index fa2cf7ce..c239853f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/Cache2dDensityAsset_Deprecated.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/Cache2dDensityAsset_Deprecated.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Cache2dDensityAsset_Deprecated extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Cache2dDensityAsset_Deprecated.class, Cache2dDensityAsset_Deprecated::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CacheDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CacheDensityAsset.java index b09d62b5..5cda38b3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CacheDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CacheDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class CacheDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CacheDensityAsset.class, CacheDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CeilingDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CeilingDensityAsset.java index 38a19189..0edce5e3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CeilingDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CeilingDensityAsset.java @@ -9,13 +9,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class CeilingDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CeilingDensityAsset.class, CeilingDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Limit", Codec.DOUBLE, true), (t, k) -> t.limit = k, k -> k.limit) .add() .build(); - private double limit = 0.0; + private double limit; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise2DDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise2DDensityAsset.java index d930188a..d464de50 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise2DDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise2DDensityAsset.java @@ -18,6 +18,7 @@ import javax.annotation.Nonnull; public class CellNoise2DDensityAsset extends DensityAsset { private static Set validCellTypes = new HashSet<>(); + @Nonnull public static final BuilderCodec CODEC; private double scaleX = 1.0; private double scaleZ = 1.0; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise3DDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise3DDensityAsset.java index 76c84793..e04d0825 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise3DDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellNoise3DDensityAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class CellNoise3DDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CellNoise3DDensityAsset.class, CellNoise3DDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -43,6 +44,7 @@ public class CellNoise3DDensityAsset extends DensityAsset { private double jitter = 0.5; private int octaves = 1; private String seedKey = "A"; + @Nonnull private FastNoiseLite.CellularReturnType cellType = FastNoiseLite.CellularReturnType.CellValue; @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellWallDistanceDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellWallDistanceDensityAsset.java index 952ed0c2..0ae24f13 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellWallDistanceDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CellWallDistanceDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class CellWallDistanceDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CellWallDistanceDensityAsset.class, CellWallDistanceDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ClampDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ClampDensityAsset.java index 059fa0f8..e199d12f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ClampDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ClampDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ClampDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ClampDensityAsset.class, ClampDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -17,8 +18,8 @@ public class ClampDensityAsset extends DensityAsset { .append(new KeyedCodec<>("WallB", Codec.DOUBLE, true), (t, k) -> t.wallB = k, k -> k.wallB) .add() .build(); - private double wallA = 0.0; - private double wallB = 0.0; + private double wallA; + private double wallB; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ConstantDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ConstantDensityAsset.java index a17ef09a..9a3022f5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ConstantDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ConstantDensityAsset.java @@ -8,13 +8,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ConstantDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantDensityAsset.class, ConstantDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Value", Codec.DOUBLE, true), (t, k) -> t.value = k, k -> k.value) .add() .build(); - private double value = 0.0; + private double value; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CubeDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CubeDensityAsset.java index 04b9ee17..1b952b48 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CubeDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CubeDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class CubeDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(CubeDensityAsset.class, CubeDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Curve", CurveAsset.CODEC, false), (t, k) -> t.densityCurveAsset = k, k -> k.densityCurveAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CuboidDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CuboidDensityAsset.java index bdd54f89..d190a8ea 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CuboidDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CuboidDensityAsset.java @@ -15,6 +15,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class CuboidDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CuboidDensityAsset.class, CuboidDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -40,7 +41,7 @@ public class CuboidDensityAsset extends DensityAsset { private Vector3d scaleVector = new Vector3d(1.0, 1.0, 1.0); @Nonnull private Vector3d newYAxis = new Vector3d(0.0, 1.0, 0.0); - private double spinAngle = 0.0; + private double spinAngle; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CurveMapperDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CurveMapperDensityAsset.java index e07e33a9..c36cb548 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CurveMapperDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CurveMapperDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class CurveMapperDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CurveMapperDensityAsset.class, CurveMapperDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CylinderDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CylinderDensityAsset.java index 0efa8142..c1f6c731 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CylinderDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/CylinderDensityAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class CylinderDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CylinderDensityAsset.class, CylinderDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -33,7 +34,7 @@ public class CylinderDensityAsset extends DensityAsset { private CurveAsset axialCurveAsset = new ConstantCurveAsset(); @Nonnull private Vector3d newYAxis = new Vector3d(0.0, 1.0, 0.0); - private double spinAngle = 0.0; + private double spinAngle; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DensityAsset.java index 06d08275..c1f611d4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DensityAsset.java @@ -19,6 +19,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.WorldSt import com.hypixel.hytale.builtin.hytalegenerator.density.Density; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -31,13 +32,19 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public abstract class DensityAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull private static final DensityAsset[] EMPTY_INPUTS = new DensityAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(DensityAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(DensityAsset.class) .append(new KeyedCodec<>("Inputs", new ArrayCodec<>(CODEC, DensityAsset[]::new), true), (t, k) -> t.inputs = k, t -> t.inputs) .add() @@ -162,61 +169,64 @@ public abstract class DensityAsset implements JsonAssetWithMap threadInstances; + public Map threadInstances; public Exported(boolean i, @Nonnull DensityAsset asset) { this.isSingleInstance = i; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceDensityAsset.java index 2c020856..cbe9efa4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class DistanceDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DistanceDensityAsset.class, DistanceDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceToBiomeEdgeDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceToBiomeEdgeDensityAsset.java index 5a457aef..6be5ab58 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceToBiomeEdgeDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/DistanceToBiomeEdgeDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class DistanceToBiomeEdgeDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DistanceToBiomeEdgeDensityAsset.class, DistanceToBiomeEdgeDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/EllipsoidDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/EllipsoidDensityAsset.java index 5a801edc..6afeb005 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/EllipsoidDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/EllipsoidDensityAsset.java @@ -15,6 +15,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class EllipsoidDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( EllipsoidDensityAsset.class, EllipsoidDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ExportedDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ExportedDensityAsset.java index 2bbcf462..dea6b8e0 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ExportedDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ExportedDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ExportedDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ExportedDensityAsset.class, ExportedDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -27,11 +28,10 @@ public class ExportedDensityAsset extends DensityAsset { .severe("Couldn't find Density asset exported with name: '" + this.exportName + "'. This could indicate a defect in the HytaleGenerator assets."); return this.firstInput().build(argument); } else if (exported.isSingleInstance) { - Thread thread = Thread.currentThread(); - Density builtInstance = exported.threadInstances.get(thread); + Density builtInstance = exported.threadInstances.get(argument.workerId); if (builtInstance == null) { builtInstance = this.firstInput().build(argument); - exported.threadInstances.put(thread, builtInstance); + exported.threadInstances.put(argument.workerId, builtInstance); } return builtInstance; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FastGradientWarpDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FastGradientWarpDensityAsset.java index c3099701..52c3fa19 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FastGradientWarpDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FastGradientWarpDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class FastGradientWarpDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FastGradientWarpDensityAsset.class, FastGradientWarpDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FloorDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FloorDensityAsset.java index 26b6b43f..3bc0b12a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FloorDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/FloorDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class FloorDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FloorDensityAsset.class, FloorDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientDensityAsset.java index 60241359..b5c2b666 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientDensityAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class GradientDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( GradientDensityAsset.class, GradientDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientWarpDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientWarpDensityAsset.java index b4710d76..52ae89a9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientWarpDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/GradientWarpDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class GradientWarpDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( GradientWarpDensityAsset.class, GradientWarpDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -25,8 +26,8 @@ public class GradientWarpDensityAsset extends DensityAsset { .build(); private double sampleRange = 1.0; private double warpFactor = 1.0; - private boolean is2d = false; - private double y2d = 0.0; + private boolean is2d; + private double y2d; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ImportedDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ImportedDensityAsset.java index 4e8ab463..f14a62b1 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ImportedDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ImportedDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ImportedDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedDensityAsset.class, ImportedDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -28,11 +29,10 @@ public class ImportedDensityAsset extends DensityAsset { LoggerUtil.getLogger().warning("Couldn't find Density asset exported with name: '" + this.importedNodeName + "'. Using empty Node instead."); return new ConstantValueDensity(0.0); } else if (exported.isSingleInstance) { - Thread thread = Thread.currentThread(); - Density builtInstance = exported.threadInstances.get(thread); + Density builtInstance = exported.threadInstances.get(argument.workerId); if (builtInstance == null) { builtInstance = exported.asset.build(argument); - exported.threadInstances.put(thread, builtInstance); + exported.threadInstances.put(argument.workerId, builtInstance); } return builtInstance; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/InverterDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/InverterDensityAsset.java index da48a5ff..7eef05b2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/InverterDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/InverterDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class InverterDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( InverterDensityAsset.class, InverterDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MaxDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MaxDensityAsset.java index ef39eefb..c47a30a9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MaxDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MaxDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class MaxDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(MaxDensityAsset.class, MaxDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .build(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MinDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MinDensityAsset.java index 63d07145..33109b1b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MinDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MinDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class MinDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(MinDensityAsset.class, MinDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .build(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MixDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MixDensityAsset.java index 24505679..58918c58 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MixDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MixDensityAsset.java @@ -8,6 +8,7 @@ import java.util.List; import javax.annotation.Nonnull; public class MixDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(MixDensityAsset.class, MixDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .build(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiMixDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiMixDensityAsset.java index 9ed96159..3e89d36e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiMixDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiMixDensityAsset.java @@ -17,6 +17,7 @@ import java.util.List; import javax.annotation.Nonnull; public class MultiMixDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( MultiMixDensityAsset.class, MultiMixDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -108,6 +109,7 @@ public class MultiMixDensityAsset extends DensityAsset { public static class KeyAsset implements JsonAssetWithMap> { public static final int NO_DENSITY_INDEX = 0; + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( MultiMixDensityAsset.KeyAsset.class, MultiMixDensityAsset.KeyAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiplierDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiplierDensityAsset.java index 543b7c5c..7c8a09a4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiplierDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/MultiplierDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class MultiplierDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( MultiplierDensityAsset.class, MultiplierDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/NormalizerDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/NormalizerDensityAsset.java index 86692c81..bfc1bc33 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/NormalizerDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/NormalizerDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class NormalizerDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( NormalizerDensityAsset.class, NormalizerDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -21,9 +22,9 @@ public class NormalizerDensityAsset extends DensityAsset { .append(new KeyedCodec<>("ToMax", Codec.DOUBLE, true), (t, k) -> t.toMax = k, k -> k.toMax) .add() .build(); - private double fromMin = 0.0; + private double fromMin; private double fromMax = 1.0; - private double toMin = 0.0; + private double toMin; private double toMax = 1.0; @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetConstantAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetConstantAsset.java index ba708991..5763e4aa 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetConstantAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetConstantAsset.java @@ -9,13 +9,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class OffsetConstantAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( OffsetConstantAsset.class, OffsetConstantAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Value", Codec.DOUBLE, true), (t, k) -> t.value = k, t -> t.value) .add() .build(); - private double value = 0.0; + private double value; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetDensityAsset.java index df72d7b7..41b497a4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/OffsetDensityAsset.java @@ -9,12 +9,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class OffsetDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( OffsetDensityAsset.class, OffsetDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("FunctionForY", NodeFunctionYOutAsset.CODEC, true), (t, k) -> t.nodeFunctionYOutAsset = k, k -> k.nodeFunctionYOutAsset) .add() .build(); + @Nonnull private NodeFunctionYOutAsset nodeFunctionYOutAsset = new NodeFunctionYOutAsset(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PipelineDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PipelineDensityAsset.java index 854894cd..19e010ad 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PipelineDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PipelineDensityAsset.java @@ -8,7 +8,9 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public class PipelineDensityAsset extends DensityAsset { + @Nonnull private static final DensityAsset[] EMPTY_INPUTS = new DensityAsset[0]; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PipelineDensityAsset.class, PipelineDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PlaneDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PlaneDensityAsset.java index 82f4336d..4b969f15 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PlaneDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PlaneDensityAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class PlaneDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PlaneDensityAsset.class, PlaneDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -30,7 +31,7 @@ public class PlaneDensityAsset extends DensityAsset { .build(); private CurveAsset distanceCurveAsset = new ConstantCurveAsset(); private Vector3d planeNormal = new Vector3d(0.0, 1.0, 0.0); - private boolean isAnchored = false; + private boolean isAnchored; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsPinchDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsPinchDensityAsset.java index 521b0a57..affc699f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsPinchDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsPinchDensityAsset.java @@ -15,6 +15,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class PositionsPinchDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PositionsPinchDensityAsset.class, PositionsPinchDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -38,10 +39,10 @@ public class PositionsPinchDensityAsset extends DensityAsset { .build(); private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); private CurveAsset pinchCurveAsset = new ConstantCurveAsset(); - private double maxDistance = 0.0; - private boolean normalizeDistance = false; - private boolean isHorizontal = false; - private double positionsMinY = 0.0; + private double maxDistance; + private boolean normalizeDistance; + private boolean isHorizontal; + private double positionsMinY; private double positionsMaxY = 1.0E-6; @Nonnull @@ -53,7 +54,7 @@ public class PositionsPinchDensityAsset extends DensityAsset { return (Density)(this.isHorizontal ? new PositionsHorizontalPinchDensity( this.buildFirstInput(argument), - this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle)), + this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle, argument.workerId)), this.pinchCurveAsset.build(), this.maxDistance, this.normalizeDistance, @@ -62,7 +63,7 @@ public class PositionsPinchDensityAsset extends DensityAsset { ) : new PositionsPinchDensity( this.buildFirstInput(argument), - this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle)), + this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle, argument.workerId)), this.pinchCurveAsset.build(), this.maxDistance, this.normalizeDistance diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsTwistDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsTwistDensityAsset.java index f71ae530..55930075 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsTwistDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PositionsTwistDensityAsset.java @@ -15,6 +15,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class PositionsTwistDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PositionsTwistDensityAsset.class, PositionsTwistDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -37,9 +38,9 @@ public class PositionsTwistDensityAsset extends DensityAsset { private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); private CurveAsset pinchCurveAsset = new ConstantCurveAsset(); private Vector3d twistAxis = new Vector3d(); - private double maxDistance = 0.0; - private boolean normalizeDistance = false; - private boolean zeroPositionsY = false; + private double maxDistance; + private boolean normalizeDistance; + private boolean zeroPositionsY; @Nonnull @Override @@ -48,7 +49,7 @@ public class PositionsTwistDensityAsset extends DensityAsset { ? new ConstantValueDensity(0.0) : new PositionsTwistDensity( this.buildFirstInput(argument), - this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle)), + this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle, argument.workerId)), this.pinchCurveAsset.build(), this.twistAxis, this.maxDistance, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PowDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PowDensityAsset.java index d15a6aa4..94dddf63 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PowDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/PowDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class PowDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(PowDensityAsset.class, PowDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Exponent", Codec.DOUBLE, true), (t, k) -> t.exponent = k, t -> t.exponent) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/RotatorDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/RotatorDensityAsset.java index 62f0cb68..64e6c303 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/RotatorDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/RotatorDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class RotatorDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( RotatorDensityAsset.class, RotatorDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -19,7 +20,7 @@ public class RotatorDensityAsset extends DensityAsset { .add() .build(); private Vector3d newYAxis = new Vector3d(); - private double spinAngle = 0.0; + private double spinAngle; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ScaleDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ScaleDensityAsset.java index 0aa2be63..25e976cb 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ScaleDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ScaleDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ScaleDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ScaleDensityAsset.class, ScaleDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SelectorDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SelectorDensityAsset.java index f22e282b..78a6cd9f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SelectorDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SelectorDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SelectorDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SelectorDensityAsset.class, SelectorDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ShellDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ShellDensityAsset.java index b95bb98e..21ca23d8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ShellDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ShellDensityAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class ShellDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ShellDensityAsset.class, ShellDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -25,7 +26,7 @@ public class ShellDensityAsset extends DensityAsset { .add() .build(); private Vector3d axis = new Vector3d(0.0, 0.0, 0.0); - private boolean isMirrored = false; + private boolean isMirrored; private CurveAsset angleCurveAsset = new ConstantCurveAsset(); private CurveAsset distanceCurveAsset = new ConstantCurveAsset(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise2dDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise2dDensityAsset.java index 49cf25d3..51a2b8c3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise2dDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise2dDensityAsset.java @@ -14,6 +14,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SimplexNoise2dDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SimplexNoise2dDensityAsset.class, SimplexNoise2dDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise3DDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise3DDensityAsset.java index 6bd42354..1b43251b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise3DDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SimplexNoise3DDensityAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SimplexNoise3DDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SimplexNoise3DDensityAsset.class, SimplexNoise3DDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SliderDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SliderDensityAsset.java index 0af5a8f2..2f93617d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SliderDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SliderDensityAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class SliderDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SliderDensityAsset.class, SliderDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothCeilingDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothCeilingDensityAsset.java index df625a6b..a34a62a4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothCeilingDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothCeilingDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SmoothCeilingDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothCeilingDensityAsset.class, SmoothCeilingDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -20,7 +21,7 @@ public class SmoothCeilingDensityAsset extends DensityAsset { .add() .build(); private double smoothRange = 1.0; - private double limit = 0.0; + private double limit; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothClampDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothClampDensityAsset.java index 29cfec0b..1b04d6dd 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothClampDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothClampDensityAsset.java @@ -11,6 +11,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SmoothClampDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothClampDensityAsset.class, SmoothClampDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothFloorDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothFloorDensityAsset.java index 0e5a82e4..3d15459a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothFloorDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothFloorDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SmoothFloorDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothFloorDensityAsset.class, SmoothFloorDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -20,7 +21,7 @@ public class SmoothFloorDensityAsset extends DensityAsset { .add() .build(); private double smoothRange = 1.0; - private double limit = 0.0; + private double limit; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMaxDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMaxDensityAsset.java index 3e9d78a7..0170e7db 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMaxDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMaxDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SmoothMaxDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothMaxDensityAsset.class, SmoothMaxDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMinDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMinDensityAsset.java index 4e27fcff..28f69833 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMinDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SmoothMinDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SmoothMinDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmoothMinDensityAsset.class, SmoothMinDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SqrtDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SqrtDensityAsset.java index 97b4c950..9227565b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SqrtDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SqrtDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class SqrtDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(SqrtDensityAsset.class, SqrtDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .build(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SumDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SumDensityAsset.java index 1051b8fb..4371df54 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SumDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SumDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class SumDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(SumDensityAsset.class, SumDensityAsset::new, DensityAsset.ABSTRACT_CODEC) .build(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchDensityAsset.java index 9eebbfb0..a12803f9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchDensityAsset.java @@ -17,6 +17,7 @@ import java.util.Objects; import javax.annotation.Nonnull; public class SwitchDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SwitchDensityAsset.class, SwitchDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -27,7 +28,9 @@ public class SwitchDensityAsset extends DensityAsset { ) .add() .build(); + @Nonnull public static final String DEFAULT_STATE = "Default"; + @Nonnull public static final int DEFAULT_STATE_HASH = 0; private SwitchDensityAsset.SwitchCaseAsset[] switchCaseAssets = new SwitchDensityAsset.SwitchCaseAsset[0]; @@ -68,6 +71,7 @@ public class SwitchDensityAsset extends DensityAsset { } public static class SwitchCaseAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( SwitchDensityAsset.SwitchCaseAsset.class, SwitchDensityAsset.SwitchCaseAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchStateDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchStateDensityAsset.java index 2c2d3ccd..c31c479c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchStateDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/SwitchStateDensityAsset.java @@ -10,6 +10,7 @@ import java.util.Objects; import javax.annotation.Nonnull; public class SwitchStateDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SwitchStateDensityAsset.class, SwitchStateDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/TerrainDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/TerrainDensityAsset.java index 5dc50ec9..18fdfca5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/TerrainDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/TerrainDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class TerrainDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( TerrainDensityAsset.class, TerrainDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/VectorWarpDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/VectorWarpDensityAsset.java index 7b23d639..9d01d1e7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/VectorWarpDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/VectorWarpDensityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class VectorWarpDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( VectorWarpDensityAsset.class, VectorWarpDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XOverrideDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XOverrideDensityAsset.java index add1fdd4..962dacf6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XOverrideDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XOverrideDensityAsset.java @@ -9,13 +9,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class XOverrideDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( XOverrideDensityAsset.class, XOverrideDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Value", Codec.DOUBLE, true), (t, k) -> t.value = k, t -> t.value) .add() .build(); - private double value = 0.0; + private double value; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XValueDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XValueDensityAsset.java index c1cb50a5..e2eabdda 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XValueDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/XValueDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class XValueDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( XValueDensityAsset.class, XValueDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YOverrideDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YOverrideDensityAsset.java index e7085a6d..c728ac8a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YOverrideDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YOverrideDensityAsset.java @@ -9,13 +9,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class YOverrideDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( YOverrideDensityAsset.class, YOverrideDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Value", Codec.DOUBLE, true), (t, k) -> t.value = k, t -> t.value) .add() .build(); - private double value = 0.0; + private double value; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YSampledDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YSampledDensityAsset.java new file mode 100644 index 00000000..90a3ac08 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YSampledDensityAsset.java @@ -0,0 +1,38 @@ +package com.hypixel.hytale.builtin.hytalegenerator.assets.density; + +import com.hypixel.hytale.builtin.hytalegenerator.density.Density; +import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.ConstantValueDensity; +import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.YSampledDensity; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.codec.validation.Validators; +import javax.annotation.Nonnull; + +public class YSampledDensityAsset extends DensityAsset { + @Nonnull + public static final BuilderCodec CODEC = BuilderCodec.builder( + YSampledDensityAsset.class, YSampledDensityAsset::new, DensityAsset.ABSTRACT_CODEC + ) + .append(new KeyedCodec<>("SampleDistance", Codec.DOUBLE, true), (asset, value) -> asset.sampleDistance = value, asset -> asset.sampleDistance) + .addValidator(Validators.greaterThan(0.0)) + .add() + .append(new KeyedCodec<>("SampleOffset", Codec.DOUBLE, true), (asset, value) -> asset.sampleOffset = value, asset -> asset.sampleOffset) + .add() + .build(); + private double sampleDistance = 4.0; + private double sampleOffset = 0.0; + + @Nonnull + @Override + public Density build(@Nonnull DensityAsset.Argument argument) { + return (Density)(this.sampleDistance <= 0.0 + ? new ConstantValueDensity(0.0) + : new YSampledDensity(this.buildFirstInput(argument), this.sampleDistance, this.sampleOffset)); + } + + @Override + public void cleanUp() { + this.cleanUpInputs(); + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YValueDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YValueDensityAsset.java index 323bbd33..7f02309e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YValueDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/YValueDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class YValueDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( YValueDensityAsset.class, YValueDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZOverrideDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZOverrideDensityAsset.java index dfb93d02..fb41b64e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZOverrideDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZOverrideDensityAsset.java @@ -9,13 +9,14 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ZOverrideDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ZOverrideDensityAsset.class, ZOverrideDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Value", Codec.DOUBLE, true), (t, k) -> t.value = k, t -> t.value) .add() .build(); - private double value = 0.0; + private double value; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZValueDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZValueDensityAsset.java index 8eafd57b..e301218f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZValueDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/ZValueDensityAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ZValueDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ZValueDensityAsset.class, ZValueDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/Positions3DDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/Positions3DDensityAsset.java index 323abe92..77d995dc 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/Positions3DDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/Positions3DDensityAsset.java @@ -19,6 +19,7 @@ import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class Positions3DDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Positions3DDensityAsset.class, Positions3DDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -42,7 +43,8 @@ public class Positions3DDensityAsset extends DensityAsset { if (this.isSkipped()) { return new ConstantValueDensity(0.0); } else { - PositionProvider positionsField = this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle)); + PositionProvider positionsField = this.positionProviderAsset + .build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle, argument.workerId)); Double2DoubleFunction curve = this.curveAsset.build(); CurveReturnType returnType = new CurveReturnType(curve); return new PositionsDensity(positionsField, returnType, new EuclideanDistanceFunction(), this.maxDistance); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/PositionsCellNoiseDensityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/PositionsCellNoiseDensityAsset.java index be3b0eb8..27a657c1 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/PositionsCellNoiseDensityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/PositionsCellNoiseDensityAsset.java @@ -20,6 +20,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class PositionsCellNoiseDensityAsset extends DensityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PositionsCellNoiseDensityAsset.class, PositionsCellNoiseDensityAsset::new, DensityAsset.ABSTRACT_CODEC ) @@ -50,8 +51,9 @@ public class PositionsCellNoiseDensityAsset extends DensityAsset { if (this.isSkipped()) { return new ConstantValueDensity(0.0); } else { - PositionProvider positionsField = this.positionProviderAsset.build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle)); - ReturnType returnType = this.returnTypeAsset.build(argument.parentSeed, argument.referenceBundle); + PositionProvider positionsField = this.positionProviderAsset + .build(new PositionProviderAsset.Argument(argument.parentSeed, argument.referenceBundle, argument.workerId)); + ReturnType returnType = this.returnTypeAsset.build(argument.parentSeed, argument.referenceBundle, argument.workerId); returnType.setMaxDistance(this.maxDistance); DistanceFunction distanceFunction = this.distanceFunctionAsset.build(argument.parentSeed, this.maxDistance); return new PositionsDensity(positionsField, returnType, distanceFunction, this.maxDistance); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/DistanceFunctionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/DistanceFunctionAsset.java index cc073608..f17d8cc1 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/DistanceFunctionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/DistanceFunctionAsset.java @@ -13,11 +13,15 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public abstract class DistanceFunctionAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(DistanceFunctionAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(DistanceFunctionAsset.class).build(); private String id; private AssetExtraInfo.Data data; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/EuclideanDistanceFunctionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/EuclideanDistanceFunctionAsset.java index 739f287d..e41e59de 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/EuclideanDistanceFunctionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/EuclideanDistanceFunctionAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class EuclideanDistanceFunctionAsset extends DistanceFunctionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( EuclideanDistanceFunctionAsset.class, EuclideanDistanceFunctionAsset::new, DistanceFunctionAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/ManhattanDistanceFunctionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/ManhattanDistanceFunctionAsset.java index 05e44722..81d77357 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/ManhattanDistanceFunctionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/distancefunctions/ManhattanDistanceFunctionAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ManhattanDistanceFunctionAsset extends DistanceFunctionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ManhattanDistanceFunctionAsset.class, ManhattanDistanceFunctionAsset::new, DistanceFunctionAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CellValueReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CellValueReturnTypeAsset.java index 998ce847..4b5318df 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CellValueReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CellValueReturnTypeAsset.java @@ -9,12 +9,14 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class CellValueReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CellValueReturnTypeAsset.class, CellValueReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -24,12 +26,12 @@ public class CellValueReturnTypeAsset extends ReturnTypeAsset { .add() .build(); private DensityAsset densityAsset = new ConstantDensityAsset(); - private double defaultValue = 0.0; + private double defaultValue; @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { - Density densityNode = this.densityAsset.build(new DensityAsset.Argument(parentSeed, referenceBundle)); + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { + Density densityNode = this.densityAsset.build(new DensityAsset.Argument(parentSeed, referenceBundle, workerId)); Density cache = new MultiCacheDensity(densityNode, CacheDensityAsset.DEFAULT_CAPACITY); return new CellValueReturnType(cache, this.defaultValue); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CurveReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CurveReturnTypeAsset.java index fbc08552..36e13631 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CurveReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/CurveReturnTypeAsset.java @@ -6,12 +6,14 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import it.unimi.dsi.fastutil.doubles.Double2DoubleFunction; import javax.annotation.Nonnull; public class CurveReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CurveReturnTypeAsset.class, CurveReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -22,7 +24,7 @@ public class CurveReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { Double2DoubleFunction curve = this.curveAsset.build(); return new CurveReturnType(curve); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DensityReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DensityReturnTypeAsset.java index c0103f9b..528c4569 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DensityReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DensityReturnTypeAsset.java @@ -14,6 +14,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -23,6 +24,7 @@ import java.util.HashMap; import javax.annotation.Nonnull; public class DensityReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DensityReturnTypeAsset.class, DensityReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -43,8 +45,8 @@ public class DensityReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { - DensityAsset.Argument densityArgument = new DensityAsset.Argument(parentSeed, referenceBundle); + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { + DensityAsset.Argument densityArgument = new DensityAsset.Argument(parentSeed, referenceBundle, workerId); Density choiceDensity = this.choiceDensityAsset.build(densityArgument); HashMap delimiterMap = new HashMap<>(this.delimiterAssets.length); @@ -57,6 +59,7 @@ public class DensityReturnTypeAsset extends ReturnTypeAsset { } public static class DelimiterAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( DensityReturnTypeAsset.DelimiterAsset.class, DensityReturnTypeAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2AddReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2AddReturnTypeAsset.java index adc1718f..857d568a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2AddReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2AddReturnTypeAsset.java @@ -4,10 +4,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Distance2AddReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Distance2AddReturnTypeAsset.class, Distance2AddReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -15,7 +17,7 @@ public class Distance2AddReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { return new Distance2AddReturnType(); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2DivReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2DivReturnTypeAsset.java index 02311da2..1dfcc740 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2DivReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2DivReturnTypeAsset.java @@ -4,10 +4,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Distance2DivReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Distance2DivReturnTypeAsset.class, Distance2DivReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -15,7 +17,7 @@ public class Distance2DivReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { return new Distance2DivReturnType(); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2MulReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2MulReturnTypeAsset.java index 6f6faa3e..57521d0b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2MulReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2MulReturnTypeAsset.java @@ -4,10 +4,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Distance2MulReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Distance2MulReturnTypeAsset.class, Distance2MulReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -15,7 +17,7 @@ public class Distance2MulReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { return new Distance2MulReturnType(); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2ReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2ReturnTypeAsset.java index 38d208db..7c150f35 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2ReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2ReturnTypeAsset.java @@ -4,10 +4,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Distance2ReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Distance2ReturnTypeAsset.class, Distance2ReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -15,7 +17,7 @@ public class Distance2ReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { return new Distance2ReturnType(); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2SubReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2SubReturnTypeAsset.java index 6406b9af..aae8a51c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2SubReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/Distance2SubReturnTypeAsset.java @@ -4,10 +4,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Distance2SubReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Distance2SubReturnTypeAsset.class, Distance2SubReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -15,7 +17,7 @@ public class Distance2SubReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { return new Distance2SubReturnType(); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DistanceReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DistanceReturnTypeAsset.java index d0e610a8..c0131633 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DistanceReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/DistanceReturnTypeAsset.java @@ -4,10 +4,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.return import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class DistanceReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DistanceReturnTypeAsset.class, DistanceReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -15,7 +17,7 @@ public class DistanceReturnTypeAsset extends ReturnTypeAsset { @Nonnull @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { return new DistanceReturnType(); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ImportedReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ImportedReturnTypeAsset.java index a8db9be3..078baf7d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ImportedReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ImportedReturnTypeAsset.java @@ -4,6 +4,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.density.Density; import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -13,6 +14,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ImportedReturnTypeAsset extends ReturnTypeAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedReturnTypeAsset.class, ImportedReturnTypeAsset::new, ReturnTypeAsset.ABSTRACT_CODEC ) @@ -22,7 +24,7 @@ public class ImportedReturnTypeAsset extends ReturnTypeAsset { private String importedAssetName = ""; @Override - public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public ReturnType build(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { ReturnTypeAsset asset = getExportedAsset(this.importedAssetName); if (asset == null) { Logger.getLogger("Density") @@ -41,7 +43,7 @@ public class ImportedReturnTypeAsset extends ReturnTypeAsset { } }; } else { - return asset.build(parentSeed, referenceBundle); + return asset.build(parentSeed, referenceBundle, workerId); } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ReturnTypeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ReturnTypeAsset.java index 5423d34c..ea56b30d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ReturnTypeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/density/positions/returntypes/ReturnTypeAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.LoggerUtil; import com.hypixel.hytale.builtin.hytalegenerator.density.nodes.positions.returntypes.ReturnType; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -18,13 +19,19 @@ import java.util.Map; import javax.annotation.Nonnull; public abstract class ReturnTypeAsset implements JsonAssetWithMap> { + @Nonnull private static final ReturnTypeAsset[] EMPTY_INPUTS = new ReturnTypeAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new HashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(ReturnTypeAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(ReturnTypeAsset.class) .append(new KeyedCodec<>("ExportAs", Codec.STRING, false), (t, k) -> t.exportName = k, t -> t.exportName) .add() @@ -42,7 +49,7 @@ public abstract class ReturnTypeAsset implements JsonAssetWithMap CODEC = BuilderCodec.builder( ConstantEnvironmentProviderAsset.class, ConstantEnvironmentProviderAsset::new, EnvironmentProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/DensityDelimitedEnvironmentProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/DensityDelimitedEnvironmentProviderAsset.java index f8cf2065..273b450d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/DensityDelimitedEnvironmentProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/DensityDelimitedEnvironmentProviderAsset.java @@ -21,6 +21,7 @@ import java.util.List; import javax.annotation.Nonnull; public class DensityDelimitedEnvironmentProviderAsset extends EnvironmentProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DensityDelimitedEnvironmentProviderAsset.class, DensityDelimitedEnvironmentProviderAsset::new, EnvironmentProviderAsset.ABSTRACT_CODEC ) @@ -69,6 +70,7 @@ public class DensityDelimitedEnvironmentProviderAsset extends EnvironmentProvide public static class DelimiterAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( DensityDelimitedEnvironmentProviderAsset.DelimiterAsset.class, DensityDelimitedEnvironmentProviderAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/EnvironmentProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/EnvironmentProviderAsset.java index 91e13c58..d303c2fd 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/EnvironmentProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/environmentproviders/EnvironmentProviderAsset.java @@ -11,6 +11,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.environmentproviders.Environme import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -20,12 +21,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class EnvironmentProviderAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(EnvironmentProviderAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(EnvironmentProviderAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -77,17 +83,22 @@ public abstract class EnvironmentProviderAsset implements Cleanable, JsonAssetWi public SeedBox parentSeed; public MaterialCache materialCache; public ReferenceBundle referenceBundle; + public WorkerIndexer.Id workerId; - public Argument(@Nonnull SeedBox parentSeed, @Nonnull MaterialCache materialCache, @Nonnull ReferenceBundle referenceBundle) { + public Argument( + @Nonnull SeedBox parentSeed, @Nonnull MaterialCache materialCache, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId + ) { this.parentSeed = parentSeed; this.materialCache = materialCache; this.referenceBundle = referenceBundle; + this.workerId = workerId; } public Argument(@Nonnull EnvironmentProviderAsset.Argument argument) { this.parentSeed = argument.parentSeed; this.materialCache = argument.materialCache; this.referenceBundle = argument.referenceBundle; + this.workerId = argument.workerId; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/framework/DecimalConstantsFrameworkAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/framework/DecimalConstantsFrameworkAsset.java new file mode 100644 index 00000000..e4fd84c8 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/framework/DecimalConstantsFrameworkAsset.java @@ -0,0 +1,94 @@ +package com.hypixel.hytale.builtin.hytalegenerator.assets.framework; + +import com.hypixel.hytale.assetstore.AssetExtraInfo; +import com.hypixel.hytale.assetstore.codec.AssetBuilderCodec; +import com.hypixel.hytale.assetstore.map.DefaultAssetMap; +import com.hypixel.hytale.assetstore.map.JsonAssetWithMap; +import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.WorldStructureAsset; +import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.codec.codecs.array.ArrayCodec; +import java.util.HashMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class DecimalConstantsFrameworkAsset extends FrameworkAsset { + @Nonnull + public static final String NAME = "DecimalConstants"; + @Nonnull + public static final Class CLASS = DecimalConstantsFrameworkAsset.Entries.class; + @Nonnull + public static final BuilderCodec CODEC = BuilderCodec.builder( + DecimalConstantsFrameworkAsset.class, DecimalConstantsFrameworkAsset::new, FrameworkAsset.ABSTRACT_CODEC + ) + .append( + new KeyedCodec<>("Entries", new ArrayCodec<>(DecimalConstantsFrameworkAsset.EntryAsset.CODEC, DecimalConstantsFrameworkAsset.EntryAsset[]::new), true), + (asset, value) -> asset.entryAssets = value, + asset -> asset.entryAssets + ) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + private DecimalConstantsFrameworkAsset.EntryAsset[] entryAssets = new DecimalConstantsFrameworkAsset.EntryAsset[0]; + + private DecimalConstantsFrameworkAsset() { + } + + @Override + public String getId() { + return this.id; + } + + @Override + public void build(@Nonnull WorldStructureAsset.Argument argument, @Nonnull ReferenceBundle referenceBundle) { + DecimalConstantsFrameworkAsset.Entries entries = new DecimalConstantsFrameworkAsset.Entries(); + + for (DecimalConstantsFrameworkAsset.EntryAsset entryAsset : this.entryAssets) { + entries.put(entryAsset.name, entryAsset.value); + } + + referenceBundle.put("DecimalConstants", entries, CLASS); + } + + public static class Entries extends HashMap { + @Nullable + public static DecimalConstantsFrameworkAsset.Entries get(@Nonnull ReferenceBundle referenceBundle) { + return referenceBundle.get("DecimalConstants", DecimalConstantsFrameworkAsset.CLASS); + } + + @Nullable + public static Double get(@Nonnull String name, @Nonnull ReferenceBundle referenceBundle) { + DecimalConstantsFrameworkAsset.Entries entries = get(referenceBundle); + return entries == null ? null : entries.get(name); + } + } + + public static class EntryAsset implements JsonAssetWithMap> { + @Nonnull + public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( + DecimalConstantsFrameworkAsset.EntryAsset.class, + DecimalConstantsFrameworkAsset.EntryAsset::new, + Codec.STRING, + (asset, id) -> asset.id = id, + config -> config.id, + (config, data) -> config.data = data, + config -> config.data + ) + .append(new KeyedCodec<>("Name", Codec.STRING, true), (asset, value) -> asset.name = value, asset -> asset.name) + .add() + .append(new KeyedCodec<>("Value", Codec.DOUBLE, true), (asset, value) -> asset.value = value, asset -> asset.value) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + private String name = ""; + private double value = 0.0; + + public String getId() { + return this.id; + } + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/mapcontentfield/ContentFieldAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/framework/FrameworkAsset.java similarity index 52% rename from src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/mapcontentfield/ContentFieldAsset.java rename to src/com/hypixel/hytale/builtin/hytalegenerator/assets/framework/FrameworkAsset.java index 587b5f05..78127887 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/mapcontentfield/ContentFieldAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/framework/FrameworkAsset.java @@ -1,4 +1,4 @@ -package com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.mapcontentfield; +package com.hypixel.hytale.builtin.hytalegenerator.assets.framework; import com.hypixel.hytale.assetstore.AssetExtraInfo; import com.hypixel.hytale.assetstore.codec.AssetCodecMapCodec; @@ -6,21 +6,28 @@ import com.hypixel.hytale.assetstore.codec.ContainedAssetCodec; import com.hypixel.hytale.assetstore.map.DefaultAssetMap; import com.hypixel.hytale.assetstore.map.JsonAssetWithMap; import com.hypixel.hytale.builtin.hytalegenerator.assets.Cleanable; +import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.WorldStructureAsset; +import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; +import javax.annotation.Nonnull; -public abstract class ContentFieldAsset implements Cleanable, JsonAssetWithMap> { - public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( +public abstract class FrameworkAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull + public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); - public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(ContentFieldAsset.class, CODEC); + @Nonnull + public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(FrameworkAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); - public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(ContentFieldAsset.class).build(); + @Nonnull + public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(FrameworkAsset.class).build(); private String id; private AssetExtraInfo.Data data; - protected ContentFieldAsset() { + protected FrameworkAsset() { } public String getId() { @@ -30,4 +37,6 @@ public abstract class ContentFieldAsset implements Cleanable, JsonAssetWithMap CLASS = PositionsFrameworkAsset.Entries.class; + @Nonnull + public static final BuilderCodec CODEC = BuilderCodec.builder( + PositionsFrameworkAsset.class, PositionsFrameworkAsset::new, FrameworkAsset.ABSTRACT_CODEC + ) + .append( + new KeyedCodec<>("Entries", new ArrayCodec<>(PositionsFrameworkAsset.EntryAsset.CODEC, PositionsFrameworkAsset.EntryAsset[]::new), true), + (asset, value) -> asset.entryAssets = value, + asset -> asset.entryAssets + ) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + private PositionsFrameworkAsset.EntryAsset[] entryAssets = new PositionsFrameworkAsset.EntryAsset[0]; + + private PositionsFrameworkAsset() { + } + + @Override + public String getId() { + return this.id; + } + + @Override + public void build(@NonNullDecl WorldStructureAsset.Argument argument, @NonNullDecl ReferenceBundle referenceBundle) { + PositionsFrameworkAsset.Entries entries = new PositionsFrameworkAsset.Entries(); + + for (PositionsFrameworkAsset.EntryAsset entryAsset : this.entryAssets) { + entries.put(entryAsset.name, entryAsset.positionProviderAsset); + } + + referenceBundle.put("Positions", entries, CLASS); + } + + public static class Entries extends HashMap { + @Nullable + public static PositionsFrameworkAsset.Entries get(@Nonnull ReferenceBundle referenceBundle) { + return referenceBundle.get("Positions", PositionsFrameworkAsset.CLASS); + } + + @Nullable + public static PositionProviderAsset get(@Nonnull String name, @Nonnull ReferenceBundle referenceBundle) { + PositionsFrameworkAsset.Entries entries = get(referenceBundle); + return entries == null ? null : entries.get(name); + } + } + + public static class EntryAsset implements JsonAssetWithMap> { + @Nonnull + public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( + PositionsFrameworkAsset.EntryAsset.class, + PositionsFrameworkAsset.EntryAsset::new, + Codec.STRING, + (asset, id) -> asset.id = id, + config -> config.id, + (config, data) -> config.data = data, + config -> config.data + ) + .append(new KeyedCodec<>("Name", Codec.STRING, true), (asset, value) -> asset.name = value, asset -> asset.name) + .add() + .append( + new KeyedCodec<>("Positions", PositionProviderAsset.CODEC, true), + (asset, value) -> asset.positionProviderAsset = value, + asset -> asset.positionProviderAsset + ) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + private String name = ""; + private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); + + public String getId() { + return this.id; + } + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/interpolationasset/BiomeFrontierAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/interpolationasset/BiomeFrontierAsset.java index 4ecaf55c..4b38f77d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/interpolationasset/BiomeFrontierAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/interpolationasset/BiomeFrontierAsset.java @@ -6,8 +6,10 @@ import com.hypixel.hytale.assetstore.map.DefaultAssetMap; import com.hypixel.hytale.assetstore.map.JsonAssetWithMap; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; +import javax.annotation.Nonnull; public class BiomeFrontierAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( BiomeFrontierAsset.class, BiomeFrontierAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/material/MaterialAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/material/MaterialAsset.java index aeb5154f..3524f322 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/material/MaterialAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/material/MaterialAsset.java @@ -11,9 +11,12 @@ import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.material.SolidMaterial; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple; import javax.annotation.Nonnull; public class MaterialAsset implements JsonAssetWithMap>, Cleanable { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( MaterialAsset.class, MaterialAsset::new, @@ -27,6 +30,10 @@ public class MaterialAsset implements JsonAssetWithMap("Fluid", Codec.STRING, true), (t, value) -> t.fluidName = value, t -> t.fluidName) .add() + .append(new KeyedCodec<>("SolidBottomUp", Codec.BOOLEAN, false), (t, value) -> t.isSolidBottomUp = value, t -> t.isSolidBottomUp) + .add() + .append(new KeyedCodec<>("SolidRotation", OrthogonalRotationAsset.CODEC, false), (t, value) -> t.solidRotationAsset = value, t -> t.solidRotationAsset) + .add() .build(); private String id; private AssetExtraInfo.Data data; @@ -34,19 +41,37 @@ public class MaterialAsset implements JsonAssetWithMap> { + @Nonnull + public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( + OrthogonalRotationAsset.class, + OrthogonalRotationAsset::new, + Codec.STRING, + (asset, id) -> asset.id = id, + config -> config.id, + (config, data) -> config.data = data, + config -> config.data + ) + .append(new KeyedCodec<>("Yaw", Rotation.CODEC, false), (asset, value) -> asset.yaw = value, asset -> asset.yaw) + .add() + .append(new KeyedCodec<>("Pitch", Rotation.CODEC, false), (asset, value) -> asset.pitch = value, asset -> asset.pitch) + .add() + .append(new KeyedCodec<>("Roll", Rotation.CODEC, false), (asset, value) -> asset.roll = value, asset -> asset.roll) + .add() + .build(); + private String id; + private AssetExtraInfo.Data data; + @Nonnull + private Rotation yaw = Rotation.None; + @Nonnull + private Rotation pitch = Rotation.None; + @Nonnull + private Rotation roll = Rotation.None; + + @Nonnull + public RotationTuple build() { + return RotationTuple.of(this.yaw, this.pitch, this.roll); + } + + public boolean isNone() { + return this.yaw == Rotation.None && this.pitch == Rotation.None && this.roll == Rotation.None; + } + + public String getId() { + return this.id; + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ConstantMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ConstantMaterialProviderAsset.java index 7050a5c0..9ce6ab72 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ConstantMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ConstantMaterialProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ConstantMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantMaterialProviderAsset.class, ConstantMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardDepthMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardDepthMaterialProviderAsset.java index 23fd5165..9e253e1a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardDepthMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardDepthMaterialProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class DownwardDepthMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DownwardDepthMaterialProviderAsset.class, DownwardDepthMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -17,7 +18,7 @@ public class DownwardDepthMaterialProviderAsset extends MaterialProviderAsset { .append(new KeyedCodec<>("Material", MaterialProviderAsset.CODEC, true), (t, k) -> t.materialProviderAsset = k, k -> k.materialProviderAsset) .add() .build(); - private int depth = 0; + private int depth; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardSpaceMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardSpaceMaterialProviderAsset.java index 19bdc30f..5eff7676 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardSpaceMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/DownwardSpaceMaterialProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class DownwardSpaceMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DownwardSpaceMaterialProviderAsset.class, DownwardSpaceMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/FieldFunctionMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/FieldFunctionMaterialProviderAsset.java index 683d0625..d662c6e4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/FieldFunctionMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/FieldFunctionMaterialProviderAsset.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class FieldFunctionMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FieldFunctionMaterialProviderAsset.class, FieldFunctionMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -71,6 +72,7 @@ public class FieldFunctionMaterialProviderAsset extends MaterialProviderAsset { public static class DelimiterAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( FieldFunctionMaterialProviderAsset.DelimiterAsset.class, FieldFunctionMaterialProviderAsset.DelimiterAsset::new, @@ -89,8 +91,8 @@ public class FieldFunctionMaterialProviderAsset extends MaterialProviderAsset { .build(); private String id; private AssetExtraInfo.Data data; - private double from = 0.0; - private double to = 0.0; + private double from; + private double to; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); public String getId() { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ImportedMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ImportedMaterialProviderAsset.java index 475c8cbe..50a1e200 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ImportedMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/ImportedMaterialProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ImportedMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedMaterialProviderAsset.class, ImportedMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/MaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/MaterialProviderAsset.java index 83412e12..8fa24e21 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/MaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/MaterialProviderAsset.java @@ -14,6 +14,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.materialproviders.MaterialProvider; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -23,13 +24,19 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class MaterialProviderAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull private static final MaterialProviderAsset[] EMPTY_INPUTS = new MaterialProviderAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(MaterialProviderAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(MaterialProviderAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -48,7 +55,7 @@ public abstract class MaterialProviderAsset implements Cleanable, JsonAssetWithM .build(); private String id; private AssetExtraInfo.Data data; - private boolean skip = false; + private boolean skip; private String exportName = ""; protected MaterialProviderAsset() { @@ -68,12 +75,14 @@ public abstract class MaterialProviderAsset implements Cleanable, JsonAssetWithM return this.id; } + @Nonnull public static MaterialProviderAsset.Argument argumentFrom(@Nonnull DensityAsset.Argument argument, @Nonnull MaterialCache materialCache) { - return new MaterialProviderAsset.Argument(argument.parentSeed, materialCache, argument.referenceBundle); + return new MaterialProviderAsset.Argument(argument.parentSeed, materialCache, argument.referenceBundle, argument.workerId); } + @Nonnull public static MaterialProviderAsset.Argument argumentFrom(@Nonnull PropAsset.Argument argument) { - return new MaterialProviderAsset.Argument(argument.parentSeed, argument.materialCache, argument.referenceBundle); + return new MaterialProviderAsset.Argument(argument.parentSeed, argument.materialCache, argument.referenceBundle, argument.workerId); } @Override @@ -84,16 +93,21 @@ public abstract class MaterialProviderAsset implements Cleanable, JsonAssetWithM public SeedBox parentSeed; public MaterialCache materialCache; public ReferenceBundle referenceBundle; + public WorkerIndexer.Id workerId; - public Argument(@Nonnull SeedBox parentSeed, @Nonnull MaterialCache materialCache, @Nonnull ReferenceBundle referenceBundle) { + public Argument( + @Nonnull SeedBox parentSeed, @Nonnull MaterialCache materialCache, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId + ) { this.parentSeed = parentSeed; this.materialCache = materialCache; this.referenceBundle = referenceBundle; + this.workerId = workerId; } public Argument(@Nonnull MaterialProviderAsset.Argument argument) { this.parentSeed = argument.parentSeed; this.materialCache = argument.materialCache; + this.workerId = argument.workerId; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/QueueMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/QueueMaterialProviderAsset.java index 1b3b5aa7..715ae5fb 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/QueueMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/QueueMaterialProviderAsset.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class QueueMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( QueueMaterialProviderAsset.class, QueueMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SimpleHorizontalMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SimpleHorizontalMaterialProviderAsset.java index a438a2cd..f33d9932 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SimpleHorizontalMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SimpleHorizontalMaterialProviderAsset.java @@ -1,17 +1,16 @@ package com.hypixel.hytale.builtin.hytalegenerator.assets.materialproviders; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.DecimalConstantsFrameworkAsset; import com.hypixel.hytale.builtin.hytalegenerator.material.Material; import com.hypixel.hytale.builtin.hytalegenerator.materialproviders.HorizontalMaterialProvider; import com.hypixel.hytale.builtin.hytalegenerator.materialproviders.MaterialProvider; -import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.BaseHeightReference; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; -import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class SimpleHorizontalMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SimpleHorizontalMaterialProviderAsset.class, SimpleHorizontalMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -26,8 +25,8 @@ public class SimpleHorizontalMaterialProviderAsset extends MaterialProviderAsset .append(new KeyedCodec<>("BottomBaseHeight", Codec.STRING, false), (t, k) -> t.bottomBaseHeightName = k, t -> t.bottomBaseHeightName) .add() .build(); - private int topY = 0; - private int bottomY = 0; + private int topY; + private int bottomY; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); private String topBaseHeightName = ""; private String bottomBaseHeightName = ""; @@ -38,33 +37,21 @@ public class SimpleHorizontalMaterialProviderAsset extends MaterialProviderAsset if (super.skip()) { return MaterialProvider.noMaterialProvider(); } else { - BiDouble2DoubleFunction topFunction = (x, z) -> this.topY; - BiDouble2DoubleFunction bottomFunction = (x, z) -> this.bottomY; + double topBaseHeight = 0.0; + double bottomBaseHeight = 0.0; if (!this.topBaseHeightName.isEmpty()) { - BaseHeightReference topHeightDataLayer = argument.referenceBundle.getLayerWithName(this.topBaseHeightName, BaseHeightReference.class); - if (topHeightDataLayer != null) { - BiDouble2DoubleFunction baseHeight = topHeightDataLayer.getHeightFunction(); - topFunction = (x, z) -> baseHeight.apply(x, z) + this.topY; - } else { - HytaleLogger.getLogger() - .atConfig() - .log("Couldn't find height data layer with name \"" + this.topBaseHeightName + "\", using a zero-constant Density node."); + Double topValue = DecimalConstantsFrameworkAsset.Entries.get(this.topBaseHeightName, argument.referenceBundle); + if (topValue != null) { + topBaseHeight = topValue; + } + + Double bottomValue = DecimalConstantsFrameworkAsset.Entries.get(this.bottomBaseHeightName, argument.referenceBundle); + if (topValue != null) { + bottomBaseHeight = bottomValue; } } - if (!this.bottomBaseHeightName.isEmpty()) { - BaseHeightReference bottomHeightDataLayer = argument.referenceBundle.getLayerWithName(this.bottomBaseHeightName, BaseHeightReference.class); - if (bottomHeightDataLayer != null) { - BiDouble2DoubleFunction baseHeight = bottomHeightDataLayer.getHeightFunction(); - bottomFunction = (x, z) -> baseHeight.apply(x, z) + this.bottomY; - } else { - HytaleLogger.getLogger() - .atConfig() - .log("Couldn't find height data layer with name \"" + this.bottomBaseHeightName + "\", using a zero-constant Density node."); - } - } - - return new HorizontalMaterialProvider<>(this.materialProviderAsset.build(argument), topFunction::apply, bottomFunction::apply); + return new HorizontalMaterialProvider<>(this.materialProviderAsset.build(argument), this.topY + topBaseHeight, this.bottomY + bottomBaseHeight); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SolidityMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SolidityMaterialProviderAsset.java index a1c775cd..fecbd291 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SolidityMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/SolidityMaterialProviderAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class SolidityMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SolidityMaterialProviderAsset.class, SolidityMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/StripedMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/StripedMaterialProviderAsset.java index 15841b5b..0bfd2e25 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/StripedMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/StripedMaterialProviderAsset.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class StripedMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( StripedMaterialProviderAsset.class, StripedMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -59,6 +60,7 @@ public class StripedMaterialProviderAsset extends MaterialProviderAsset { } public static class StripeAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( StripedMaterialProviderAsset.StripeAsset.class, StripedMaterialProviderAsset.StripeAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/TerrainDensityMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/TerrainDensityMaterialProviderAsset.java index e5edae7c..83002fa6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/TerrainDensityMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/TerrainDensityMaterialProviderAsset.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class TerrainDensityMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( TerrainDensityMaterialProviderAsset.class, TerrainDensityMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -62,6 +63,7 @@ public class TerrainDensityMaterialProviderAsset extends MaterialProviderAsset { public static class DelimiterAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( TerrainDensityMaterialProviderAsset.DelimiterAsset.class, TerrainDensityMaterialProviderAsset.DelimiterAsset::new, @@ -80,8 +82,8 @@ public class TerrainDensityMaterialProviderAsset extends MaterialProviderAsset { .build(); private String id; private AssetExtraInfo.Data data; - private double from = 0.0; - private double to = 0.0; + private double from; + private double to; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); public String getId() { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardDepthMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardDepthMaterialProviderAsset.java index 41995bc1..f018304d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardDepthMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardDepthMaterialProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class UpwardDepthMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( UpwardDepthMaterialProviderAsset.class, UpwardDepthMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -17,7 +18,7 @@ public class UpwardDepthMaterialProviderAsset extends MaterialProviderAsset { .append(new KeyedCodec<>("Material", MaterialProviderAsset.CODEC, true), (t, k) -> t.materialProviderAsset = k, k -> k.materialProviderAsset) .add() .build(); - private int depth = 0; + private int depth; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardSpaceMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardSpaceMaterialProviderAsset.java index baf1fc21..b0ddcd8d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardSpaceMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/UpwardSpaceMaterialProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class UpwardSpaceMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( UpwardSpaceMaterialProviderAsset.class, UpwardSpaceMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -17,7 +18,7 @@ public class UpwardSpaceMaterialProviderAsset extends MaterialProviderAsset { .append(new KeyedCodec<>("Material", MaterialProviderAsset.CODEC, true), (t, k) -> t.materialProviderAsset = k, k -> k.materialProviderAsset) .add() .build(); - private int space = 0; + private int space; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/WeightedMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/WeightedMaterialProviderAsset.java index 6b0cf8bb..b0447c6a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/WeightedMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/WeightedMaterialProviderAsset.java @@ -17,6 +17,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class WeightedMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( WeightedMaterialProviderAsset.class, WeightedMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) @@ -36,7 +37,7 @@ public class WeightedMaterialProviderAsset extends MaterialProviderAsset { .add() .build(); private WeightedMaterialProviderAsset.WeightedMaterialAsset[] weighedMapEntries = new WeightedMaterialProviderAsset.WeightedMaterialAsset[0]; - private double skipChance = 0.0; + private double skipChance; private String seed = ""; @Nonnull @@ -65,6 +66,7 @@ public class WeightedMaterialProviderAsset extends MaterialProviderAsset { public static class WeightedMaterialAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( WeightedMaterialProviderAsset.WeightedMaterialAsset.class, WeightedMaterialProviderAsset.WeightedMaterialAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/SpaceAndDepthMaterialProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/SpaceAndDepthMaterialProviderAsset.java index e907547f..58f74505 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/SpaceAndDepthMaterialProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/SpaceAndDepthMaterialProviderAsset.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class SpaceAndDepthMaterialProviderAsset extends MaterialProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SpaceAndDepthMaterialProviderAsset.class, SpaceAndDepthMaterialProviderAsset::new, MaterialProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AlwaysTrueConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AlwaysTrueConditionAsset.java index bb3d6b71..2af392b4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AlwaysTrueConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AlwaysTrueConditionAsset.java @@ -6,6 +6,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class AlwaysTrueConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AlwaysTrueConditionAsset.class, AlwaysTrueConditionAsset::new, ConditionAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AndConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AndConditionAsset.java index 35b16195..63895d33 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AndConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/AndConditionAsset.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class AndConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AndConditionAsset.class, AndConditionAsset::new, ConditionAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/ConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/ConditionAsset.java index 4f0209b8..28660a28 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/ConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/ConditionAsset.java @@ -9,14 +9,20 @@ import com.hypixel.hytale.builtin.hytalegenerator.materialproviders.spaceanddept import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; +import javax.annotation.Nonnull; public abstract class ConditionAsset implements JsonAssetWithMap> { + @Nonnull private static final ConditionAsset[] EMPTY_INPUTS = new ConditionAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(ConditionAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(ConditionAsset.class).build(); private String id; private AssetExtraInfo.Data data; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/EqualsConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/EqualsConditionAsset.java index e337b533..fc201de3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/EqualsConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/EqualsConditionAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class EqualsConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( EqualsConditionAsset.class, EqualsConditionAsset::new, ConditionAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/GreaterThanConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/GreaterThanConditionAsset.java index 0749e241..283a7117 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/GreaterThanConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/GreaterThanConditionAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class GreaterThanConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( GreaterThanConditionAsset.class, GreaterThanConditionAsset::new, ConditionAsset.ABSTRACT_CODEC ) @@ -18,7 +19,7 @@ public class GreaterThanConditionAsset extends ConditionAsset { .add() .build(); private ConditionParameter parameter = ConditionParameter.SPACE_ABOVE_FLOOR; - private int threshold = 0; + private int threshold; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/NotConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/NotConditionAsset.java index fd3db553..894a032b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/NotConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/NotConditionAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class NotConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( NotConditionAsset.class, NotConditionAsset::new, ConditionAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/OrConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/OrConditionAsset.java index cd0f3f4e..c606b61c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/OrConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/OrConditionAsset.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class OrConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(OrConditionAsset.class, OrConditionAsset::new, ConditionAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("Conditions", new ArrayCodec<>(ConditionAsset.CODEC, ConditionAsset[]::new), true), diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/SmallerThanConditionAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/SmallerThanConditionAsset.java index b784a5b9..316ed3e8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/SmallerThanConditionAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/conditionassets/SmallerThanConditionAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class SmallerThanConditionAsset extends ConditionAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SmallerThanConditionAsset.class, SmallerThanConditionAsset::new, ConditionAsset.ABSTRACT_CODEC ) @@ -18,7 +19,7 @@ public class SmallerThanConditionAsset extends ConditionAsset { .add() .build(); private ConditionParameter parameter = ConditionParameter.SPACE_ABOVE_FLOOR; - private int threshold = 0; + private int threshold; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/ConstantThicknessLayerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/ConstantThicknessLayerAsset.java index c3e24424..5bb91f0e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/ConstantThicknessLayerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/ConstantThicknessLayerAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class ConstantThicknessLayerAsset extends LayerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantThicknessLayerAsset.class, ConstantThicknessLayerAsset::new, LayerAsset.ABSTRACT_CODEC ) @@ -21,7 +22,7 @@ public class ConstantThicknessLayerAsset extends LayerAsset { .append(new KeyedCodec<>("Material", MaterialProviderAsset.CODEC, true), (t, k) -> t.materialProviderAsset = k, k -> k.materialProviderAsset) .add() .build(); - private int thickness = 0; + private int thickness; private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/LayerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/LayerAsset.java index 77f662aa..8b0de02a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/LayerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/LayerAsset.java @@ -15,12 +15,17 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public abstract class LayerAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull private static final LayerAsset[] EMPTY_INPUTS = new LayerAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(LayerAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(LayerAsset.class).build(); private String id; private AssetExtraInfo.Data data; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/NoiseThicknessAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/NoiseThicknessAsset.java index 7209eca4..14320e6f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/NoiseThicknessAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/NoiseThicknessAsset.java @@ -14,6 +14,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class NoiseThicknessAsset extends LayerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( NoiseThicknessAsset.class, NoiseThicknessAsset::new, LayerAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/RangeThicknessAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/RangeThicknessAsset.java index 061e2626..c7823d9a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/RangeThicknessAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/RangeThicknessAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class RangeThicknessAsset extends LayerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( RangeThicknessAsset.class, RangeThicknessAsset::new, LayerAsset.ABSTRACT_CODEC ) @@ -27,8 +28,8 @@ public class RangeThicknessAsset extends LayerAsset { .build(); private MaterialProviderAsset materialProviderAsset = new ConstantMaterialProviderAsset(); private String seed = ""; - private int rangeMin = 0; - private int rangeMax = 0; + private int rangeMin; + private int rangeMax; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/WeightedThicknessLayerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/WeightedThicknessLayerAsset.java index 73e14955..c2be500b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/WeightedThicknessLayerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/materialproviders/spaceanddepth/layerassets/WeightedThicknessLayerAsset.java @@ -18,6 +18,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class WeightedThicknessLayerAsset extends LayerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( WeightedThicknessLayerAsset.class, WeightedThicknessLayerAsset::new, LayerAsset.ABSTRACT_CODEC ) @@ -59,6 +60,7 @@ public class WeightedThicknessLayerAsset extends LayerAsset { } public static class WeightedThicknessAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( WeightedThicknessLayerAsset.WeightedThicknessAsset.class, WeightedThicknessLayerAsset.WeightedThicknessAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/CellNoiseAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/CellNoiseAsset.java index 5293d495..b805fc29 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/CellNoiseAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/CellNoiseAsset.java @@ -13,7 +13,9 @@ import java.util.Set; import javax.annotation.Nonnull; public class CellNoiseAsset extends NoiseAsset { + @Nonnull private static Set validCellTypes = new HashSet<>(); + @Nonnull public static final BuilderCodec CODEC; private double warpScale = 1.0; private double warpAmount = 1.0; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/NoiseAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/NoiseAsset.java index 36df09bd..81245460 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/NoiseAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/NoiseAsset.java @@ -13,11 +13,15 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public abstract class NoiseAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(NoiseAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(NoiseAsset.class).build(); private String id; private AssetExtraInfo.Data data; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/SimplexNoiseAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/SimplexNoiseAsset.java index 39f77f01..2fe1b7bd 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/SimplexNoiseAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/noisegenerators/SimplexNoiseAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class SimplexNoiseAsset extends NoiseAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(SimplexNoiseAsset.class, SimplexNoiseAsset::new, NoiseAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Lacunarity", Codec.DOUBLE, true), (asset, lacunarity) -> asset.lacunarity = lacunarity, asset -> asset.lacunarity) .addValidator(Validators.greaterThan(0.0)) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/AndPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/AndPatternAsset.java index bde6fcbe..17bdc375 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/AndPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/AndPatternAsset.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class AndPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(AndPatternAsset.class, AndPatternAsset::new, PatternAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("Patterns", new ArrayCodec<>(PatternAsset.CODEC, PatternAsset[]::new), true), (t, k) -> t.patternAssets = k, k -> k.patternAssets diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/BlockSetPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/BlockSetPatternAsset.java index bf3ffda0..b0e74201 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/BlockSetPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/BlockSetPatternAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class BlockSetPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( BlockSetPatternAsset.class, BlockSetPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CeilingPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CeilingPatternAsset.java index e99150b0..5c0b6dd5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CeilingPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CeilingPatternAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class CeilingPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CeilingPatternAsset.class, CeilingPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ConstantPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ConstantPatternAsset.java index 274ef305..841382ed 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ConstantPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ConstantPatternAsset.java @@ -8,14 +8,16 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ConstantPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantPatternAsset.class, ConstantPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) .append(new KeyedCodec<>("Value", Codec.BOOLEAN, true), (asset, value) -> asset.value = value, value -> value.value) .add() .build(); - private boolean value = false; + private boolean value; + @Nonnull @Override public Pattern build(@Nonnull PatternAsset.Argument argument) { return super.isSkipped() ? Pattern.noPattern() : new Pattern() { @@ -24,6 +26,7 @@ public class ConstantPatternAsset extends PatternAsset { return ConstantPatternAsset.this.value; } + @Nonnull @Override public SpaceSize readSpace() { return SpaceSize.empty(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CuboidPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CuboidPatternAsset.java index ac92b7c7..e89c5530 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CuboidPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/CuboidPatternAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class CuboidPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CuboidPatternAsset.class, CuboidPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/DensityPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/DensityPatternAsset.java index 84256acf..9c4a6bab 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/DensityPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/DensityPatternAsset.java @@ -16,6 +16,7 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public class DensityPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DensityPatternAsset.class, DensityPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) @@ -54,6 +55,7 @@ public class DensityPatternAsset extends PatternAsset { } public static class DelimiterAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( DensityPatternAsset.DelimiterAsset.class, DensityPatternAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/FloorPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/FloorPatternAsset.java index 853f7d49..d7493063 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/FloorPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/FloorPatternAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class FloorPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FloorPatternAsset.class, FloorPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/GapPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/GapPatternAsset.java index dc0143c1..d5869238 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/GapPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/GapPatternAsset.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class GapPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(GapPatternAsset.class, GapPatternAsset::new, PatternAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("GapPattern", PatternAsset.CODEC, true), (t, k) -> t.gapPatternAsset = k, k -> k.gapPatternAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ImportedPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ImportedPatternAsset.java index e98d0efa..2badbd1c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ImportedPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/ImportedPatternAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ImportedPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedPatternAsset.class, ImportedPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/MaterialPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/MaterialPatternAsset.java index 27a880d4..8913676a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/MaterialPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/MaterialPatternAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class MaterialPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( MaterialPatternAsset.class, MaterialPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) @@ -17,6 +18,7 @@ public class MaterialPatternAsset extends PatternAsset { .build(); private MaterialAsset materialAsset = new MaterialAsset(); + @Nonnull @Override public Pattern build(@Nonnull PatternAsset.Argument argument) { if (super.isSkipped()) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/NotPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/NotPatternAsset.java index f6b634c5..309554e7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/NotPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/NotPatternAsset.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class NotPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(NotPatternAsset.class, NotPatternAsset::new, PatternAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Pattern", PatternAsset.CODEC, true), (t, k) -> t.patternAsset = k, k -> k.patternAsset) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OffsetPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OffsetPatternAsset.java index 8c439602..4ea5bd07 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OffsetPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OffsetPatternAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class OffsetPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( OffsetPatternAsset.class, OffsetPatternAsset::new, PatternAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OrPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OrPatternAsset.java index 2b33028a..fc2279ee 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OrPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/OrPatternAsset.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class OrPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(OrPatternAsset.class, OrPatternAsset::new, PatternAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("Patterns", new ArrayCodec<>(PatternAsset.CODEC, PatternAsset[]::new), true), (t, k) -> t.patternAssets = k, k -> k.patternAssets diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/PatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/PatternAsset.java index 30c5d4d3..62cfc4bb 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/PatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/PatternAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.patterns.Pattern; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -22,12 +23,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class PatternAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(PatternAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(PatternAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -46,7 +52,7 @@ public abstract class PatternAsset implements Cleanable, JsonAssetWithMap CODEC = BuilderCodec.builder( SurfacePatternAsset.class, SurfacePatternAsset::new, PatternAsset.ABSTRACT_CODEC ) @@ -43,12 +44,12 @@ public class SurfacePatternAsset extends PatternAsset { .build(); private PatternAsset surface = new ConstantPatternAsset(); private PatternAsset origin = new ConstantPatternAsset(); - private double surfaceRadius = 0.0; - private double originRadius = 0.0; - private int surfaceGap = 0; - private int originGap = 0; + private double surfaceRadius; + private double originRadius; + private int surfaceGap; + private int originGap; private SurfacePattern.Facing[] facings = new SurfacePattern.Facing[0]; - private boolean requireAllFacings = false; + private boolean requireAllFacings; @Nonnull @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/WallPatternAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/WallPatternAsset.java index 98d3c2fe..57bbb4e2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/WallPatternAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/patterns/WallPatternAsset.java @@ -10,6 +10,7 @@ import java.util.List; import javax.annotation.Nonnull; public class WallPatternAsset extends PatternAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(WallPatternAsset.class, WallPatternAsset::new, PatternAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Wall", PatternAsset.CODEC, true), (t, k) -> t.wall = k, k -> k.wall) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/MeshPointGeneratorAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/MeshPointGeneratorAsset.java index a952b5d3..7925ec40 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/MeshPointGeneratorAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/MeshPointGeneratorAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class MeshPointGeneratorAsset extends PointGeneratorAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( MeshPointGeneratorAsset.class, MeshPointGeneratorAsset::new, PointGeneratorAsset.ABSTRACT_CODEC ) @@ -29,9 +30,9 @@ public class MeshPointGeneratorAsset extends PointGeneratorAsset { .add() .build(); private double jitter = 0.35; - private double scaleX = 1.0; - private double scaleY = 1.0; - private double scaleZ = 1.0; + private double scaleX = 40.0; + private double scaleY = 40.0; + private double scaleZ = 40.0; private String seedKey = "A"; @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/NoPointGeneratorAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/NoPointGeneratorAsset.java index e05291c8..b6cbce71 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/NoPointGeneratorAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/NoPointGeneratorAsset.java @@ -12,24 +12,29 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; public class NoPointGeneratorAsset extends PointGeneratorAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( NoPointGeneratorAsset.class, NoPointGeneratorAsset::new, PointGeneratorAsset.ABSTRACT_CODEC ) .build(); + @Nonnull @Override public PointProvider build(@Nonnull SeedBox parentSeed) { return new PointProvider() { + @Nonnull @Override public List points3i(@Nonnull Vector3i min, @Nonnull Vector3i max) { return List.of(); } + @Nonnull @Override public List points2i(@Nonnull Vector2i min, @Nonnull Vector2i max) { return List.of(); } + @Nonnull @Override public List points1i(int min, int max) { return List.of(); @@ -47,16 +52,19 @@ public class NoPointGeneratorAsset extends PointGeneratorAsset { public void points1i(int min, int max, @Nonnull Consumer pointsOut) { } + @Nonnull @Override public List points3d(@Nonnull Vector3d min, @Nonnull Vector3d max) { return List.of(); } + @Nonnull @Override public List points2d(@Nonnull Vector2d min, @Nonnull Vector2d max) { return List.of(); } + @Nonnull @Override public List points1d(double min, double max) { return List.of(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/PointGeneratorAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/PointGeneratorAsset.java index e2f7aad1..13913a4c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/PointGeneratorAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/pointgenerators/PointGeneratorAsset.java @@ -17,13 +17,19 @@ import java.util.Map; import javax.annotation.Nonnull; public abstract class PointGeneratorAsset implements JsonAssetWithMap> { + @Nonnull private static final PointGeneratorAsset[] EMPTY_INPUTS = new PointGeneratorAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new HashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(PointGeneratorAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(PointGeneratorAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -38,8 +44,9 @@ public abstract class PointGeneratorAsset implements JsonAssetWithMap CODEC = BuilderCodec.builder( AnchorPositionProviderAsset.class, AnchorPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BaseHeightPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BaseHeightPositionProviderAsset.java index d2723e4f..8a3c6e56 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BaseHeightPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BaseHeightPositionProviderAsset.java @@ -1,16 +1,15 @@ package com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.DecimalConstantsFrameworkAsset; import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.BaseHeightPositionProvider; import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; -import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.BaseHeightReference; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; -import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class BaseHeightPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( BaseHeightPositionProviderAsset.class, BaseHeightPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) @@ -18,7 +17,7 @@ public class BaseHeightPositionProviderAsset extends PositionProviderAsset { .add() .append(new KeyedCodec<>("MaxYRead", Codec.DOUBLE, false), (asset, v) -> asset.maxYRead = v, asset -> asset.maxYRead) .add() - .append(new KeyedCodec<>("BedName", Codec.STRING, false), (asset, v) -> asset.bedName = v, asset -> asset.bedName) + .append(new KeyedCodec<>("BedName", Codec.STRING, false), (asset, v) -> asset.baseHeightName = v, asset -> asset.baseHeightName) .add() .append( new KeyedCodec<>("Positions", PositionProviderAsset.CODEC, true), (asset, v) -> asset.positionProviderAsset = v, asset -> asset.positionProviderAsset @@ -27,7 +26,7 @@ public class BaseHeightPositionProviderAsset extends PositionProviderAsset { .build(); private double minYRead = -1.0; private double maxYRead = 1.0; - private String bedName = ""; + private String baseHeightName = ""; private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); @Nonnull @@ -37,16 +36,12 @@ public class BaseHeightPositionProviderAsset extends PositionProviderAsset { return PositionProvider.noPositionProvider(); } else { PositionProvider positionProvider = this.positionProviderAsset.build(argument); - BaseHeightReference heightDataLayer = argument.referenceBundle.getLayerWithName(this.bedName, BaseHeightReference.class); - if (heightDataLayer == null) { - HytaleLogger.getLogger() - .atConfig() - .log("Couldn't height data layer with name \"" + this.bedName + "\", the positions will not be offset by the bed."); - return new BaseHeightPositionProvider((x, z) -> 0.0, positionProvider, this.minYRead, this.maxYRead); - } else { - BiDouble2DoubleFunction heightFunction = heightDataLayer.getHeightFunction(); - return new BaseHeightPositionProvider(heightFunction, positionProvider, this.minYRead, this.maxYRead); + Double baseHeight = DecimalConstantsFrameworkAsset.Entries.get(this.baseHeightName, argument.referenceBundle); + if (baseHeight == null) { + baseHeight = 0.0; } + + return new BaseHeightPositionProvider(baseHeight, positionProvider, this.minYRead, this.maxYRead); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BoundPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BoundPositionProviderAsset.java new file mode 100644 index 00000000..cca4f3db --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/BoundPositionProviderAsset.java @@ -0,0 +1,39 @@ +package com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders; + +import com.hypixel.hytale.builtin.hytalegenerator.assets.bounds.DecimalBounds3dAsset; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.BoundPositionProvider; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import javax.annotation.Nonnull; + +public class BoundPositionProviderAsset extends PositionProviderAsset { + @Nonnull + public static final BuilderCodec CODEC = BuilderCodec.builder( + BoundPositionProviderAsset.class, BoundPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC + ) + .append(new KeyedCodec<>("Bounds", DecimalBounds3dAsset.CODEC, true), (asset, value) -> asset.bounds = value, asset -> asset.bounds) + .add() + .append( + new KeyedCodec<>("Positions", PositionProviderAsset.CODEC, true), + (asset, value) -> asset.positionProviderAsset = value, + asset -> asset.positionProviderAsset + ) + .add() + .build(); + private DecimalBounds3dAsset bounds = new DecimalBounds3dAsset(); + private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); + + @Nonnull + @Override + public PositionProvider build(@Nonnull PositionProviderAsset.Argument argument) { + return (PositionProvider)(super.skip() + ? PositionProvider.noPositionProvider() + : new BoundPositionProvider(this.positionProviderAsset.build(argument), this.bounds.build())); + } + + @Override + public void cleanUp() { + this.positionProviderAsset.cleanUp(); + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/CachedPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/CachedPositionProviderAsset.java index 0e241920..afd99f0e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/CachedPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/CachedPositionProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class CachedPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CachedPositionProviderAsset.class, CachedPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionOccurrencePositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionOccurrencePositionProviderAsset.java index 60c0ab89..013e70a4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionOccurrencePositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionOccurrencePositionProviderAsset.java @@ -11,6 +11,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class FieldFunctionOccurrencePositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FieldFunctionOccurrencePositionProviderAsset.class, FieldFunctionOccurrencePositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionPositionProviderAsset.java index 2866afe2..f0636e66 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FieldFunctionPositionProviderAsset.java @@ -16,7 +16,9 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public class FieldFunctionPositionProviderAsset extends PositionProviderAsset { + @Nonnull private static final FieldFunctionPositionProviderAsset.DelimiterAsset[] EMPTY_DELIMITER_ASSETS = new FieldFunctionPositionProviderAsset.DelimiterAsset[0]; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FieldFunctionPositionProviderAsset.class, FieldFunctionPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) @@ -47,9 +49,9 @@ public class FieldFunctionPositionProviderAsset extends PositionProviderAsset { if (super.skip()) { return PositionProvider.noPositionProvider(); } else { - Density functionTree = this.densityAsset.build(DensityAsset.from(argument)); + Density density = this.densityAsset.build(DensityAsset.from(argument)); PositionProvider positionProvider = this.positionProviderAsset.build(argument); - FieldFunctionPositionProvider out = new FieldFunctionPositionProvider(functionTree, positionProvider); + FieldFunctionPositionProvider out = new FieldFunctionPositionProvider(density, positionProvider); for (FieldFunctionPositionProviderAsset.DelimiterAsset asset : this.delimiterAssets) { out.addDelimiter(asset.min, asset.max); @@ -66,6 +68,7 @@ public class FieldFunctionPositionProviderAsset extends PositionProviderAsset { } public static class DelimiterAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( FieldFunctionPositionProviderAsset.DelimiterAsset.class, FieldFunctionPositionProviderAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FrameworkPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FrameworkPositionProviderAsset.java new file mode 100644 index 00000000..c1549ed4 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/FrameworkPositionProviderAsset.java @@ -0,0 +1,36 @@ +package com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders; + +import com.hypixel.hytale.builtin.hytalegenerator.LoggerUtil; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.PositionsFrameworkAsset; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import java.util.logging.Level; +import javax.annotation.Nonnull; + +public class FrameworkPositionProviderAsset extends PositionProviderAsset { + @Nonnull + public static final BuilderCodec CODEC = BuilderCodec.builder( + FrameworkPositionProviderAsset.class, FrameworkPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC + ) + .append(new KeyedCodec<>("Name", Codec.STRING, true), (asset, v) -> asset.name = v, asset -> asset.name) + .add() + .build(); + private String name = ""; + + @Override + public PositionProvider build(@Nonnull PositionProviderAsset.Argument argument) { + if (super.skip()) { + return PositionProvider.noPositionProvider(); + } else { + PositionProviderAsset baseAsset = PositionsFrameworkAsset.Entries.get(this.name, argument.referenceBundle); + if (baseAsset == null) { + LoggerUtil.getLogger().log(Level.WARNING, "Couldn't find WorldFramework Positions with name " + this.name); + return PositionProvider.noPositionProvider(); + } else { + return baseAsset.build(argument); + } + } + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ImportedPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ImportedPositionProviderAsset.java index f4652829..8fcc12fd 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ImportedPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ImportedPositionProviderAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ImportedPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedPositionProviderAsset.class, ImportedPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ListPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ListPositionProviderAsset.java index 4c04dd12..611a9081 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ListPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/ListPositionProviderAsset.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class ListPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ListPositionProviderAsset.class, ListPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) @@ -45,6 +46,7 @@ public class ListPositionProviderAsset extends PositionProviderAsset { } public static class PositionAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( ListPositionProviderAsset.PositionAsset.class, ListPositionProviderAsset.PositionAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh2DPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh2DPositionProviderAsset.java index 7909f935..18cea4e5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh2DPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh2DPositionProviderAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Mesh2DPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Mesh2DPositionProviderAsset.class, Mesh2DPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh3DPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh3DPositionProviderAsset.java index 2fa191d9..e8c5f30f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh3DPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/Mesh3DPositionProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class Mesh3DPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( Mesh3DPositionProviderAsset.class, Mesh3DPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/OffsetPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/OffsetPositionProviderAsset.java index 7ce681e3..0c75cc78 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/OffsetPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/OffsetPositionProviderAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class OffsetPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( OffsetPositionProviderAsset.class, OffsetPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) @@ -23,9 +24,9 @@ public class OffsetPositionProviderAsset extends PositionProviderAsset { ) .add() .build(); - private int offsetX = 0; - private int offsetY = 0; - private int offsetZ = 0; + private int offsetX; + private int offsetY; + private int offsetZ; private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/PositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/PositionProviderAsset.java index b7fa4e7d..248d1a88 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/PositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/PositionProviderAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.Cleanable; import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -19,12 +20,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class PositionProviderAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(PositionProviderAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(PositionProviderAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -70,15 +76,18 @@ public abstract class PositionProviderAsset implements Cleanable, JsonAssetWithM public static class Argument { public SeedBox parentSeed; public ReferenceBundle referenceBundle; + public WorkerIndexer.Id workerId; - public Argument(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public Argument(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { this.parentSeed = parentSeed; this.referenceBundle = referenceBundle; + this.workerId = workerId; } public Argument(@Nonnull PositionProviderAsset.Argument argument) { this.parentSeed = argument.parentSeed; this.referenceBundle = argument.referenceBundle; + this.workerId = argument.workerId; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SimpleHorizontalPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SimpleHorizontalPositionProviderAsset.java index 98b92b3e..70fee1b2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SimpleHorizontalPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SimpleHorizontalPositionProviderAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class SimpleHorizontalPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SimpleHorizontalPositionProviderAsset.class, SimpleHorizontalPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SpherePositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SpherePositionProviderAsset.java deleted file mode 100644 index e37892c9..00000000 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/SpherePositionProviderAsset.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders; - -import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; -import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.SpherePositionProvider; -import com.hypixel.hytale.codec.Codec; -import com.hypixel.hytale.codec.KeyedCodec; -import com.hypixel.hytale.codec.builder.BuilderCodec; -import javax.annotation.Nonnull; - -public class SpherePositionProviderAsset extends PositionProviderAsset { - public static final BuilderCodec CODEC = BuilderCodec.builder( - SpherePositionProviderAsset.class, SpherePositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC - ) - .append(new KeyedCodec<>("Range", Codec.DOUBLE, false), (t, k) -> t.range = k, k -> k.range) - .add() - .append(new KeyedCodec<>("Positions", PositionProviderAsset.CODEC, true), (t, k) -> t.positionProviderAsset = k, k -> k.positionProviderAsset) - .add() - .build(); - private double range = 0.0; - private PositionProviderAsset positionProviderAsset = new ListPositionProviderAsset(); - - @Nonnull - @Override - public PositionProvider build(@Nonnull PositionProviderAsset.Argument argument) { - if (super.skip()) { - return PositionProvider.noPositionProvider(); - } else { - PositionProvider positionProvider = this.positionProviderAsset == null - ? PositionProvider.noPositionProvider() - : this.positionProviderAsset.build(argument); - return new SpherePositionProvider(positionProvider, this.range); - } - } - - @Override - public void cleanUp() { - this.positionProviderAsset.cleanUp(); - } -} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/UnionPositionProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/UnionPositionProviderAsset.java index 57c405f6..24c4d820 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/UnionPositionProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/positionproviders/UnionPositionProviderAsset.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class UnionPositionProviderAsset extends PositionProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( UnionPositionProviderAsset.class, UnionPositionProviderAsset::new, PositionProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/AssignmentsAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/AssignmentsAsset.java index 8295a4a8..d21485da 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/AssignmentsAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/AssignmentsAsset.java @@ -11,6 +11,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.propdistributions.Assignments; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -20,12 +21,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class AssignmentsAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(AssignmentsAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(AssignmentsAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -44,7 +50,7 @@ public abstract class AssignmentsAsset implements Cleanable, JsonAssetWithMap CODEC = BuilderCodec.builder( ConstantAssignmentsAsset.class, ConstantAssignmentsAsset::new, AssignmentsAsset.ABSTRACT_CODEC ) @@ -24,7 +25,7 @@ public class ConstantAssignmentsAsset extends AssignmentsAsset { if (super.skip()) { return Assignments.noPropDistribution(argument.runtime); } else { - Prop prop = this.propAsset.build(new PropAsset.Argument(argument.parentSeed, argument.materialCache, argument.referenceBundle)); + Prop prop = this.propAsset.build(new PropAsset.Argument(argument.parentSeed, argument.materialCache, argument.referenceBundle, argument.workerId)); return new ConstantAssignments(prop, argument.runtime); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/FieldFunctionAssignmentsAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/FieldFunctionAssignmentsAsset.java index 6791e573..2beebb65 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/FieldFunctionAssignmentsAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/FieldFunctionAssignmentsAsset.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class FieldFunctionAssignmentsAsset extends AssignmentsAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( FieldFunctionAssignmentsAsset.class, FieldFunctionAssignmentsAsset::new, AssignmentsAsset.ABSTRACT_CODEC ) @@ -60,6 +61,7 @@ public class FieldFunctionAssignmentsAsset extends AssignmentsAsset { } public static class DelimiterAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( FieldFunctionAssignmentsAsset.DelimiterAsset.class, FieldFunctionAssignmentsAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/ImportedAssignmentsAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/ImportedAssignmentsAsset.java index ae8f3f91..22434359 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/ImportedAssignmentsAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/ImportedAssignmentsAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class ImportedAssignmentsAsset extends AssignmentsAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedAssignmentsAsset.class, ImportedAssignmentsAsset::new, AssignmentsAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/SandwichAssignmentsAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/SandwichAssignmentsAsset.java index bf538969..160788f3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/SandwichAssignmentsAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/SandwichAssignmentsAsset.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class SandwichAssignmentsAsset extends AssignmentsAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( SandwichAssignmentsAsset.class, SandwichAssignmentsAsset::new, AssignmentsAsset.ABSTRACT_CODEC ) @@ -53,6 +54,7 @@ public class SandwichAssignmentsAsset extends AssignmentsAsset { } public static class DelimiterAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( SandwichAssignmentsAsset.DelimiterAsset.class, SandwichAssignmentsAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/WeightedAssignmentsAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/WeightedAssignmentsAsset.java index 91a58472..b2a9a244 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/WeightedAssignmentsAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propassignments/WeightedAssignmentsAsset.java @@ -16,6 +16,7 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public class WeightedAssignmentsAsset extends AssignmentsAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( WeightedAssignmentsAsset.class, WeightedAssignmentsAsset::new, AssignmentsAsset.ABSTRACT_CODEC ) @@ -61,6 +62,7 @@ public class WeightedAssignmentsAsset extends AssignmentsAsset { } public static class WeightedAssets implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( WeightedAssignmentsAsset.WeightedAssets.class, WeightedAssignmentsAsset.WeightedAssets::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/BoxPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/BoxPropAsset.java index 4f68c49a..43dc2f8e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/BoxPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/BoxPropAsset.java @@ -14,6 +14,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class BoxPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(BoxPropAsset.class, BoxPropAsset::new, PropAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Range", Vector3i.CODEC, true), (asset, v) -> asset.range = v, asset -> asset.range) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ClusterPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ClusterPropAsset.java index 4c7f0426..af390dcb 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ClusterPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ClusterPropAsset.java @@ -28,6 +28,7 @@ import java.util.logging.Level; import javax.annotation.Nonnull; public class ClusterPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(ClusterPropAsset.class, ClusterPropAsset::new, PropAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Range", Codec.INTEGER, false), (asset, v) -> asset.range = v, asset -> asset.range) .addValidator(Validators.greaterThanOrEqual(0)) @@ -95,6 +96,7 @@ public class ClusterPropAsset extends PropAsset { } public static class WeightedPropAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( ClusterPropAsset.WeightedPropAsset.class, ClusterPropAsset.WeightedPropAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ColumnPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ColumnPropAsset.java index d7034239..5650772d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ColumnPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ColumnPropAsset.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class ColumnPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(ColumnPropAsset.class, ColumnPropAsset::new, PropAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("ColumnBlocks", new ArrayCodec<>(ColumnPropAsset.ColumnBlock.CODEC, ColumnPropAsset.ColumnBlock[]::new), true), @@ -61,7 +62,7 @@ public class ColumnPropAsset extends PropAsset { blockTypes.add(this.columnBlocks[i].materialAsset.build(argument.materialCache)); } - BlockMask blockMask = null; + BlockMask blockMask; if (this.blockMaskAsset != null) { blockMask = this.blockMaskAsset.build(argument.materialCache); } else { @@ -82,6 +83,7 @@ public class ColumnPropAsset extends PropAsset { } public static class ColumnBlock implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( ColumnPropAsset.ColumnBlock.class, ColumnPropAsset.ColumnBlock::new, @@ -99,7 +101,7 @@ public class ColumnPropAsset extends PropAsset { private String id; private AssetExtraInfo.Data data; private int y = 1; - private MaterialAsset materialAsset = new MaterialAsset("Empty", "Empty"); + private MaterialAsset materialAsset = new MaterialAsset("Empty", "Empty", false); public String getId() { return this.id; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/DensityPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/DensityPropAsset.java index 411849b2..ba34a7fd 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/DensityPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/DensityPropAsset.java @@ -20,6 +20,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class DensityPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(DensityPropAsset.class, DensityPropAsset::new, PropAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Range", Vector3i.CODEC, true), (asset, v) -> asset.range = v, asset -> asset.range) .addValidator((LegacyValidator)((v, r) -> { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ImportedPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ImportedPropAsset.java index 09936da1..6c9e6376 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ImportedPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/ImportedPropAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ImportedPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(ImportedPropAsset.class, ImportedPropAsset::new, PropAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Name", Codec.STRING, true), (asset, v) -> asset.name = v, asset -> asset.name) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/NoPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/NoPropAsset.java index cc2e4110..2f19fb2c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/NoPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/NoPropAsset.java @@ -13,14 +13,17 @@ import javax.annotation.Nonnull; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class NoPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(NoPropAsset.class, NoPropAsset::new, PropAsset.ABSTRACT_CODEC).build(); @Nonnull @Override public Prop build(@Nonnull PropAsset.Argument argument) { return new Prop() { + @Nonnull final Bounds3i emptyBounds_voxelGrid = new Bounds3i(); + @Nonnull @Override public ScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { return ScanResult.noScanResult(); @@ -30,6 +33,7 @@ public class NoPropAsset extends PropAsset { public void place(@Nonnull Prop.Context context) { } + @Nonnull @Override public ContextDependency getContextDependency() { return ContextDependency.EMPTY; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/OffsetPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/OffsetPropAsset.java index bf4e43d0..19345d22 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/OffsetPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/OffsetPropAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class OffsetPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(OffsetPropAsset.class, OffsetPropAsset::new, PropAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("Offset", Vector3i.CODEC, true), (asset, value) -> asset.offset_voxelGrid = value, asset -> asset.offset_voxelGrid) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PondFillerPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PondFillerPropAsset.java index ba707d72..724f0e81 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PondFillerPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PondFillerPropAsset.java @@ -20,6 +20,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class PondFillerPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PondFillerPropAsset.class, PondFillerPropAsset::new, PropAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PropAsset.java index 0bbd0b5b..6c9f750f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/PropAsset.java @@ -11,6 +11,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.props.Prop; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -20,12 +21,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class PropAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(PropAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(PropAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -72,17 +78,22 @@ public abstract class PropAsset implements Cleanable, JsonAssetWithMap CODEC = BuilderCodec.builder(QueuePropAsset.class, QueuePropAsset::new, PropAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("Queue", new ArrayCodec<>(PropAsset.CODEC, PropAsset[]::new), true), (asset, v) -> asset.propAssets = v, asset -> asset.propAssets diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/UnionPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/UnionPropAsset.java index 0331d6ae..256af177 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/UnionPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/UnionPropAsset.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import javax.annotation.Nonnull; public class UnionPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(UnionPropAsset.class, UnionPropAsset::new, PropAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("Props", new ArrayCodec<>(PropAsset.CODEC, PropAsset[]::new), true), (asset, v) -> asset.propAssets = v, asset -> asset.propAssets diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/WeightedPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/WeightedPropAsset.java index 069aa954..cb950637 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/WeightedPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/WeightedPropAsset.java @@ -16,6 +16,7 @@ import com.hypixel.hytale.codec.validation.Validators; import javax.annotation.Nonnull; public class WeightedPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(WeightedPropAsset.class, WeightedPropAsset::new, PropAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("Entries", new ArrayCodec<>(WeightedPropAsset.EntryAsset.CODEC, WeightedPropAsset.EntryAsset[]::new), true), @@ -55,6 +56,7 @@ public class WeightedPropAsset extends PropAsset { } public static class EntryAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( WeightedPropAsset.EntryAsset.class, WeightedPropAsset.EntryAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabLoader.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabLoader.java index 8746996d..8adc590e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabLoader.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabLoader.java @@ -14,8 +14,7 @@ import javax.annotation.Nullable; import org.bson.BsonDocument; public class PrefabLoader { - @Nonnull - public static void loadAllPrefabBuffersUnder(@Nonnull Path dirPath, List pathPrefabs) { + public static void loadAllPrefabBuffersUnder(@Nonnull Path dirPath, @Nonnull List pathPrefabs) { if (!Files.isDirectory(dirPath)) { PrefabBuffer prefab = loadPrefabBufferAt(dirPath); if (prefab != null) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabPropAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabPropAsset.java index e5f382af..a919a244 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabPropAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/PrefabPropAsset.java @@ -30,6 +30,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.codec.validation.Validators; import com.hypixel.hytale.common.util.ExceptionUtil; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.PrefabBuffer; @@ -40,6 +41,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class PrefabPropAsset extends PropAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(PrefabPropAsset.class, PrefabPropAsset::new, PropAsset.ABSTRACT_CODEC) .append( new KeyedCodec<>("WeightedPrefabPaths", new ArrayCodec<>(PrefabPropAsset.WeightedPathAsset.CODEC, PrefabPropAsset.WeightedPathAsset[]::new), true), @@ -150,21 +152,25 @@ public class PrefabPropAsset extends PropAsset { List pathPrefabs = new ArrayList<>(); for (AssetPack pack : AssetModule.get().getAssetPacks()) { - Path fullPath = pack.getRoot().resolve("Server"); + Path prefabsDir = pack.getRoot().resolve("Server"); if (this.legacyPath) { - fullPath = fullPath.resolve("World").resolve("Default").resolve("Prefabs"); + prefabsDir = prefabsDir.resolve("World").resolve("Default").resolve("Prefabs"); } else { - fullPath = fullPath.resolve("Prefabs"); + prefabsDir = prefabsDir.resolve("Prefabs"); } - fullPath = fullPath.resolve(path); + Path fullPath = PathUtil.resolvePathWithinDir(prefabsDir, path); + if (fullPath == null) { + LoggerUtil.getLogger().severe("Invalid prefab path: " + path); + return null; + } try { PrefabLoader.loadAllPrefabBuffersUnder(fullPath, pathPrefabs); - } catch (Exception var8) { + } catch (Exception var9) { String msg = "Couldn't load prefab with path: " + path; msg = msg + "\n"; - msg = msg + ExceptionUtil.toStringWithStack(var8); + msg = msg + ExceptionUtil.toStringWithStack(var9); LoggerUtil.getLogger().severe(msg); return null; } @@ -179,6 +185,7 @@ public class PrefabPropAsset extends PropAsset { } public static class WeightedPathAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( PrefabPropAsset.WeightedPathAsset.class, PrefabPropAsset.WeightedPathAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/DirectionalityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/DirectionalityAsset.java index 3f9fe9b7..f2077dc6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/DirectionalityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/DirectionalityAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.props.directionality.Directionality; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; @@ -21,12 +22,17 @@ import java.util.Map; import javax.annotation.Nonnull; public abstract class DirectionalityAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new HashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(DirectionalityAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(DirectionalityAsset.class) .append(new KeyedCodec<>("ExportAs", Codec.STRING, false), (t, k) -> t.exportName = k, t -> t.exportName) .add() @@ -60,24 +66,29 @@ public abstract class DirectionalityAsset implements Cleanable, JsonAssetWithMap @Nonnull public static DirectionalityAsset.Argument argumentFrom(@Nonnull PropAsset.Argument argument) { - return new DirectionalityAsset.Argument(argument.parentSeed, argument.materialCache, argument.referenceBundle); + return new DirectionalityAsset.Argument(argument.parentSeed, argument.materialCache, argument.referenceBundle, argument.workerId); } public static class Argument { public SeedBox parentSeed; public MaterialCache materialCache; public ReferenceBundle referenceBundle; + public WorkerIndexer.Id workerId; - public Argument(@Nonnull SeedBox parentSeed, @Nonnull MaterialCache materialCache, @Nonnull ReferenceBundle referenceBundle) { + public Argument( + @Nonnull SeedBox parentSeed, @Nonnull MaterialCache materialCache, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId + ) { this.parentSeed = parentSeed; this.materialCache = materialCache; this.referenceBundle = referenceBundle; + this.workerId = workerId; } public Argument(@Nonnull DirectionalityAsset.Argument argument) { this.parentSeed = argument.parentSeed; this.materialCache = argument.materialCache; this.referenceBundle = argument.referenceBundle; + this.workerId = argument.workerId; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/ImportedDirectionalityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/ImportedDirectionalityAsset.java index 307657ef..4084414a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/ImportedDirectionalityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/ImportedDirectionalityAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ImportedDirectionalityAsset extends DirectionalityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedDirectionalityAsset.class, ImportedDirectionalityAsset::new, DirectionalityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/PatternDirectionalityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/PatternDirectionalityAsset.java index 66e7a489..f289af82 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/PatternDirectionalityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/PatternDirectionalityAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class PatternDirectionalityAsset extends DirectionalityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( PatternDirectionalityAsset.class, PatternDirectionalityAsset::new, DirectionalityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/RandomDirectionalityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/RandomDirectionalityAsset.java index 82d6b84e..4b6b4cfd 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/RandomDirectionalityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/RandomDirectionalityAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class RandomDirectionalityAsset extends DirectionalityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( RandomDirectionalityAsset.class, RandomDirectionalityAsset::new, DirectionalityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/StaticDirectionalityAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/StaticDirectionalityAsset.java index 146d6ca2..9f7ae2f3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/StaticDirectionalityAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/props/prefabprop/directionality/StaticDirectionalityAsset.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.server.core.prefab.PrefabRotation; import javax.annotation.Nonnull; public class StaticDirectionalityAsset extends DirectionalityAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( StaticDirectionalityAsset.class, StaticDirectionalityAsset::new, DirectionalityAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propstageiterations/PropRuntimeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propstageiterations/PropRuntimeAsset.java index 3a3988e5..471bee58 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propstageiterations/PropRuntimeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/propstageiterations/PropRuntimeAsset.java @@ -14,11 +14,13 @@ import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProv import com.hypixel.hytale.builtin.hytalegenerator.propdistributions.Assignments; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import javax.annotation.Nonnull; public class PropRuntimeAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( PropRuntimeAsset.class, PropRuntimeAsset::new, @@ -57,14 +59,18 @@ public class PropRuntimeAsset implements Cleanable, JsonAssetWithMap CODEC = BuilderCodec.builder(AreaScannerAsset.class, AreaScannerAsset::new, ScannerAsset.ABSTRACT_CODEC) .append(new KeyedCodec<>("ResultCap", Codec.INTEGER, true), (t, k) -> t.resultCap = k, k -> k.resultCap) .addValidator(Validators.greaterThanOrEqual(0)) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnLinearScannerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnLinearScannerAsset.java index 5670796a..35cd6371 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnLinearScannerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnLinearScannerAsset.java @@ -1,17 +1,16 @@ package com.hypixel.hytale.builtin.hytalegenerator.assets.scanners; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; -import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.BaseHeightReference; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.DecimalConstantsFrameworkAsset; import com.hypixel.hytale.builtin.hytalegenerator.scanners.ColumnLinearScanner; import com.hypixel.hytale.builtin.hytalegenerator.scanners.Scanner; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.validation.Validators; -import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ColumnLinearScannerAsset extends ScannerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ColumnLinearScannerAsset.class, ColumnLinearScannerAsset::new, ScannerAsset.ABSTRACT_CODEC ) @@ -26,7 +25,7 @@ public class ColumnLinearScannerAsset extends ScannerAsset { .add() .append(new KeyedCodec<>("RelativeToPosition", Codec.BOOLEAN, false), (t, k) -> t.isRelativeToPosition = k, k -> k.isRelativeToPosition) .add() - .append(new KeyedCodec<>("BaseHeightName", Codec.STRING, false), (t, k) -> t.baseHeight = k, k -> k.baseHeight) + .append(new KeyedCodec<>("BaseHeightName", Codec.STRING, false), (t, k) -> t.baseHeightName = k, k -> k.baseHeightName) .add() .build(); private int minY = 0; @@ -34,7 +33,7 @@ public class ColumnLinearScannerAsset extends ScannerAsset { private int resultCap = 1; private boolean topDownOrder = true; private boolean isRelativeToPosition = false; - private String baseHeight = ""; + private String baseHeightName = ""; @Nonnull @Override @@ -42,16 +41,14 @@ public class ColumnLinearScannerAsset extends ScannerAsset { if (super.skip()) { return Scanner.noScanner(); } else if (this.isRelativeToPosition) { - return new ColumnLinearScanner(this.minY, this.maxY, this.resultCap, this.topDownOrder, true, null); + return new ColumnLinearScanner(this.minY, this.maxY, this.resultCap, this.topDownOrder, true, 0.0); } else { - BaseHeightReference heightDataLayer = argument.referenceBundle.getLayerWithName(this.baseHeight, BaseHeightReference.class); - if (heightDataLayer == null) { - HytaleLogger.getLogger().atConfig().log("Couldn't find height data layer with name \"" + this.baseHeight + "\", defaulting to not using a bed."); - return new ColumnLinearScanner(this.minY, this.maxY, this.resultCap, this.topDownOrder, false, null); - } else { - BiDouble2DoubleFunction baseHeightFunction = heightDataLayer.getHeightFunction(); - return new ColumnLinearScanner(this.minY, this.maxY, this.resultCap, this.topDownOrder, false, baseHeightFunction); + Double baseHeight = DecimalConstantsFrameworkAsset.Entries.get(this.baseHeightName, argument.referenceBundle); + if (baseHeight == null) { + baseHeight = 0.0; } + + return new ColumnLinearScanner(this.minY, this.maxY, this.resultCap, this.topDownOrder, false, baseHeight); } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnRandomScannerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnRandomScannerAsset.java index 247f2aea..d6df6200 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnRandomScannerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ColumnRandomScannerAsset.java @@ -1,8 +1,7 @@ package com.hypixel.hytale.builtin.hytalegenerator.assets.scanners; import com.hypixel.hytale.builtin.hytalegenerator.assets.ValidatorUtil; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; -import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.BaseHeightReference; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.DecimalConstantsFrameworkAsset; import com.hypixel.hytale.builtin.hytalegenerator.scanners.ColumnRandomScanner; import com.hypixel.hytale.builtin.hytalegenerator.scanners.Scanner; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; @@ -10,10 +9,10 @@ import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.validation.Validators; -import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ColumnRandomScannerAsset extends ScannerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ColumnRandomScannerAsset.class, ColumnRandomScannerAsset::new, ScannerAsset.ABSTRACT_CODEC ) @@ -31,7 +30,7 @@ public class ColumnRandomScannerAsset extends ScannerAsset { .add() .append(new KeyedCodec<>("RelativeToPosition", Codec.BOOLEAN, false), (t, k) -> t.isRelativeToPosition = k, k -> k.isRelativeToPosition) .add() - .append(new KeyedCodec<>("BaseHeightName", Codec.STRING, false), (t, k) -> t.baseHeight = k, k -> k.baseHeight) + .append(new KeyedCodec<>("BaseHeightName", Codec.STRING, false), (t, k) -> t.baseHeightName = k, k -> k.baseHeightName) .add() .build(); private int minY = 0; @@ -40,7 +39,7 @@ public class ColumnRandomScannerAsset extends ScannerAsset { private String seed = "A"; private String strategyName = "DART_THROW"; private boolean isRelativeToPosition = false; - private String baseHeight = ""; + private String baseHeightName = ""; @Nonnull @Override @@ -51,16 +50,14 @@ public class ColumnRandomScannerAsset extends ScannerAsset { SeedBox childSeed = argument.parentSeed.child(this.seed); ColumnRandomScanner.Strategy strategy = ColumnRandomScanner.Strategy.valueOf(this.strategyName); if (this.isRelativeToPosition) { - return new ColumnRandomScanner(this.minY, this.maxY, this.resultCap, childSeed.createSupplier().get(), strategy, true, null); + return new ColumnRandomScanner(this.minY, this.maxY, this.resultCap, childSeed.createSupplier().get(), strategy, true, 0.0); } else { - BaseHeightReference heightDataLayer = argument.referenceBundle.getLayerWithName(this.baseHeight, BaseHeightReference.class); - if (heightDataLayer == null) { - HytaleLogger.getLogger().atConfig().log("Couldn't find height data layer with name \"" + this.baseHeight + "\", defaulting to not using a bed."); - return new ColumnRandomScanner(this.minY, this.maxY, this.resultCap, childSeed.createSupplier().get(), strategy, false, null); - } else { - BiDouble2DoubleFunction baseHeightFunction = heightDataLayer.getHeightFunction(); - return new ColumnRandomScanner(this.minY, this.maxY, this.resultCap, childSeed.createSupplier().get(), strategy, false, baseHeightFunction); + Double baseHeight = DecimalConstantsFrameworkAsset.Entries.get(this.baseHeightName, argument.referenceBundle); + if (baseHeight == null) { + baseHeight = 0.0; } + + return new ColumnRandomScanner(this.minY, this.maxY, this.resultCap, childSeed.createSupplier().get(), strategy, false, baseHeight); } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ImportedScannerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ImportedScannerAsset.java index 8555e53a..1dcaac24 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ImportedScannerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ImportedScannerAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.logger.HytaleLogger; import javax.annotation.Nonnull; public class ImportedScannerAsset extends ScannerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedScannerAsset.class, ImportedScannerAsset::new, ScannerAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/OriginScannerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/OriginScannerAsset.java index 40b77bbc..600b9878 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/OriginScannerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/OriginScannerAsset.java @@ -6,6 +6,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class OriginScannerAsset extends ScannerAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( OriginScannerAsset.class, OriginScannerAsset::new, ScannerAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ScannerAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ScannerAsset.java index 2c839349..212f826d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ScannerAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/scanners/ScannerAsset.java @@ -20,12 +20,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class ScannerAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(ScannerAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(ScannerAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/DensityTerrainAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/DensityTerrainAsset.java index 88c98d1f..2a64f3a4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/DensityTerrainAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/DensityTerrainAsset.java @@ -5,11 +5,13 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.density.DensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.density.Density; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import javax.annotation.Nonnull; public class DensityTerrainAsset extends TerrainAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DensityTerrainAsset.class, DensityTerrainAsset::new, TerrainAsset.ABSTRACT_CODEC ) @@ -21,8 +23,8 @@ public class DensityTerrainAsset extends TerrainAsset { @Nonnull @Override - public Density buildDensity(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { - return this.densityAsset.build(new DensityAsset.Argument(parentSeed, referenceBundle)); + public Density buildDensity(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { + return this.densityAsset.build(new DensityAsset.Argument(parentSeed, referenceBundle, workerId)); } @Override diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/TerrainAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/TerrainAsset.java index 0146c84f..f4cb7a1b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/TerrainAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/terrains/TerrainAsset.java @@ -9,28 +9,35 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.Cleanable; import com.hypixel.hytale.builtin.hytalegenerator.density.Density; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; public abstract class TerrainAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull private static final TerrainAsset[] EMPTY_INPUTS = new TerrainAsset[0]; + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(TerrainAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(TerrainAsset.class).build(); private String id; private AssetExtraInfo.Data data; + @Nonnull private TerrainAsset[] inputs = EMPTY_INPUTS; private boolean skip = false; protected TerrainAsset() { } - public abstract Density buildDensity(@Nonnull SeedBox var1, @Nonnull ReferenceBundle var2); + public abstract Density buildDensity(@Nonnull SeedBox var1, @Nonnull ReferenceBundle var2, @Nonnull WorkerIndexer.Id var3); public String getId() { return this.id; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/ConstantTintProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/ConstantTintProviderAsset.java index 74e846b6..8f3d2ab0 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/ConstantTintProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/ConstantTintProviderAsset.java @@ -10,7 +10,9 @@ import com.hypixel.hytale.server.core.codec.ProtocolCodecs; import javax.annotation.Nonnull; public class ConstantTintProviderAsset extends TintProviderAsset { + @Nonnull public static final Color DEFAULT_COLOR = ColorParseUtil.hexStringToColor("#FF0000"); + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantTintProviderAsset.class, ConstantTintProviderAsset::new, TintProviderAsset.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/DensityDelimitedTintProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/DensityDelimitedTintProviderAsset.java index 5c60f5db..dae46e93 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/DensityDelimitedTintProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/DensityDelimitedTintProviderAsset.java @@ -20,6 +20,7 @@ import java.util.List; import javax.annotation.Nonnull; public class DensityDelimitedTintProviderAsset extends TintProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DensityDelimitedTintProviderAsset.class, DensityDelimitedTintProviderAsset::new, TintProviderAsset.ABSTRACT_CODEC ) @@ -57,6 +58,7 @@ public class DensityDelimitedTintProviderAsset extends TintProviderAsset { } public static class DelimiterAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( DensityDelimitedTintProviderAsset.DelimiterAsset.class, DensityDelimitedTintProviderAsset.DelimiterAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/TintProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/TintProviderAsset.java index 5d5450c9..74f6f9b7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/TintProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/tintproviders/TintProviderAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.Cleanable; import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.builtin.hytalegenerator.tintproviders.TintProvider; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; @@ -20,12 +21,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class TintProviderAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(TintProviderAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(TintProviderAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -77,17 +83,22 @@ public abstract class TintProviderAsset implements Cleanable, JsonAssetWithMap CODEC = BuilderCodec.builder( CacheVectorProviderAsset.class, CacheVectorProviderAsset::new, ABSTRACT_CODEC ) @@ -28,6 +29,7 @@ public class CacheVectorProviderAsset extends VectorProviderAsset { this.vectorProviderAsset = vectorProviderAsset; } + @Nonnull @Override public VectorProvider build(@Nonnull VectorProviderAsset.Argument argument) { if (this.isSkipped()) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ConstantVectorProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ConstantVectorProviderAsset.java index ac8b2f4e..e69d4d73 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ConstantVectorProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ConstantVectorProviderAsset.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class ConstantVectorProviderAsset extends VectorProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ConstantVectorProviderAsset.class, ConstantVectorProviderAsset::new, ABSTRACT_CODEC ) @@ -23,6 +24,7 @@ public class ConstantVectorProviderAsset extends VectorProviderAsset { this.value.assign(vector); } + @Nonnull @Override public VectorProvider build(@Nonnull VectorProviderAsset.Argument argument) { return this.isSkipped() ? new ConstantVectorProvider(new Vector3d()) : new ConstantVectorProvider(this.value); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/DensityGradientVectorProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/DensityGradientVectorProviderAsset.java index 4b5fd657..17047208 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/DensityGradientVectorProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/DensityGradientVectorProviderAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class DensityGradientVectorProviderAsset extends VectorProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( DensityGradientVectorProviderAsset.class, DensityGradientVectorProviderAsset::new, VectorProviderAsset.ABSTRACT_CODEC ) @@ -27,6 +28,7 @@ public class DensityGradientVectorProviderAsset extends VectorProviderAsset { private DensityAsset densityAsset = new ConstantDensityAsset(); private double sampleDistance = 1.0; + @Nonnull @Override public VectorProvider build(@Nonnull VectorProviderAsset.Argument argument) { if (this.isSkipped()) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ExportedVectorProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ExportedVectorProviderAsset.java index 6b5c14c4..038ceb07 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ExportedVectorProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ExportedVectorProviderAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class ExportedVectorProviderAsset extends VectorProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ExportedVectorProviderAsset.class, ExportedVectorProviderAsset::new, VectorProviderAsset.ABSTRACT_CODEC ) @@ -35,11 +36,10 @@ public class ExportedVectorProviderAsset extends VectorProviderAsset { LoggerUtil.getLogger().warning("Couldn't find VectorProvider asset exported with name: '" + this.exportName + "'. Using empty Node instead."); return new ConstantVectorProvider(new Vector3d()); } else if (exported.isSingleInstance) { - Thread thread = Thread.currentThread(); - VectorProvider builtInstance = exported.threadInstances.get(thread); + VectorProvider builtInstance = exported.threadInstances.get(argument.workerId); if (builtInstance == null) { builtInstance = this.vectorProviderAsset.build(argument); - exported.threadInstances.put(thread, builtInstance); + exported.threadInstances.put(argument.workerId, builtInstance); } return builtInstance; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ImportedVectorProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ImportedVectorProviderAsset.java index e46403cf..237a3ff9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ImportedVectorProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/ImportedVectorProviderAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class ImportedVectorProviderAsset extends VectorProviderAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ImportedVectorProviderAsset.class, ImportedVectorProviderAsset::new, VectorProviderAsset.ABSTRACT_CODEC ) @@ -28,11 +29,10 @@ public class ImportedVectorProviderAsset extends VectorProviderAsset { LoggerUtil.getLogger().warning("Couldn't find VectorProvider asset exported with name: '" + this.importedNodeName + "'. Using empty Node instead."); return new ConstantVectorProvider(new Vector3d()); } else if (exported.isSingleInstance) { - Thread thread = Thread.currentThread(); - VectorProvider builtInstance = exported.threadInstances.get(thread); + VectorProvider builtInstance = exported.threadInstances.get(argument.workerId); if (builtInstance == null) { builtInstance = exported.asset.build(argument); - exported.threadInstances.put(thread, builtInstance); + exported.threadInstances.put(argument.workerId, builtInstance); } return builtInstance; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/VectorProviderAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/VectorProviderAsset.java index 1dd919f3..36af173b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/VectorProviderAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/vectorproviders/VectorProviderAsset.java @@ -10,6 +10,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.assets.Cleanable; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.DensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.builtin.hytalegenerator.vectorproviders.VectorProvider; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; @@ -20,12 +21,17 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; public abstract class VectorProviderAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull private static final Map exportedNodes = new ConcurrentHashMap<>(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(VectorProviderAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(VectorProviderAsset.class) .append(new KeyedCodec<>("Skip", Codec.BOOLEAN, false), (t, k) -> t.skip = k, t -> t.skip) .add() @@ -79,20 +85,24 @@ public abstract class VectorProviderAsset implements Cleanable, JsonAssetWithMap public static class Argument { public SeedBox parentSeed; public ReferenceBundle referenceBundle; + public WorkerIndexer.Id workerId; - public Argument(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle) { + public Argument(@Nonnull SeedBox parentSeed, @Nonnull ReferenceBundle referenceBundle, @Nonnull WorkerIndexer.Id workerId) { this.parentSeed = parentSeed; this.referenceBundle = referenceBundle; + this.workerId = workerId; } public Argument(@Nonnull VectorProviderAsset.Argument argument) { this.parentSeed = argument.parentSeed; this.referenceBundle = argument.referenceBundle; + this.workerId = argument.workerId; } public Argument(@Nonnull DensityAsset.Argument argument) { this.parentSeed = argument.parentSeed; this.referenceBundle = argument.referenceBundle; + this.workerId = argument.workerId; } } @@ -101,7 +111,7 @@ public abstract class VectorProviderAsset implements Cleanable, JsonAssetWithMap @Nonnull public VectorProviderAsset asset; @Nonnull - public Map threadInstances; + public Map threadInstances; public Exported(boolean isSingleInstance, @Nonnull VectorProviderAsset asset) { this.isSingleInstance = isSingleInstance; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/WorldStructureAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/WorldStructureAsset.java index 075ebd22..2ef58d1b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/WorldStructureAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/WorldStructureAsset.java @@ -6,20 +6,27 @@ import com.hypixel.hytale.assetstore.codec.ContainedAssetCodec; import com.hypixel.hytale.assetstore.map.DefaultAssetMap; import com.hypixel.hytale.assetstore.map.JsonAssetWithMap; import com.hypixel.hytale.builtin.hytalegenerator.assets.Cleanable; +import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.PositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.material.MaterialCache; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; +import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.builtin.hytalegenerator.worldstructure.WorldStructure; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public abstract class WorldStructureAsset implements Cleanable, JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(WorldStructureAsset.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(WorldStructureAsset.class).build(); private String id; private AssetExtraInfo.Data data; @@ -27,8 +34,12 @@ public abstract class WorldStructureAsset implements Cleanable, JsonAssetWithMap protected WorldStructureAsset() { } + @Nullable public abstract WorldStructure build(@Nonnull WorldStructureAsset.Argument var1); + @Nonnull + public abstract PositionProviderAsset getSpawnPositionsAsset(); + public String getId() { return this.id; } @@ -40,15 +51,18 @@ public abstract class WorldStructureAsset implements Cleanable, JsonAssetWithMap public static class Argument { public MaterialCache materialCache; public SeedBox parentSeed; + public WorkerIndexer.Id workerId; - public Argument(@Nonnull MaterialCache materialCache, @Nonnull SeedBox parentSeed) { + public Argument(@Nonnull MaterialCache materialCache, @Nonnull SeedBox parentSeed, @Nonnull WorkerIndexer.Id workerId) { this.materialCache = materialCache; this.parentSeed = parentSeed; + this.workerId = workerId; } public Argument(@Nonnull WorldStructureAsset.Argument argument) { this.materialCache = argument.materialCache; this.parentSeed = argument.parentSeed; + this.workerId = argument.workerId; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BasicWorldStructureAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BasicWorldStructureAsset.java index 6140e74b..c72fdaaa 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BasicWorldStructureAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BasicWorldStructureAsset.java @@ -7,14 +7,15 @@ import com.hypixel.hytale.builtin.hytalegenerator.Registry; import com.hypixel.hytale.builtin.hytalegenerator.assets.biomes.BiomeAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.ConstantDensityAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.density.DensityAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.framework.FrameworkAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.ListPositionProviderAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.PositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.WorldStructureAsset; -import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.mapcontentfield.BaseHeightContentFieldAsset; -import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.mapcontentfield.ContentFieldAsset; import com.hypixel.hytale.builtin.hytalegenerator.biome.Biome; import com.hypixel.hytale.builtin.hytalegenerator.cartas.SimpleNoiseCarta; import com.hypixel.hytale.builtin.hytalegenerator.density.Density; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; import com.hypixel.hytale.builtin.hytalegenerator.rangemaps.DoubleRange; -import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.BaseHeightReference; import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.worldstructure.WorldStructure; import com.hypixel.hytale.codec.Codec; @@ -25,38 +26,52 @@ import com.hypixel.hytale.codec.validation.Validators; import java.util.HashMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class BasicWorldStructureAsset extends WorldStructureAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( BasicWorldStructureAsset.class, BasicWorldStructureAsset::new, WorldStructureAsset.ABSTRACT_CODEC ) .append( new KeyedCodec<>("Biomes", new ArrayCodec<>(BiomeRangeAsset.CODEC, BiomeRangeAsset[]::new), true), - (t, k) -> t.biomeRangeAssets = k, - t -> t.biomeRangeAssets + (asset, value) -> asset.biomeRangeAssets = value, + asset -> asset.biomeRangeAssets ) .add() - .append(new KeyedCodec<>("Density", DensityAsset.CODEC, true), (t, k) -> t.densityAsset = k, t -> t.densityAsset) + .append(new KeyedCodec<>("Density", DensityAsset.CODEC, true), (asset, value) -> asset.densityAsset = value, asset -> asset.densityAsset) .add() .append( new KeyedCodec<>("DefaultBiome", new ContainedAssetCodec<>(BiomeAsset.class, BiomeAsset.CODEC), true), - (t, k) -> t.defaultBiomeId = k, - t -> t.defaultBiomeId + (asset, value) -> asset.defaultBiomeId = value, + asset -> asset.defaultBiomeId ) .addValidatorLate(() -> BiomeAsset.VALIDATOR_CACHE.getValidator().late()) .add() .append( - new KeyedCodec<>("DefaultTransitionDistance", Codec.INTEGER, true), (t, k) -> t.biomeTransitionDistance = k, t -> t.biomeTransitionDistance + new KeyedCodec<>("DefaultTransitionDistance", Codec.INTEGER, true), + (asset, value) -> asset.biomeTransitionDistance = value, + asset -> asset.biomeTransitionDistance ) .addValidator(Validators.greaterThan(0)) .add() - .append(new KeyedCodec<>("MaxBiomeEdgeDistance", Codec.INTEGER, true), (t, k) -> t.maxBiomeEdgeDistance = k, t -> t.maxBiomeEdgeDistance) + .append( + new KeyedCodec<>("MaxBiomeEdgeDistance", Codec.INTEGER, true), + (asset, value) -> asset.maxBiomeEdgeDistance = value, + asset -> asset.maxBiomeEdgeDistance + ) .addValidator(Validators.greaterThanOrEqual(0)) .add() .append( - new KeyedCodec<>("ContentFields", new ArrayCodec<>(ContentFieldAsset.CODEC, ContentFieldAsset[]::new), false), - (t, k) -> t.contentFieldAssets = k, - t -> t.contentFieldAssets + new KeyedCodec<>("Framework", new ArrayCodec<>(FrameworkAsset.CODEC, FrameworkAsset[]::new), false), + (asset, value) -> asset.frameworkAssets = value, + asset -> asset.frameworkAssets + ) + .add() + .append( + new KeyedCodec<>("SpawnPositions", PositionProviderAsset.CODEC, false), + (asset, value) -> asset.spawnPositionsAsset = value, + asset -> asset.spawnPositionsAsset ) .add() .build(); @@ -65,20 +80,16 @@ public class BasicWorldStructureAsset extends WorldStructureAsset { private int maxBiomeEdgeDistance = 0; private DensityAsset densityAsset = new ConstantDensityAsset(); private String defaultBiomeId = ""; - private ContentFieldAsset[] contentFieldAssets = new ContentFieldAsset[0]; + private FrameworkAsset[] frameworkAssets = new FrameworkAsset[0]; + private PositionProviderAsset spawnPositionsAsset = new ListPositionProviderAsset(); @Nullable @Override public WorldStructure build(@Nonnull WorldStructureAsset.Argument argument) { ReferenceBundle referenceBundle = new ReferenceBundle(); - for (int i = this.contentFieldAssets.length - 1; i >= 0; i--) { - if (this.contentFieldAssets[i] instanceof BaseHeightContentFieldAsset bedAsset) { - String name = bedAsset.getName(); - double y = bedAsset.getY(); - BaseHeightReference bedLayer = new BaseHeightReference((x, z) -> y); - referenceBundle.put(name, bedLayer, bedLayer.getClass()); - } + for (FrameworkAsset frameworkAsset : this.frameworkAssets) { + frameworkAsset.build(argument, referenceBundle); } HashMap biomeAssetToBiomeType = new HashMap<>(); @@ -87,7 +98,7 @@ public class BasicWorldStructureAsset extends WorldStructureAsset { LoggerUtil.getLogger().warning("Couldn't find Biome asset with id: " + this.defaultBiomeId); return null; } else { - Biome defaultBiome = defaultBiomeAsset.build(argument.materialCache, argument.parentSeed, referenceBundle); + Biome defaultBiome = defaultBiomeAsset.build(argument.materialCache, argument.parentSeed, referenceBundle, argument.workerId); biomeAssetToBiomeType.put(defaultBiomeAsset, defaultBiome); Density noise = this.densityAsset.build(DensityAsset.from(argument, referenceBundle)); Registry biomeRegistry = new Registry<>(); @@ -104,7 +115,7 @@ public class BasicWorldStructureAsset extends WorldStructureAsset { if (biomeAssetToBiomeType.containsKey(biomeAsset)) { biome = biomeAssetToBiomeType.get(biomeAsset); } else { - biome = biomeAsset.build(argument.materialCache, argument.parentSeed, referenceBundle); + biome = biomeAsset.build(argument.materialCache, argument.parentSeed, referenceBundle, argument.workerId); biomeAssetToBiomeType.put(biomeAsset, biome); } @@ -112,17 +123,25 @@ public class BasicWorldStructureAsset extends WorldStructureAsset { } } - int biomeTransitionRadius = Math.max(1, this.biomeTransitionDistance / 2); - return new WorldStructure(carta, biomeRegistry, biomeTransitionRadius, this.maxBiomeEdgeDistance); + int biomeTransitionDistance = Math.max(1, this.biomeTransitionDistance); + PositionProvider spawnPositions = this.spawnPositionsAsset + .build(new PositionProviderAsset.Argument(argument.parentSeed, referenceBundle, argument.workerId)); + return new WorldStructure(carta, biomeRegistry, biomeTransitionDistance, this.maxBiomeEdgeDistance, spawnPositions); } } + @NonNullDecl + @Override + public PositionProviderAsset getSpawnPositionsAsset() { + return this.spawnPositionsAsset; + } + @Override public void cleanUp() { this.densityAsset.cleanUp(); - for (ContentFieldAsset contentFieldAsset : this.contentFieldAssets) { - contentFieldAsset.cleanUp(); + for (FrameworkAsset frameworkAsset : this.frameworkAssets) { + frameworkAsset.cleanUp(); } BiomeAsset defaultBiomeAsset = (BiomeAsset)((DefaultAssetMap)BiomeAsset.getAssetStore().getAssetMap()).getAsset(this.defaultBiomeId); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BiomeRangeAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BiomeRangeAsset.java index 3715b2ae..c1580b67 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BiomeRangeAsset.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/basic/BiomeRangeAsset.java @@ -13,6 +13,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BiomeRangeAsset implements JsonAssetWithMap> { + @Nonnull public static final AssetBuilderCodec CODEC = AssetBuilderCodec.builder( BiomeRangeAsset.class, BiomeRangeAsset::new, diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/mapcontentfield/BaseHeightContentFieldAsset.java b/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/mapcontentfield/BaseHeightContentFieldAsset.java deleted file mode 100644 index 7f3dff6d..00000000 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/assets/worldstructures/mapcontentfield/BaseHeightContentFieldAsset.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.mapcontentfield; - -import com.hypixel.hytale.assetstore.AssetExtraInfo; -import com.hypixel.hytale.codec.Codec; -import com.hypixel.hytale.codec.KeyedCodec; -import com.hypixel.hytale.codec.builder.BuilderCodec; - -public class BaseHeightContentFieldAsset extends ContentFieldAsset { - public static final BuilderCodec CODEC = BuilderCodec.builder( - BaseHeightContentFieldAsset.class, BaseHeightContentFieldAsset::new, ContentFieldAsset.ABSTRACT_CODEC - ) - .append(new KeyedCodec<>("Name", Codec.STRING, true), (t, k) -> t.name = k, t -> t.name) - .add() - .append(new KeyedCodec<>("Y", Codec.DOUBLE, false), (t, k) -> t.y = k, t -> t.y) - .add() - .build(); - private String id; - private AssetExtraInfo.Data data; - private String name = ""; - private double y = 0.0; - - private BaseHeightContentFieldAsset() { - } - - @Override - public String getId() { - return this.id; - } - - public String getName() { - return this.name; - } - - public double getY() { - return this.y; - } -} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/biome/SimpleBiome.java b/src/com/hypixel/hytale/builtin/hytalegenerator/biome/SimpleBiome.java index 92dde53e..a37faaa5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/biome/SimpleBiome.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/biome/SimpleBiome.java @@ -12,11 +12,17 @@ import java.util.List; import javax.annotation.Nonnull; public class SimpleBiome implements Biome { + @Nonnull private final Density terrainDensity; + @Nonnull private final MaterialProvider materialProvider; + @Nonnull private final List propFields; + @Nonnull private final EnvironmentProvider environmentProvider; + @Nonnull private final TintProvider tintProvider; + @Nonnull private final String biomeName; public SimpleBiome( @@ -38,6 +44,7 @@ public class SimpleBiome implements Biome { this.propFields.add(propField); } + @Nonnull @Override public MaterialProvider getMaterialProvider() { return this.materialProvider; @@ -49,26 +56,31 @@ public class SimpleBiome implements Biome { return this.terrainDensity; } + @Nonnull @Override public String getBiomeName() { return this.biomeName; } + @Nonnull @Override public List getPropFields() { return this.propFields; } + @Nonnull @Override public EnvironmentProvider getEnvironmentProvider() { return this.environmentProvider; } + @Nonnull @Override public TintProvider getTintProvider() { return this.tintProvider; } + @Nonnull @Override public List getAllPropDistributions() { ArrayList list = new ArrayList<>(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3d.java b/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3d.java index 25592c5a..de189a44 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3d.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3d.java @@ -5,7 +5,9 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class Bounds3d implements MemInstrument { + @Nonnull public final Vector3d min; + @Nonnull public final Vector3d max; public Bounds3d() { @@ -49,6 +51,7 @@ public class Bounds3d implements MemInstrument { return this.min.x >= this.max.x || this.min.y >= this.max.y || this.min.z >= this.max.z; } + @Nonnull public Vector3d getSize() { return this.max.clone().subtract(this.min); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3i.java b/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3i.java index aa5f1a11..3363836a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3i.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/bounds/Bounds3i.java @@ -5,7 +5,9 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class Bounds3i implements MemInstrument { + @Nonnull public final Vector3i min; + @Nonnull public final Vector3i max; public Bounds3i() { @@ -49,6 +51,7 @@ public class Bounds3i implements MemInstrument { return this.min.x >= this.max.x || this.min.y >= this.max.y || this.min.z >= this.max.z; } + @Nonnull public Vector3i getSize() { return this.max.clone().subtract(this.min); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkGenerator.java b/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkGenerator.java index 2352ea96..e0b8c99a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkGenerator.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkGenerator.java @@ -1,8 +1,13 @@ package com.hypixel.hytale.builtin.hytalegenerator.chunkgenerator; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedChunk; import javax.annotation.Nonnull; public interface ChunkGenerator { + @Nonnull GeneratedChunk generate(@Nonnull ChunkRequest.Arguments var1); + + @Nonnull + PositionProvider getSpawnPositions(); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkRequest.java b/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkRequest.java index 4d2695c0..e0cb3ca4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkRequest.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/ChunkRequest.java @@ -46,6 +46,11 @@ public record ChunkRequest(@Nonnull ChunkRequest.GeneratorProfile generatorProfi return Objects.hash(this.worldStructureName, this.seed, this.worldCounter); } + public ChunkRequest.GeneratorProfile clone() { + return new ChunkRequest.GeneratorProfile(this.worldStructureName, this.seed, this.worldCounter); + } + + @Nonnull @Override public String toString() { return "GeneratorProfile{worldStructureName='" + this.worldStructureName + "', seed=" + this.seed + ", worldCounter=" + this.worldCounter + "}"; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/FallbackGenerator.java b/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/FallbackGenerator.java index b57132f3..a54ecae7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/FallbackGenerator.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/chunkgenerator/FallbackGenerator.java @@ -1,14 +1,18 @@ package com.hypixel.hytale.builtin.hytalegenerator.chunkgenerator; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedBlockChunk; import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedBlockStateChunk; import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedChunk; import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedEntityChunk; import javax.annotation.Nonnull; +import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class FallbackGenerator implements ChunkGenerator { + @Nonnull public static final FallbackGenerator INSTANCE = new FallbackGenerator(); + @NonNullDecl @Override public GeneratedChunk generate(@Nonnull ChunkRequest.Arguments arguments) { return new GeneratedChunk( @@ -18,4 +22,10 @@ public class FallbackGenerator implements ChunkGenerator { GeneratedChunk.makeSections() ); } + + @NonNullDecl + @Override + public PositionProvider getSpawnPositions() { + return PositionProvider.noPositionProvider(); + } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/conveyor/stagedconveyor/ContextDependency.java b/src/com/hypixel/hytale/builtin/hytalegenerator/conveyor/stagedconveyor/ContextDependency.java index 4127ba7f..c84653ec 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/conveyor/stagedconveyor/ContextDependency.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/conveyor/stagedconveyor/ContextDependency.java @@ -12,7 +12,9 @@ import javax.annotation.Nonnull; public class ContextDependency { @Nonnull public static ContextDependency EMPTY = new ContextDependency(new Vector3i(), new Vector3i()); + @Nonnull private final Vector3i readRange; + @Nonnull private final Vector3i writeRange; private Vector3i trashRange; private Vector3i externalDependencyRange; @@ -174,6 +176,7 @@ public class ContextDependency { return new ContextDependency(rangeFromBounds(readBounds), rangeFromBounds(writeBounds)); } + @Nonnull private static Vector3i rangeFromBounds(@Nonnull Bounds3i readBounds) { Vector3i readRange = new Vector3i(); readRange.x = Math.max(Math.abs(readBounds.min.x), Math.abs(readBounds.max.x - 1)); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/datastructures/voxelspace/NullSpace.java b/src/com/hypixel/hytale/builtin/hytalegenerator/datastructures/voxelspace/NullSpace.java index fa676f31..b0b098b3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/datastructures/voxelspace/NullSpace.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/datastructures/voxelspace/NullSpace.java @@ -6,12 +6,15 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class NullSpace implements VoxelSpace { + @Nonnull private static final NullSpace INSTANCE = new NullSpace(); + @Nonnull public static NullSpace instance() { return INSTANCE; } + @Nonnull public static NullSpace instance(@Nonnull Class clazz) { return INSTANCE; } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/Density.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/Density.java index c2fb1e97..fb107bd6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/Density.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/Density.java @@ -12,6 +12,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public abstract class Density { + @Nonnull private static final Bounds3i DEFAULT_READ_BOUNDS = new Bounds3i(); public static final double DEFAULT_VALUE = Double.MAX_VALUE; public static final double DEFAULT_DENSITY = 0.0; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AnchorDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AnchorDensity.java index 766170d5..be2cf3de 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AnchorDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AnchorDensity.java @@ -9,7 +9,9 @@ public class AnchorDensity extends Density { @Nullable private Density input; private final boolean isReversed; + @Nonnull private final Vector3d rChildPosition; + @Nonnull private final Density.Context rChildContext; public AnchorDensity(Density input, boolean isReversed) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AngleDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AngleDensity.java index 8d9863af..6be879e8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AngleDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AngleDensity.java @@ -13,7 +13,9 @@ public class AngleDensity extends Density { @Nonnull private final Vector3d vector; private final boolean toAxis; + @Nonnull private final Vector3d rOtherVector; + @Nonnull private final VectorProvider.Context rVectorProviderContext; public AngleDensity(@Nonnull VectorProvider vectorProvider, @Nonnull Vector3d vector, boolean toAxis) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AxisDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AxisDensity.java index 3a7157c4..bfc31dae 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AxisDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/AxisDensity.java @@ -8,17 +8,24 @@ import javax.annotation.Nonnull; public class AxisDensity extends Density { public static final double ZERO_DELTA = 1.0E-9; + @Nonnull private static final Vector3d ZERO_VECTOR = new Vector3d(); @Nonnull private final Double2DoubleFunction distanceCurve; @Nonnull private final Vector3d axis; private final boolean isAnchored; + @Nonnull private final Vector3d rPosition; + @Nonnull private final Vector3d r0; + @Nonnull private final Vector3d r1; + @Nonnull private final Vector3d r2; + @Nonnull private final Vector3d r3; + @Nonnull private final Vector3d r4; public AxisDensity(@Nonnull Double2DoubleFunction distanceCurve, @Nonnull Vector3d axis, boolean isAnchored) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/BaseHeightDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/BaseHeightDensity.java index bab58a8b..36e89eb9 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/BaseHeightDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/BaseHeightDensity.java @@ -1,24 +1,21 @@ package com.hypixel.hytale.builtin.hytalegenerator.density.nodes; import com.hypixel.hytale.builtin.hytalegenerator.density.Density; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; import javax.annotation.Nonnull; public class BaseHeightDensity extends Density { @Nonnull - private final BiDouble2DoubleFunction heightFunction; + private final double baseHeight; private final boolean isDistance; - public BaseHeightDensity(@Nonnull BiDouble2DoubleFunction heightFunction, boolean isDistance) { - this.heightFunction = heightFunction; + public BaseHeightDensity(double baseHeight, boolean isDistance) { + this.baseHeight = baseHeight; this.isDistance = isDistance; } @Override public double process(@Nonnull Density.Context context) { - return this.isDistance - ? context.position.y - this.heightFunction.apply(context.position.x, context.position.z) - : this.heightFunction.apply(context.position.x, context.position.z); + return this.isDistance ? context.position.y - this.baseHeight : this.baseHeight; } public boolean skipInputs(double y) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/CacheDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/CacheDensity.java index 5dc66e39..f4a8ee82 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/CacheDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/CacheDensity.java @@ -5,6 +5,7 @@ import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class CacheDensity extends Density { + @Nonnull private final CacheDensity.Cache cache; @Nonnull private Density input; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/FastGradientWarpDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/FastGradientWarpDensity.java index 4ec60db1..88fe8612 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/FastGradientWarpDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/FastGradientWarpDensity.java @@ -13,8 +13,11 @@ public class FastGradientWarpDensity extends Density { private final double warpScale; @Nonnull private final FastNoiseLite warper; + @Nonnull private final FastNoiseLite.Vector3 rWarpedPosition; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rPosition; public FastGradientWarpDensity( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientDensity.java index 6660fc1f..033dcb58 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientDensity.java @@ -13,8 +13,11 @@ public class GradientDensity extends Density { private final double slopeRange; @Nonnull private final Vector3d axis; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rSlopeDirection; + @Nonnull private final Vector3d rPosition; public GradientDensity(@Nonnull Density input, double slopeRange, @Nonnull Vector3d axis) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientWarpDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientWarpDensity.java index 123f7a98..9bf4d647 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientWarpDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/GradientWarpDensity.java @@ -13,8 +13,11 @@ public class GradientWarpDensity extends Density { private Density warpInput; private final double slopeRange; private final double warpFactor; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rGradient; + @Nonnull public final Vector3d rPosition; public GradientWarpDensity(@Nonnull Density input, @Nonnull Density warpInput, double slopeRange, double warpFactor) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiCacheDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiCacheDensity.java index 057a0890..6b364495 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiCacheDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiCacheDensity.java @@ -91,6 +91,7 @@ public class MultiCacheDensity extends Density { } private static class Entry { + @Nullable Vector3d position = null; double value = 0.0; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiMixDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiMixDensity.java index 82b9b067..42c1d744 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiMixDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/MultiMixDensity.java @@ -123,6 +123,7 @@ public class MultiMixDensity extends Density { } public static class GaugeSegmentComparator implements BiFunction { + @Nonnull public static final MultiMixDensity.Segment.GaugeSegmentComparator INSTANCE = new MultiMixDensity.Segment.GaugeSegmentComparator(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PlaneDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PlaneDensity.java index 421351ba..d5cc0d73 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PlaneDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PlaneDensity.java @@ -9,6 +9,7 @@ import javax.annotation.Nullable; public class PlaneDensity extends Density { public static final double ZERO_DELTA = 1.0E-9; + @Nonnull private static final Vector3d ZERO_VECTOR = new Vector3d(); @Nonnull private final Double2DoubleFunction distanceCurve; @@ -16,12 +17,19 @@ public class PlaneDensity extends Density { private final Vector3d planeNormal; private final boolean isPlaneHorizontal; private final boolean isAnchored; + @Nonnull private final Vector3d rNearestPoint; + @Nonnull private final Vector3d rPosition; + @Nonnull private final Vector3d rVectorFromPlane; + @Nonnull private final Vector3d r0; + @Nonnull private final Vector3d r1; + @Nonnull private final Vector3d r2; + @Nonnull private final Vector3d r3; public PlaneDensity(@Nonnull Double2DoubleFunction distanceCurve, @Nonnull Vector3d planeNormal, boolean isAnchored) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsHorizontalPinchDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsHorizontalPinchDensity.java index 9a3329a1..891876d2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsHorizontalPinchDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsHorizontalPinchDensity.java @@ -21,16 +21,27 @@ public class PositionsHorizontalPinchDensity extends Density { private final boolean distanceNormalized; private final double positionsMinY; private final double positionsMaxY; + @Nonnull private final Vector3d rWarpVector; + @Nonnull private final Vector3d rSamplePoint; + @Nonnull private final Vector3d rMin; + @Nonnull private final Vector3d rMax; + @Nonnull private final Vector3d rPosition; + @Nonnull private final Vector3d rConsumerResult; + @Nonnull private final ReusableList rWarpVectors; + @Nonnull private final ReusableList rWarpDistances; + @Nonnull private final ReusableList rWeights; + @Nonnull private final PositionProvider.Context rPositionsContext; + @Nonnull private final Density.Context rChildContext; public PositionsHorizontalPinchDensity( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsPinchDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsPinchDensity.java index 13f3f7b5..98b2d0b8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsPinchDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsPinchDensity.java @@ -16,13 +16,21 @@ public class PositionsPinchDensity extends Density { private Double2DoubleFunction pinchCurve; private double maxDistance; private boolean distanceNormalized; + @Nonnull private final Vector3d rMin; + @Nonnull private final Vector3d rMax; + @Nonnull private final Vector3d rSamplePoint; + @Nonnull private final Vector3d rWarpVector; + @Nonnull private final ReusableList rWarpVectors; + @Nonnull private final ReusableList rWarpDistances; + @Nonnull private final ReusableList rWeights; + @Nonnull private final Density.Context rChildContext; public PositionsPinchDensity( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsTwistDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsTwistDensity.java index 986aae05..c56870d8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsTwistDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/PositionsTwistDensity.java @@ -19,15 +19,25 @@ public class PositionsTwistDensity extends Density { private double maxDistance; private boolean distanceNormalized; private boolean zeroPositionsY; + @Nonnull private final Vector3d rMin; + @Nonnull private final Vector3d rMax; + @Nonnull private final Vector3d rSamplePoint; + @Nonnull private final Vector3d rQueryPosition; + @Nonnull private final Vector3d rWarpVector; + @Nonnull private final ReusableList rWarpVectors; + @Nonnull private final ReusableList rWarpDistances; + @Nonnull private final ReusableList rWeights; + @Nonnull private final PositionProvider.Context rPositionsContext; + @Nonnull private final Density.Context rChildContext; public PositionsTwistDensity( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/RotatorDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/RotatorDensity.java index 51a2d8c5..a619b074 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/RotatorDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/RotatorDensity.java @@ -7,6 +7,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class RotatorDensity extends Density { + @Nonnull private static final Vector3d Y_AXIS = new Vector3d(0.0, 1.0, 0.0); @Nullable private Density input; @@ -16,7 +17,9 @@ public class RotatorDensity extends Density { private final double spinAngle; @Nonnull private final RotatorDensity.SpecialCase axisSpecialCase; + @Nonnull private final Vector3d rChildPosition; + @Nonnull private final Density.Context rChildContext; public RotatorDensity(@Nonnull Density input, @Nonnull Vector3d newYAxis, double spinAngle) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ScaleDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ScaleDensity.java index 9caf6dd8..a59e1861 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ScaleDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ScaleDensity.java @@ -11,7 +11,9 @@ public class ScaleDensity extends Density { private final boolean isInvalid; @Nullable private Density input; + @Nonnull private final Vector3d rChildPosition; + @Nonnull private final Density.Context rChildContext; public ScaleDensity(double scaleX, double scaleY, double scaleZ, Density input) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ShellDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ShellDensity.java index 04fa797a..7c4e47ac 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ShellDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ShellDensity.java @@ -16,6 +16,7 @@ public class ShellDensity extends Density { @Nonnull private final Vector3d axis; private final boolean isMirrored; + @Nonnull private final Vector3d rRadialVector; public ShellDensity(@Nonnull Double2DoubleFunction angleCurve, @Nonnull Double2DoubleFunction distanceCurve, @Nonnull Vector3d axis, boolean isMirrored) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SliderDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SliderDensity.java index 47dcf41d..43805139 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SliderDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SliderDensity.java @@ -11,7 +11,9 @@ public class SliderDensity extends Density { private final double slideZ; @Nullable private Density input; + @Nonnull private final Vector3d rChildPosition; + @Nonnull private final Density.Context rChildContext; public SliderDensity(double slideX, double slideY, double slideZ, Density input) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SwitchStateDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SwitchStateDensity.java index 576829c8..1b002ee3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SwitchStateDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/SwitchStateDensity.java @@ -9,6 +9,7 @@ public class SwitchStateDensity extends Density { @Nullable private Density input; private final int switchState; + @Nonnull private final Density.Context rChildContext; public SwitchStateDensity(Density input, int switchState) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/VectorWarpDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/VectorWarpDensity.java index 2b64a082..5768e2a2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/VectorWarpDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/VectorWarpDensity.java @@ -13,7 +13,9 @@ public class VectorWarpDensity extends Density { private final double warpFactor; @Nonnull private final Vector3d warpVector; + @Nonnull private final Vector3d rSamplePoint; + @Nonnull private final Density.Context rChildContext; public VectorWarpDensity(@Nonnull Density input, @Nonnull Density warpInput, double warpFactor, @Nonnull Vector3d warpVector) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/XOverrideDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/XOverrideDensity.java index 3eb1df41..f56b829b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/XOverrideDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/XOverrideDensity.java @@ -8,7 +8,9 @@ public class XOverrideDensity extends Density { @Nonnull private Density input; private final double value; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rChildPosition; public XOverrideDensity(@Nonnull Density input, double value) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YOverrideDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YOverrideDensity.java index 7091cf4c..e9ab8223 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YOverrideDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YOverrideDensity.java @@ -8,7 +8,9 @@ public class YOverrideDensity extends Density { @Nonnull private Density input; private final double value; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rChildPosition; public YOverrideDensity(@Nonnull Density input, double value) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YSampledDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YSampledDensity.java new file mode 100644 index 00000000..e76befe4 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/YSampledDensity.java @@ -0,0 +1,96 @@ +package com.hypixel.hytale.builtin.hytalegenerator.density.nodes; + +import com.hypixel.hytale.builtin.hytalegenerator.density.Density; +import com.hypixel.hytale.builtin.hytalegenerator.framework.math.Interpolation; +import com.hypixel.hytale.math.vector.Vector3d; +import javax.annotation.Nonnull; + +public class YSampledDensity extends Density { + @Nonnull + private Density input; + private final double sampleDistance; + private final double sampleDistanceInverse; + private final double sampleOffset; + private double value0; + private double value1; + private double y0; + private double y1; + private double x; + private double z; + private boolean isEmpty; + private final Vector3d rChildPosition; + private final Density.Context rChildContext; + + public YSampledDensity(@Nonnull Density input, double sampleDistance, double sampleOffset) { + assert sampleDistance > 0.0; + + this.input = input; + this.sampleDistance = sampleDistance; + this.sampleDistanceInverse = 1.0 / sampleDistance; + this.sampleOffset = sampleOffset; + this.isEmpty = true; + this.rChildPosition = new Vector3d(); + this.rChildContext = new Density.Context(); + } + + @Override + public double process(@Nonnull Density.Context context) { + if (context.position.x != this.x || context.position.z != this.z || this.isEmpty) { + double newY0 = this.toY0(context.position.y); + double newY1 = newY0 + this.sampleDistance; + this.rChildContext.assign(context); + this.rChildContext.position = this.rChildPosition; + this.y0 = newY0; + this.y1 = newY1; + this.rChildPosition.assign(context.position.x, this.y0, context.position.z); + this.value0 = this.input.process(this.rChildContext); + this.rChildPosition.assign(context.position.x, this.y1, context.position.z); + this.value1 = this.input.process(this.rChildContext); + this.isEmpty = false; + this.x = context.position.x; + this.z = context.position.z; + } else if (context.position.y < this.y0 || context.position.y > this.y1) { + double newY0 = this.toY0(context.position.y); + double newY1 = newY0 + this.sampleDistance; + this.rChildContext.assign(context); + this.rChildContext.position = this.rChildPosition; + if (newY0 == this.y1) { + this.y0 = this.y1; + this.value0 = this.value1; + } else { + this.y0 = newY0; + this.rChildPosition.assign(context.position.x, this.y0, context.position.z); + this.value0 = this.input.process(this.rChildContext); + } + + if (newY1 == this.y0) { + this.y1 = this.y0; + this.value1 = this.value0; + } else { + this.y1 = newY1; + this.rChildPosition.assign(context.position.x, this.y1, context.position.z); + this.value1 = this.input.process(this.rChildContext); + } + } + + double ratio = (context.position.y - this.y0) * this.sampleDistanceInverse; + return Interpolation.linear(this.value0, this.value1, ratio); + } + + private double toY0(double position) { + return this.toCellGrid(position) * this.sampleDistance + this.sampleOffset; + } + + private double toCellGrid(double position) { + return Math.floor((position - this.sampleOffset) * this.sampleDistanceInverse); + } + + @Override + public void setInputs(@Nonnull Density[] inputs) { + assert inputs.length != 0; + + assert inputs[0] != null; + + this.input = inputs[0]; + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ZOverrideDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ZOverrideDensity.java index 14374818..91bf732b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ZOverrideDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/ZOverrideDensity.java @@ -8,7 +8,9 @@ public class ZOverrideDensity extends Density { @Nonnull private Density input; private final double value; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rChildPosition; public ZOverrideDensity(@Nonnull Density input, double value) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/PositionsDensity.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/PositionsDensity.java index 8789e62f..e83d9bbe 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/PositionsDensity.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/PositionsDensity.java @@ -18,12 +18,19 @@ public class PositionsDensity extends Density { private final ReturnType returnType; @Nonnull private final DistanceFunction distanceFunction; + @Nonnull private final Vector3d rMin; + @Nonnull private final Vector3d rMax; + @Nonnull private final Vector3d rClosestPoint; + @Nonnull private final Vector3d rPreviousClosestPoint; + @Nonnull private final Vector3d rLocalPoint; + @Nonnull private final double[] rDistance; + @Nonnull private final boolean[] rHasClosestPoint; public PositionsDensity( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/CellValueReturnType.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/CellValueReturnType.java index 68dd802a..900e3f52 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/CellValueReturnType.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/CellValueReturnType.java @@ -9,6 +9,7 @@ public class CellValueReturnType extends ReturnType { @Nonnull private final Density sampleField; private final double defaultValue; + @Nonnull private final Density.Context rChildContext; public CellValueReturnType(@Nonnull Density sampleField, double defaultValue) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/DensityReturnType.java b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/DensityReturnType.java index dfd0538f..2f498d1c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/DensityReturnType.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/density/nodes/positions/returntypes/DensityReturnType.java @@ -20,7 +20,9 @@ public class DensityReturnType extends ReturnType { @Nonnull private final Density[] sampleDensities; private final boolean calculateDistanceFromWall; + @Nonnull private final Vector3d rScaledSamplePointClone; + @Nonnull private final Density.Context rChildContext; public DensityReturnType( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/DensityDelimitedEnvironmentProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/DensityDelimitedEnvironmentProvider.java index 751b4ae0..18845f7b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/DensityDelimitedEnvironmentProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/DensityDelimitedEnvironmentProvider.java @@ -12,6 +12,7 @@ public class DensityDelimitedEnvironmentProvider extends EnvironmentProvider { private final List> delimiters = new ArrayList<>(); @Nonnull private final Density density; + @Nonnull private final Density.Context rDensityContext; public DensityDelimitedEnvironmentProvider(@Nonnull List> delimiters, @Nonnull Density density) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/EnvironmentProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/EnvironmentProvider.java index f901e0e1..85c6cb6a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/EnvironmentProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/environmentproviders/EnvironmentProvider.java @@ -1,6 +1,5 @@ package com.hypixel.hytale.builtin.hytalegenerator.environmentproviders; -import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; @@ -14,16 +13,13 @@ public abstract class EnvironmentProvider { public static class Context { public Vector3i position; - public WorkerIndexer.Id workerId; - public Context(@Nonnull Vector3i position, WorkerIndexer.Id workerId) { + public Context(@Nonnull Vector3i position) { this.position = position; - this.workerId = workerId; } public Context(@Nonnull EnvironmentProvider.Context other) { this.position = other.position; - this.workerId = other.workerId; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/fields/FastNoiseLite.java b/src/com/hypixel/hytale/builtin/hytalegenerator/fields/FastNoiseLite.java index 1ab442ea..a999fd86 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/fields/FastNoiseLite.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/fields/FastNoiseLite.java @@ -28,6 +28,7 @@ public class FastNoiseLite { private FastNoiseLite.TransformType3D mWarpTransformType3D = FastNoiseLite.TransformType3D.DefaultOpenSimplex2; private float mDomainWarpAmp = 1.0F; private float mDomainWarpFreq = 1.0F; + @Nonnull private static final float[] Gradients2D = new float[]{ 0.13052619F, 0.9914449F, @@ -286,6 +287,7 @@ public class FastNoiseLite { -0.38268343F, 0.9238795F }; + @Nonnull private static final float[] RandVecs2D = new float[]{ -0.2700222F, -0.9628541F, @@ -800,6 +802,7 @@ public class FastNoiseLite { -0.774312F, -0.632804F }; + @Nonnull private static final float[] Gradients3D = new float[]{ 0.0F, 1.0F, @@ -1058,6 +1061,7 @@ public class FastNoiseLite { -1.0F, 0.0F }; + @Nonnull private static final float[] randVecs3D = new float[]{ -0.7292737F, -0.66184396F, @@ -3826,6 +3830,7 @@ public class FastNoiseLite { Distance2Mul, Distance2Div; + @Nonnull public static final Codec CODEC = new EnumCodec<>(FastNoiseLite.CellularReturnType.class); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/fields/noise/Simplex.java b/src/com/hypixel/hytale/builtin/hytalegenerator/fields/noise/Simplex.java index 31fb6afc..2cebcf84 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/fields/noise/Simplex.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/fields/noise/Simplex.java @@ -9,6 +9,7 @@ class Simplex { private static final double G3 = 0.16666666666666666; private static final double F4 = (Math.sqrt(5.0) - 1.0) / 4.0; private static final double G4 = (5.0 - Math.sqrt(5.0)) / 20.0; + @Nonnull private static final Simplex.Grad[] grad3 = new Simplex.Grad[]{ new Simplex.Grad(1.0, 1.0, 0.0), new Simplex.Grad(-1.0, 1.0, 0.0), @@ -23,6 +24,7 @@ class Simplex { new Simplex.Grad(0.0, 1.0, -1.0), new Simplex.Grad(0.0, -1.0, -1.0) }; + @Nonnull private static final Simplex.Grad[] grad4 = new Simplex.Grad[]{ new Simplex.Grad(0.0, 1.0, 1.0, 1.0), new Simplex.Grad(0.0, 1.0, 1.0, -1.0), @@ -57,6 +59,7 @@ class Simplex { new Simplex.Grad(-1.0, -1.0, 1.0, 0.0), new Simplex.Grad(-1.0, -1.0, -1.0, 0.0) }; + @Nonnull private static final short[] p = new short[]{ 151, 160, @@ -315,7 +318,9 @@ class Simplex { 156, 180 }; + @Nonnull private static final short[] perm = new short[512]; + @Nonnull private static final short[] permMod12 = new short[512]; private static int fastfloor(double x) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/framework/math/Interpolation.java b/src/com/hypixel/hytale/builtin/hytalegenerator/framework/math/Interpolation.java index 8cc1bbe5..7ba5bdfa 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/framework/math/Interpolation.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/framework/math/Interpolation.java @@ -1,11 +1,11 @@ package com.hypixel.hytale.builtin.hytalegenerator.framework.math; public class Interpolation { - public static double linear(double valueA, double valueB, double weight) { - if (!(weight < 0.0) && !(weight > 1.0)) { - return valueA * (1.0 - weight) + valueB * weight; + public static double linear(double value0, double value1, double weight) { + if (weight <= 0.0) { + return value0; } else { - throw new IllegalArgumentException("weight outside range"); + return weight >= 1.0 ? value1 : value0 * (1.0 - weight) + value1 * weight; } } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/material/FluidMaterial.java b/src/com/hypixel/hytale/builtin/hytalegenerator/material/FluidMaterial.java index bf10113e..09b595e1 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/material/FluidMaterial.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/material/FluidMaterial.java @@ -4,6 +4,7 @@ import java.util.Objects; import javax.annotation.Nonnull; public class FluidMaterial { + @Nonnull private final MaterialCache materialCache; public final int fluidId; public final byte fluidLevel; @@ -14,6 +15,7 @@ public class FluidMaterial { this.fluidLevel = fluidLevel; } + @Nonnull public MaterialCache getVoxelCache() { return this.materialCache; } @@ -34,6 +36,7 @@ public class FluidMaterial { return Objects.hash(blockId, fluidLevel); } + @Nonnull @Override public String toString() { return "FluidMaterial{materialCache=" + this.materialCache + ", fluidId=" + this.fluidId + ", fluidLevel=" + this.fluidLevel + "}"; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/material/Material.java b/src/com/hypixel/hytale/builtin/hytalegenerator/material/Material.java index 7e99f13b..0611c4c8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/material/Material.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/material/Material.java @@ -53,14 +53,17 @@ public final class Material { return Objects.hash(solid.blockId, fluid.fluidId); } + @Nonnull public SolidMaterial solid() { return this.solid; } + @Nonnull public FluidMaterial fluid() { return this.fluid; } + @Nonnull @Override public String toString() { return "Material[solid=" + this.solid + ", fluid=" + this.fluid + "]"; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/material/MaterialCache.java b/src/com/hypixel/hytale/builtin/hytalegenerator/material/MaterialCache.java index 7373d9c0..d5036d2f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/material/MaterialCache.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/material/MaterialCache.java @@ -4,32 +4,50 @@ import com.hypixel.hytale.builtin.hytalegenerator.LoggerUtil; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple; import com.hypixel.hytale.server.core.asset.type.fluid.Fluid; import com.hypixel.hytale.server.core.prefab.PrefabRotation; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; -import java.util.HashMap; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class MaterialCache { - private final Map hashToSolidMap = new HashMap<>(); - private final Map hashToFluidMap = new HashMap<>(); - private final Map hashToMaterialMap = new HashMap<>(); + @Nonnull + private final ConcurrentHashMap hashToSolidMap = new ConcurrentHashMap<>(); + @Nonnull + private final ConcurrentHashMap hashToFluidMap = new ConcurrentHashMap<>(); + @Nonnull + private final ConcurrentHashMap hashToMaterialMap = new ConcurrentHashMap<>(); + @Nullable public final SolidMaterial EMPTY_AIR = this.getSolidMaterial("Empty_Air"); + @Nullable public final SolidMaterial ROCK_STONE = this.getSolidMaterial("Rock_Stone"); + @Nullable public final SolidMaterial SOIL_GRASS = this.getSolidMaterial("Soil_Grass"); + @Nullable public final SolidMaterial SOIL_DIRT = this.getSolidMaterial("Soil_Dirt"); + @Nullable public final SolidMaterial SOIL_MUD = this.getSolidMaterial("Soil_Mud"); + @Nullable public final SolidMaterial SOIL_NEEDLES = this.getSolidMaterial("Soil_Needles"); + @Nullable public final SolidMaterial SOIL_GRAVEL = this.getSolidMaterial("Soil_Gravel"); + @Nullable public final SolidMaterial ROCK_QUARTZITE = this.getSolidMaterial("Rock_Quartzite"); + @Nullable public final SolidMaterial ROCK_MARBLE = this.getSolidMaterial("Rock_Marble"); + @Nullable public final SolidMaterial ROCK_SHALE = this.getSolidMaterial("Rock_Shale"); + @Nullable public final SolidMaterial FLUID_WATER = this.getSolidMaterial("Fluid_Water"); + @Nullable public final SolidMaterial BEDROCK = this.getSolidMaterial("Rock_Volcanic"); + @Nullable public final FluidMaterial UNKNOWN_FLUID = this.getFluidMaterial(Fluid.UNKNOWN.getId()); + @Nullable public final FluidMaterial EMPTY_FLUID = this.getFluidMaterial(Fluid.EMPTY.getId()); + @Nonnull public final Material EMPTY = this.getMaterial(this.EMPTY_AIR, this.EMPTY_FLUID); @Nonnull @@ -45,6 +63,7 @@ public class MaterialCache { } } + @Nullable public FluidMaterial getFluidMaterial(@Nonnull String fluidString) { int fluidId = 0; Fluid key = Fluid.getAssetMap().getAsset(fluidString); @@ -58,6 +77,7 @@ public class MaterialCache { } } + @Nullable public FluidMaterial getFluidMaterial(int fluidId, byte level) { Fluid key = Fluid.getAssetMap().getAsset(fluidId); if (key == null) { @@ -68,6 +88,7 @@ public class MaterialCache { } } + @Nonnull private FluidMaterial getOrRegisterFluid(int fluidId, byte level) { int hash = FluidMaterial.contentHash(fluidId, level); FluidMaterial fluidMaterial = this.hashToFluidMap.get(hash); @@ -80,7 +101,8 @@ public class MaterialCache { } } - public SolidMaterial getSolidMaterial(@Nonnull String solidString) { + @Nullable + public SolidMaterial getSolidMaterial(@Nonnull String solidString, @Nonnull RotationTuple rotation) { int blockId = 0; BlockType key = BlockType.fromString(solidString); if (key != null) { @@ -91,19 +113,25 @@ public class MaterialCache { System.out.println("Attempted to register an invalid block ID " + blockId + ": using Empty_Air instead."); return this.EMPTY_AIR; } else { - int hash = SolidMaterial.contentHash(blockId, 0, 0, 0, null); + int hash = SolidMaterial.contentHash(blockId, 0, rotation.index(), 0, null); SolidMaterial solidMaterial = this.hashToSolidMap.get(hash); if (solidMaterial != null) { return solidMaterial; } else { - solidMaterial = new SolidMaterial(this, blockId, 0, 0, 0, null); + solidMaterial = new SolidMaterial(this, blockId, 0, rotation.index(), 0, null); this.hashToSolidMap.put(blockId, solidMaterial); return solidMaterial; } } } - public SolidMaterial getSolidMaterialRotatedY(@Nonnull SolidMaterial solidMaterial, Rotation rotation) { + @Nullable + public SolidMaterial getSolidMaterial(@Nonnull String solidString) { + return this.getSolidMaterial(solidString, RotationTuple.NONE); + } + + @Nonnull + public SolidMaterial getSolidMaterialRotatedY(@Nonnull SolidMaterial solidMaterial, @Nonnull Rotation rotation) { PrefabRotation prefabRotation = PrefabRotation.fromRotation(rotation); int rotatedRotation = prefabRotation.getRotation(solidMaterial.rotation); int rotatedFiller = prefabRotation.getFiller(solidMaterial.filler); @@ -118,6 +146,7 @@ public class MaterialCache { } } + @Nullable public SolidMaterial getSolidMaterial(int blockId, int support, int rotation, int filler, @Nullable Holder holder) { if (BlockType.getAssetMap().getAsset(blockId) == null) { System.out.println("Attempted to register an invalid block ID " + blockId + ": using Empty_Air instead."); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/material/SolidMaterial.java b/src/com/hypixel/hytale/builtin/hytalegenerator/material/SolidMaterial.java index e8c15bc6..6df79e5a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/material/SolidMaterial.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/material/SolidMaterial.java @@ -7,6 +7,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class SolidMaterial { + @Nonnull private final MaterialCache materialCache; public final int blockId; public final int support; @@ -45,6 +46,7 @@ public class SolidMaterial { return Objects.hash(blockId, support, rotation, filler, holder); } + @Nonnull @Override public String toString() { return "SolidMaterial{materialCache=" diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/FieldFunctionMaterialProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/FieldFunctionMaterialProvider.java index aa4ba091..908a2bda 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/FieldFunctionMaterialProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/FieldFunctionMaterialProvider.java @@ -10,6 +10,7 @@ public class FieldFunctionMaterialProvider extends MaterialProvider { private final Density density; @Nonnull private final FieldFunctionMaterialProvider.FieldDelimiter[] fieldDelimiters; + @Nonnull private final Density.Context rDensityContext; public FieldFunctionMaterialProvider(@Nonnull Density density, @Nonnull List> delimiters) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/HorizontalMaterialProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/HorizontalMaterialProvider.java index 7f3ef813..f4ce5704 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/HorizontalMaterialProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/HorizontalMaterialProvider.java @@ -1,18 +1,15 @@ package com.hypixel.hytale.builtin.hytalegenerator.materialproviders; -import com.hypixel.hytale.builtin.hytalegenerator.materialproviders.functions.DoubleFunctionXZ; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class HorizontalMaterialProvider extends MaterialProvider { @Nonnull private final MaterialProvider materialProvider; - @Nonnull - private final DoubleFunctionXZ topY; - @Nonnull - private final DoubleFunctionXZ bottomY; + private double topY; + private double bottomY; - public HorizontalMaterialProvider(@Nonnull MaterialProvider materialProvider, @Nonnull DoubleFunctionXZ topY, @Nonnull DoubleFunctionXZ bottomY) { + public HorizontalMaterialProvider(@Nonnull MaterialProvider materialProvider, double topY, double bottomY) { this.materialProvider = materialProvider; this.topY = topY; this.bottomY = bottomY; @@ -21,8 +18,6 @@ public class HorizontalMaterialProvider extends MaterialProvider { @Nullable @Override public V getVoxelTypeAt(@Nonnull MaterialProvider.Context context) { - double topY = this.topY.apply(context.position.x, context.position.z); - double bottomY = this.bottomY.apply(context.position.x, context.position.z); - return !(context.position.y >= topY) && !(context.position.y < bottomY) ? this.materialProvider.getVoxelTypeAt(context) : null; + return !(context.position.y >= this.topY) && !(context.position.y < this.bottomY) ? this.materialProvider.getVoxelTypeAt(context) : null; } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/SpaceAndDepthMaterialProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/SpaceAndDepthMaterialProvider.java index b88e2670..2cc550f7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/SpaceAndDepthMaterialProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/SpaceAndDepthMaterialProvider.java @@ -102,6 +102,7 @@ public class SpaceAndDepthMaterialProvider extends MaterialProvider { DEPTH_INTO_FLOOR, DEPTH_INTO_CEILING; + @Nonnull public static final Codec CODEC = new EnumCodec<>( SpaceAndDepthMaterialProvider.LayerContextType.class, EnumCodec.EnumStyle.LEGACY ); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/AlwaysTrueCondition.java b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/AlwaysTrueCondition.java index 986648de..ce9c0165 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/AlwaysTrueCondition.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/AlwaysTrueCondition.java @@ -1,8 +1,10 @@ package com.hypixel.hytale.builtin.hytalegenerator.materialproviders.spaceanddepth.conditions; import com.hypixel.hytale.builtin.hytalegenerator.materialproviders.spaceanddepth.SpaceAndDepthMaterialProvider; +import javax.annotation.Nonnull; public class AlwaysTrueCondition implements SpaceAndDepthMaterialProvider.Condition { + @Nonnull public static final AlwaysTrueCondition INSTANCE = new AlwaysTrueCondition(); private AlwaysTrueCondition() { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/ConditionParameter.java b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/ConditionParameter.java index e9e1ab99..7946448f 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/ConditionParameter.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/conditions/ConditionParameter.java @@ -2,10 +2,12 @@ package com.hypixel.hytale.builtin.hytalegenerator.materialproviders.spaceanddep import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.codecs.EnumCodec; +import javax.annotation.Nonnull; public enum ConditionParameter { SPACE_ABOVE_FLOOR, SPACE_BELOW_CEILING; + @Nonnull public static final Codec CODEC = new EnumCodec<>(ConditionParameter.class, EnumCodec.EnumStyle.LEGACY); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/layers/NoiseThickness.java b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/layers/NoiseThickness.java index 93982e87..dd806b37 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/layers/NoiseThickness.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/materialproviders/spaceanddepth/layers/NoiseThickness.java @@ -11,6 +11,7 @@ public class NoiseThickness extends SpaceAndDepthMaterialProvider.Layer { private final Density density; @Nullable private final MaterialProvider materialProvider; + @Nonnull private final Density.Context rDensityContext; public NoiseThickness(@Nonnull Density density, @Nullable MaterialProvider materialProvider) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/NStagedChunkGenerator.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/NStagedChunkGenerator.java index f2b109c7..950d898d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/NStagedChunkGenerator.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/NStagedChunkGenerator.java @@ -21,6 +21,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.newsystem.stages.NStage; import com.hypixel.hytale.builtin.hytalegenerator.newsystem.views.NEntityBufferView; import com.hypixel.hytale.builtin.hytalegenerator.newsystem.views.NPixelBufferView; import com.hypixel.hytale.builtin.hytalegenerator.newsystem.views.NVoxelBufferView; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.math.util.ChunkUtil; @@ -46,12 +47,15 @@ import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import javax.annotation.Nonnull; +import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class NStagedChunkGenerator implements ChunkGenerator { public static final int WORLD_MIN_Y_BUFFER_GRID = 0; public static final int WORLD_MAX_Y_BUFFER_GRID = 40; public static final int WORLD_HEIGHT_BUFFER_GRID = 40; + @Nonnull public static final Bounds3i CHUNK_BOUNDS_BUFFER_GRID = new Bounds3i(Vector3i.ZERO, new Vector3i(4, 40, 4)); + @Nonnull public static final Bounds3i SINGLE_BUFFER_TILE_BOUNDS_BUFFER_GRID = new Bounds3i( new Vector3i(0, 0, 0), new Vector3i(NVoxelBuffer.SIZE.x, 320, NVoxelBuffer.SIZE.x) ); @@ -65,6 +69,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { private ExecutorService concurrentExecutor; private MaterialCache materialCache; private WorkerIndexer workerIndexer; + private PositionProvider spawnPositions; private TimeInstrument timeInstrument; private Set statsCheckpoints; private int generatedChunkCount; @@ -74,6 +79,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { private NStagedChunkGenerator() { } + @NonNullDecl @Override public GeneratedChunk generate(@Nonnull ChunkRequest.Arguments arguments) { if (arguments.stillNeeded() != null && !arguments.stillNeeded().test(arguments.index())) { @@ -212,6 +218,12 @@ public class NStagedChunkGenerator implements ChunkGenerator { } } + @NonNullDecl + @Override + public PositionProvider getSpawnPositions() { + return this.spawnPositions; + } + @Nonnull private Map createAccesses(@Nonnull Bounds3i localChunkBounds_bufferGrid) { Map accessMap = new HashMap<>(); @@ -343,12 +355,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { world_voxelGrid.y = y_voxelGrid + chunkBounds_voxelGrid.min.y; world_voxelGrid.z = z_voxelGrid + chunkBounds_voxelGrid.min.z; Material material = materialVoxelSpace.getContent(world_voxelGrid); - if (material == null) { - blockChunk.setBlock(x_voxelGrid, y_voxelGrid, z_voxelGrid, 0, 0, 0); - fluidSection.setFluid( - x_voxelGrid, sectionY, z_voxelGrid, this.materialCache.EMPTY_FLUID.fluidId, this.materialCache.EMPTY_FLUID.fluidLevel - ); - } else { + if (material != null && !material.equals(this.materialCache.EMPTY)) { blockChunk.setBlock( x_voxelGrid, y_voxelGrid, z_voxelGrid, material.solid().blockId, material.solid().rotation, material.solid().filler ); @@ -450,6 +457,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { world_voxelGrid.x = x_voxelGrid_final + chunkBounds_voxelGrid.min.x; world_voxelGrid.y = y_voxelGrid + chunkBounds_voxelGrid.min.y; world_voxelGrid.z = z_voxelGrid_final + chunkBounds_voxelGrid.min.z; + world_voxelGrid.dropHash(); Integer environment = environmentVoxelSpace.getContent(world_voxelGrid); assert environment != null; @@ -465,7 +473,12 @@ public class NStagedChunkGenerator implements ChunkGenerator { } } - return FutureUtils.allOf(futures).thenRun(() -> bulkWriter.write(generatedChunk.getBlockChunk().getEnvironmentChunk())).handle((r, e) -> { + TimeInstrument.Probe timeProbe = transfer_timeProbe.createProbe("Environment Write"); + return FutureUtils.allOf(futures).thenRun(() -> { + timeProbe.start(); + bulkWriter.write(generatedChunk.getBlockChunk().getEnvironmentChunk()); + timeProbe.start(); + }).handle((r, e) -> { if (e == null) { return (Void)r; } else { @@ -573,15 +586,19 @@ public class NStagedChunkGenerator implements ChunkGenerator { } public static class Builder { + @Nonnull public final NParametrizedBufferType MATERIAL_OUTPUT_BUFFER_TYPE = new NParametrizedBufferType( "MaterialResult", -1, NVoxelBuffer.class, Material.class, () -> new NVoxelBuffer<>(Material.class) ); + @Nonnull public final NParametrizedBufferType TINT_OUTPUT_BUFFER_TYPE = new NParametrizedBufferType( "TintResult", -3, NSimplePixelBuffer.class, Integer.class, () -> new NSimplePixelBuffer<>(Integer.class) ); + @Nonnull public final NParametrizedBufferType ENVIRONMENT_OUTPUT_BUFFER_TYPE = new NParametrizedBufferType( "EnvironmentResult", -4, NVoxelBuffer.class, Integer.class, () -> new NVoxelBuffer<>(Integer.class) ); + @Nonnull public final NBufferType ENTITY_OUTPUT_BUFFER_TYPE = new NBufferType("EntityResult", -5, NEntityBuffer.class, NEntityBuffer::new); private List stages = new ArrayList<>(); private ExecutorService concurrentExecutor; @@ -589,6 +606,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { private WorkerIndexer workerIndexer; private String statsHeader; private Set statsCheckpoints; + private PositionProvider spawnPositions; private double bufferCapacityFactor; private double targetViewDistance; private double targetPlayerCount; @@ -605,6 +623,8 @@ public class NStagedChunkGenerator implements ChunkGenerator { assert this.statsCheckpoints != null; + assert this.spawnPositions != null; + NStagedChunkGenerator instance = new NStagedChunkGenerator(); instance.materialOutput_bufferType = this.MATERIAL_OUTPUT_BUFFER_TYPE; instance.tintOutput_bufferType = this.TINT_OUTPUT_BUFFER_TYPE; @@ -639,6 +659,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { instance.timeInstrument = new TimeInstrument(this.statsHeader); instance.statsCheckpoints = new HashSet<>(this.statsCheckpoints); instance.generatedChunkCount = 0; + instance.spawnPositions = this.spawnPositions; return instance; } @@ -649,6 +670,12 @@ public class NStagedChunkGenerator implements ChunkGenerator { return this; } + @Nonnull + public NStagedChunkGenerator.Builder withSpawnPositions(@Nonnull PositionProvider spawnPositions) { + this.spawnPositions = spawnPositions; + return this; + } + @Nonnull public NStagedChunkGenerator.Builder withConcurrentExecutor(@Nonnull ExecutorService executor, @Nonnull WorkerIndexer workerIndexer) { this.concurrentExecutor = executor; @@ -829,6 +856,7 @@ public class NStagedChunkGenerator implements ChunkGenerator { return allBufferTypes; } + @Nonnull private static Bounds3i getEncompassingBounds(@Nonnull Collection set) { Bounds3i out = new Bounds3i(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/NBufferBundle.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/NBufferBundle.java index 57282add..26e8a53b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/NBufferBundle.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/NBufferBundle.java @@ -17,6 +17,7 @@ import java.util.Map.Entry; import javax.annotation.Nonnull; public class NBufferBundle implements MemInstrument { + @Nonnull private final Map grids = new HashMap<>(); @Nonnull @@ -90,8 +91,11 @@ public class NBufferBundle implements MemInstrument { } public static class Access implements MemInstrument { + @Nonnull private final NBufferBundle.Grid grid; + @Nonnull private final Bounds3i bounds_bufferGrid; + @Nonnull private final NBufferBundle.Grid.TrackedBuffer[] buffers; private boolean isClosed; @@ -174,7 +178,9 @@ public class NBufferBundle implements MemInstrument { } public static class View { + @Nonnull private final NBufferBundle.Access access; + @Nonnull private final Bounds3i bounds_bufferGrid; private View(@Nonnull NBufferBundle.Access access, @Nonnull Bounds3i bounds_bufferGrid) { @@ -201,10 +207,14 @@ public class NBufferBundle implements MemInstrument { } public static class Grid implements MemInstrument { + @Nonnull private final NBufferType bufferType; + @Nonnull private final Map buffers; + @Nonnull private final Deque oldestColumnEntryDeque_bufferGrid; private final int capacity; + @Nonnull private final List accessors; private Grid(@Nonnull NBufferType bufferType, int capacity) { @@ -361,6 +371,7 @@ public class NBufferBundle implements MemInstrument { } public static class MemoryReport { + @Nonnull public final List gridEntries = new ArrayList<>(); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NCountedPixelBuffer.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NCountedPixelBuffer.java index d383caf8..25eeafd0 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NCountedPixelBuffer.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NCountedPixelBuffer.java @@ -12,7 +12,9 @@ import javax.annotation.Nullable; public class NCountedPixelBuffer extends NPixelBuffer { public static final int BUFFER_SIZE_BITS = 3; + @Nonnull public static final Vector3i SIZE_VOXEL_GRID = new Vector3i(8, 1, 8); + @Nonnull public static final Bounds3i BOUNDS_VOXEL_GRID = new Bounds3i(Vector3i.ZERO, SIZE_VOXEL_GRID); @Nonnull private final Class pixelType; @@ -128,9 +130,11 @@ public class NCountedPixelBuffer extends NPixelBuffer { } public static class CountedArrayContents implements MemInstrument { + @Nonnull private final T[] array = (T[])(new Object[NCountedPixelBuffer.SIZE_VOXEL_GRID.x * NCountedPixelBuffer.SIZE_VOXEL_GRID.y * NCountedPixelBuffer.SIZE_VOXEL_GRID.z]); + @Nonnull private final List allBiomes = new ArrayList<>(1); public void copyFrom(@Nonnull NCountedPixelBuffer.CountedArrayContents countedArrayContents) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NEntityBuffer.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NEntityBuffer.java index e682dc18..ac600406 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NEntityBuffer.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NEntityBuffer.java @@ -6,8 +6,10 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class NEntityBuffer extends NBuffer { + @Nullable private List entities = null; private boolean isReference = false; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NPixelBuffer.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NPixelBuffer.java index fe3b4fe0..c1c4338a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NPixelBuffer.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NPixelBuffer.java @@ -6,6 +6,7 @@ import javax.annotation.Nullable; public abstract class NPixelBuffer extends NBuffer { public static final int BUFFER_SIZE_BITS = 3; + @Nonnull public static final Vector3i SIZE = new Vector3i(8, 1, 8); @Nullable diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NSimplePixelBuffer.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NSimplePixelBuffer.java index 320ef12d..c3f59839 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NSimplePixelBuffer.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NSimplePixelBuffer.java @@ -9,6 +9,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class NSimplePixelBuffer extends NPixelBuffer { + @Nonnull private static final Bounds3i bounds = new Bounds3i(Vector3i.ZERO, SIZE); @Nonnull private final Class pixelType; @@ -112,6 +113,7 @@ public class NSimplePixelBuffer extends NPixelBuffer { } public static class ArrayContents implements MemInstrument { + @Nonnull private final T[] array = (T[])(new Object[NPixelBuffer.SIZE.x * NPixelBuffer.SIZE.y * NPixelBuffer.SIZE.z]); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NVoxelBuffer.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NVoxelBuffer.java index 52333d3c..ec8e3461 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NVoxelBuffer.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/NVoxelBuffer.java @@ -10,7 +10,9 @@ import javax.annotation.Nullable; public class NVoxelBuffer extends NBuffer { public static final int BUFFER_SIZE_BITS = 3; + @Nonnull public static final Vector3i SIZE = new Vector3i(8, 8, 8); + @Nonnull private static final Bounds3i bounds = new Bounds3i(Vector3i.ZERO, SIZE); @Nonnull private final Class voxelType; @@ -135,6 +137,7 @@ public class NVoxelBuffer extends NBuffer { } public static class ArrayContents implements MemInstrument { + @Nonnull private final T[] array = (T[])(new Object[NVoxelBuffer.SIZE.x * NVoxelBuffer.SIZE.y * NVoxelBuffer.SIZE.z]); @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/type/NBufferType.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/type/NBufferType.java index 23946ac2..89a71566 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/type/NBufferType.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/bufferbundle/buffers/type/NBufferType.java @@ -5,9 +5,12 @@ import java.util.function.Supplier; import javax.annotation.Nonnull; public class NBufferType { + @Nonnull public final Class bufferClass; public final int index; + @Nonnull public final Supplier bufferSupplier; + @Nonnull public final String name; public NBufferType(@Nonnull String name, int index, @Nonnull Class bufferClass, @Nonnull Supplier bufferSupplier) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/containers/FloatContainer3d.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/containers/FloatContainer3d.java index bdfff465..2a616e06 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/containers/FloatContainer3d.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/containers/FloatContainer3d.java @@ -6,8 +6,11 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class FloatContainer3d { + @Nonnull private final Bounds3i bounds_voxelGrid; + @Nonnull private final Vector3i size_voxelGrid; + @Nonnull private final float[] data; private final float outOfBoundsValue; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/performanceinstruments/TimeInstrument.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/performanceinstruments/TimeInstrument.java index d41eaaae..81033daf 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/performanceinstruments/TimeInstrument.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/performanceinstruments/TimeInstrument.java @@ -44,12 +44,11 @@ public class TimeInstrument { @Nonnull private String toString(int indentation, @Nonnull TimeInstrument.Probe probe) { - long ms = probe.getTotalTime() / this.sampleCount; - ms /= 1000000L; + long ns = probe.getTotalTime() / this.sampleCount; StringBuilder s = new StringBuilder(); s.append("\t".repeat(indentation)); s.append(probe.getName()).append(": "); - s.append(Long.toString(ms)).append(" ms"); + s.append(LoggerUtil.nsToMsDecimal(ns)).append(" ms"); s.append("\n"); List childProbes = probe.getProbes(); @@ -61,6 +60,7 @@ public class TimeInstrument { } public static class Probe { + @Nonnull private final String name; private long startTime; private long totalTime; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeDistanceStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeDistanceStage.java index 40bc787b..149dfe0b 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeDistanceStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeDistanceStage.java @@ -21,15 +21,23 @@ public class NBiomeDistanceStage implements NStage { private static final double ORIGIN_REACH = 1.0; private static final double BUFFER_DIAGONAL_VOXEL_GRID = Math.sqrt(NPixelBuffer.SIZE.x * NPixelBuffer.SIZE.x + NPixelBuffer.SIZE.z * NPixelBuffer.SIZE.z); public static final double DEFAULT_DISTANCE_TO_BIOME_EDGE = Double.MAX_VALUE; + @Nonnull public static final Class biomeBufferClass = NCountedPixelBuffer.class; + @Nonnull public static final Class biomeClass = Integer.class; + @Nonnull public static final Class biomeDistanceBufferClass = NSimplePixelBuffer.class; + @Nonnull public static final Class biomeDistanceClass = NBiomeDistanceStage.BiomeDistanceEntries.class; + @Nonnull private final NParametrizedBufferType biomeInputBufferType; + @Nonnull private final NParametrizedBufferType biomeDistanceOutputBufferType; + @Nonnull private final String stageName; private final double maxDistance_voxelGrid; private final int maxDistance_bufferGrid; + @Nonnull private final Bounds3i inputBounds_bufferGrid; public NBiomeDistanceStage( @@ -240,6 +248,7 @@ public class NBiomeDistanceStage implements NStage { } public static class BiomeDistanceEntries { + @Nonnull public final List entries; public BiomeDistanceEntries(@Nonnull List entries) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeStage.java index 24ae1564..26959713 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NBiomeStage.java @@ -14,10 +14,15 @@ import java.util.Map; import javax.annotation.Nonnull; public class NBiomeStage implements NStage { + @Nonnull public static final Class bufferClass = NCountedPixelBuffer.class; + @Nonnull public static final Class biomeClass = Integer.class; + @Nonnull private final NParametrizedBufferType biomeOutputBufferType; + @Nonnull private final String stageName; + @Nonnull private final WorkerIndexer.Data worldStructure_workerData; public NBiomeStage( @@ -36,7 +41,7 @@ public class NBiomeStage implements NStage { for (int x = biomeSpace.minX(); x < biomeSpace.maxX(); x++) { for (int z = biomeSpace.minZ(); z < biomeSpace.maxZ(); z++) { - Integer biomeId = biomeMap.apply(x, z, WorkerIndexer.Id.TEMP_0); + Integer biomeId = biomeMap.apply(x, z, context.workerId); biomeSpace.set(biomeId, x, 0, z); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NEnvironmentStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NEnvironmentStage.java index a356c726..281abb1d 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NEnvironmentStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NEnvironmentStage.java @@ -20,14 +20,23 @@ import java.util.Map; import javax.annotation.Nonnull; public class NEnvironmentStage implements NStage { + @Nonnull public static final Class biomeBufferClass = NCountedPixelBuffer.class; + @Nonnull public static final Class biomeTypeClass = Integer.class; + @Nonnull public static final Class environmentBufferClass = NVoxelBuffer.class; + @Nonnull public static final Class environmentClass = Integer.class; + @Nonnull private final NParametrizedBufferType biomeInputBufferType; + @Nonnull private final NParametrizedBufferType environmentOutputBufferType; + @Nonnull private final Bounds3i inputBounds_bufferGrid; + @Nonnull private final String stageName; + @Nonnull private final WorkerIndexer.Data worldStructure_workerData; public NEnvironmentStage( @@ -55,7 +64,7 @@ public class NEnvironmentStage implements NStage { NVoxelBufferView environmentSpace = new NVoxelBufferView<>(environmentAccess, environmentClass); Bounds3i outputBounds_voxelGrid = environmentSpace.getBounds(); Vector3i position_voxelGrid = new Vector3i(outputBounds_voxelGrid.min); - EnvironmentProvider.Context tintContext = new EnvironmentProvider.Context(position_voxelGrid, WorkerIndexer.Id.TEMP_0); + EnvironmentProvider.Context environmentContext = new EnvironmentProvider.Context(position_voxelGrid); Registry biomeRegistry = this.worldStructure_workerData.get(context.workerId).getBiomeRegistry(); for (position_voxelGrid.x = outputBounds_voxelGrid.min.x; position_voxelGrid.x < outputBounds_voxelGrid.max.x; position_voxelGrid.x++) { @@ -71,7 +80,8 @@ public class NEnvironmentStage implements NStage { EnvironmentProvider environmentProvider = biome.getEnvironmentProvider(); for (position_voxelGrid.y = outputBounds_voxelGrid.min.y; position_voxelGrid.y < outputBounds_voxelGrid.max.y; position_voxelGrid.y++) { - int environment = environmentProvider.getValue(tintContext); + position_voxelGrid.dropHash(); + int environment = environmentProvider.getValue(environmentContext); environmentSpace.set(environment, position_voxelGrid); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NPropStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NPropStage.java index ed409e67..bfb28f23 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NPropStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NPropStage.java @@ -37,23 +37,41 @@ import javax.annotation.Nullable; public class NPropStage implements NStage { public static final double DEFAULT_BACKGROUND_DENSITY = 0.0; + @Nonnull public static final Class biomeBufferClass = NCountedPixelBuffer.class; + @Nonnull public static final Class biomeClass = Integer.class; + @Nonnull public static final Class biomeDistanceBufferClass = NSimplePixelBuffer.class; + @Nonnull public static final Class biomeDistanceClass = NBiomeDistanceStage.BiomeDistanceEntries.class; + @Nonnull public static final Class materialBufferClass = NVoxelBuffer.class; + @Nonnull public static final Class materialClass = Material.class; + @Nonnull public static final Class entityBufferClass = NEntityBuffer.class; + @Nonnull private final NParametrizedBufferType biomeInputBufferType; + @Nonnull private final NParametrizedBufferType biomeDistanceInputBufferType; + @Nonnull private final NParametrizedBufferType materialInputBufferType; + @Nullable private final NBufferType entityInputBufferType; + @Nonnull private final NParametrizedBufferType materialOutputBufferType; + @Nonnull private final NBufferType entityOutputBufferType; + @Nonnull private final Bounds3i inputBounds_bufferGrid; + @Nonnull private final Bounds3i inputBounds_voxelGrid; + @Nonnull private final String stageName; + @Nonnull private final MaterialCache materialCache; + @Nonnull private final WorkerIndexer.Data worldStructure_workerData; private final int runtimeIndex; @@ -182,14 +200,12 @@ public class NPropStage implements NStage { Vector3i position2d_voxelGrid = positionInt_voxelGrid.clone(); position2d_voxelGrid.setY(0); double distanceToBiomeEdge = biomeDistanceSpace.getContent(position2d_voxelGrid).distanceToClosestOtherBiome(biomeIdAtPosition); - Prop prop = propField.getPropDistribution().propAt(position, WorkerIndexer.Id.TEMP_0, distanceToBiomeEdge); + Prop prop = propField.getPropDistribution().propAt(position, context.workerId, distanceToBiomeEdge); Bounds3i propWriteBounds = prop.getWriteBounds_voxelGrid().clone(); propWriteBounds.offset(positionInt_voxelGrid); if (propWriteBounds.intersects(localOutputBounds_voxelGrid)) { - ScanResult scanResult = prop.scan(positionInt_voxelGrid, materialInputSpace, WorkerIndexer.Id.TEMP_0); - Prop.Context propContext = new Prop.Context( - scanResult, materialOutputSpace, entityOutputSpace, WorkerIndexer.Id.TEMP_0, distanceToBiomeEdge - ); + ScanResult scanResult = prop.scan(positionInt_voxelGrid, materialInputSpace, context.workerId); + Prop.Context propContext = new Prop.Context(scanResult, materialOutputSpace, entityOutputSpace, context.workerId, distanceToBiomeEdge); prop.place(propContext); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTerrainStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTerrainStage.java index 5f57ac4c..1403ad83 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTerrainStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTerrainStage.java @@ -32,20 +32,34 @@ public class NTerrainStage implements NStage { public static final double ORIGIN_REACH = 1.0; public static final double ORIGIN_REACH_HALF = 0.5; public static final double QUARTER_PI = Math.PI / 4; + @Nonnull public static final Class biomeBufferClass = NCountedPixelBuffer.class; + @Nonnull public static final Class biomeClass = Integer.class; + @Nonnull public static final Class biomeDistanceBufferClass = NSimplePixelBuffer.class; + @Nonnull public static final Class biomeDistanceClass = NBiomeDistanceStage.BiomeDistanceEntries.class; + @Nonnull public static final Class materialBufferClass = NVoxelBuffer.class; + @Nonnull public static final Class materialClass = Material.class; + @Nonnull private final NParametrizedBufferType biomeInputBufferType; + @Nonnull private final NParametrizedBufferType biomeDistanceInputBufferType; + @Nonnull private final NParametrizedBufferType materialOutputBufferType; + @Nonnull private final Bounds3i inputBounds_bufferGrid; + @Nonnull private final String stageName; private final int maxInterpolationRadius_voxelGrid; + @Nonnull private final MaterialCache materialCache; + @Nonnull private final WorkerIndexer.Data densityContainers; + @Nonnull private final WorkerIndexer.Data worldStructure_workerdata; public NTerrainStage( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestPropStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestPropStage.java index 9d99d43b..fa6e87c3 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestPropStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestPropStage.java @@ -15,14 +15,22 @@ import java.util.Random; import javax.annotation.Nonnull; public class NTestPropStage implements NStage { + @Nonnull private static final Class bufferClass = NVoxelBuffer.class; + @Nonnull private static final Class solidMaterialClass = SolidMaterial.class; private final int CONTEXT_DEPENDENCY_RANGE_BUFFER_GRID = 0; + @Nonnull private final Bounds3i inputBounds_bufferGrid = new Bounds3i(new Vector3i(0, 0, 0), new Vector3i(1, 40, 1)); + @Nonnull private final NParametrizedBufferType inputBufferType; + @Nonnull private final NParametrizedBufferType outputBufferType; + @Nonnull private final SolidMaterial floorMaterial; + @Nonnull private final SolidMaterial anchorMaterial; + @Nonnull private final SolidMaterial propMaterial; public NTestPropStage( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestTerrainStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestTerrainStage.java index c641592f..02523cc2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestTerrainStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTestTerrainStage.java @@ -15,10 +15,15 @@ import java.util.Map; import javax.annotation.Nonnull; public class NTestTerrainStage implements NStage { + @Nonnull private static final Class bufferClass = NVoxelBuffer.class; + @Nonnull private static final Class solidMaterialClass = SolidMaterial.class; + @Nonnull private final NParametrizedBufferType outputBufferType; + @Nonnull private final SolidMaterial ground; + @Nonnull private final SolidMaterial empty; public NTestTerrainStage(@Nonnull NBufferType outputBufferType, @Nonnull SolidMaterial groundMaterial, @Nonnull SolidMaterial emptyMaterial) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTintStage.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTintStage.java index c0f39593..138a8ffe 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTintStage.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/stages/NTintStage.java @@ -19,14 +19,23 @@ import java.util.Map; import javax.annotation.Nonnull; public class NTintStage implements NStage { + @Nonnull public static final Class biomeBufferClass = NCountedPixelBuffer.class; + @Nonnull public static final Class biomeClass = Integer.class; + @Nonnull public static final Class tintBufferClass = NSimplePixelBuffer.class; + @Nonnull public static final Class tintClass = Integer.class; + @Nonnull private final NParametrizedBufferType biomeInputBufferType; + @Nonnull private final NParametrizedBufferType tintOutputBufferType; + @Nonnull private final Bounds3i inputBounds_bufferGrid; + @Nonnull private final String stageName; + @Nonnull private final WorkerIndexer.Data worldStructure_workerData; public NTintStage( @@ -56,7 +65,7 @@ public class NTintStage implements NStage { Registry biomeRegistry = this.worldStructure_workerData.get(context.workerId).getBiomeRegistry(); Vector3i position_voxelGrid = new Vector3i(outputBounds_voxelGrid.min); position_voxelGrid.setY(0); - TintProvider.Context tintContext = new TintProvider.Context(position_voxelGrid, WorkerIndexer.Id.TEMP_0); + TintProvider.Context tintContext = new TintProvider.Context(position_voxelGrid, context.workerId); for (position_voxelGrid.x = outputBounds_voxelGrid.min.x; position_voxelGrid.x < outputBounds_voxelGrid.max.x; position_voxelGrid.x++) { for (position_voxelGrid.z = outputBounds_voxelGrid.min.z; position_voxelGrid.z < outputBounds_voxelGrid.max.z; position_voxelGrid.z++) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NEntityBufferView.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NEntityBufferView.java index e64a2bbe..dc55636c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NEntityBufferView.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NEntityBufferView.java @@ -12,8 +12,11 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; public class NEntityBufferView implements EntityContainer { + @Nonnull private final NBufferBundle.Access.View access; + @Nonnull private final Bounds3i bounds_voxelGrid; + @Nonnull private final Bounds3i bounds_bufferGrid; public NEntityBufferView(@Nonnull NBufferBundle.Access.View bufferAccess) { @@ -46,6 +49,7 @@ public class NEntityBufferView implements EntityContainer { } } + @Nonnull private NEntityBuffer getBuffer_fromBufferGrid(@Nonnull Vector3i position_bufferGrid) { return (NEntityBuffer)this.access.getBuffer(position_bufferGrid).buffer(); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NPixelBufferView.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NPixelBufferView.java index 11d3c688..fb93425e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NPixelBufferView.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NPixelBufferView.java @@ -14,9 +14,13 @@ import javax.annotation.Nullable; public class NPixelBufferView implements VoxelSpace { public static final int Y_LEVEL_BUFFER_GRID = 0; public static final int Y_LEVEL_VOXEL_GRID = 0; + @Nonnull private final Class voxelType; + @Nonnull private final NBufferBundle.Access.View bufferAccess; + @Nonnull private final Bounds3i bounds_voxelGrid; + @Nonnull private final Vector3i size_voxelGrid; public NPixelBufferView(@Nonnull NBufferBundle.Access.View bufferAccess, @Nonnull Class pixelType) { @@ -74,6 +78,7 @@ public class NPixelBufferView implements VoxelSpace { return buffer.getPixelContent(positionInBuffer_voxelGrid); } + @Nonnull private NPixelBuffer getBuffer(@Nonnull Vector3i position_voxelGrid) { assert this.bounds_voxelGrid.contains(position_voxelGrid); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NVoxelBufferView.java b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NVoxelBufferView.java index 8b0f984d..e65ead86 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NVoxelBufferView.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/newsystem/views/NVoxelBufferView.java @@ -12,9 +12,13 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class NVoxelBufferView implements VoxelSpace { + @Nonnull private final Class voxelType; + @Nonnull private final NBufferBundle.Access.View bufferAccess; + @Nonnull private final Bounds3i bounds_voxelGrid; + @Nonnull private final Vector3i size_voxelGrid; public NVoxelBufferView(@Nonnull NBufferBundle.Access.View bufferAccess, @Nonnull Class voxelType) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CeilingPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CeilingPattern.java index fa99ba1c..f5e0823e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CeilingPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CeilingPattern.java @@ -11,7 +11,9 @@ public class CeilingPattern extends Pattern { private final Pattern airPattern; @Nonnull private final SpaceSize readSpaceSize; + @Nonnull private final Vector3i rCeilingPosition; + @Nonnull private final Pattern.Context rCeilingContext; public CeilingPattern(@Nonnull Pattern ceilingPattern, @Nonnull Pattern airPattern) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CuboidPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CuboidPattern.java index 0b59e5f7..70ba36b7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CuboidPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/CuboidPattern.java @@ -13,9 +13,13 @@ public class CuboidPattern extends Pattern { private final Vector3i max; @Nonnull private final SpaceSize readSpaceSize; + @Nonnull private final Vector3i rScanMin; + @Nonnull private final Vector3i rScanMax; + @Nonnull private final Vector3i rChildPosition; + @Nonnull private final Pattern.Context rChildContext; public CuboidPattern(@Nonnull Pattern subPattern, @Nonnull Vector3i min, @Nonnull Vector3i max) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/FieldFunctionPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/FieldFunctionPattern.java index 02052556..316f5d7c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/FieldFunctionPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/FieldFunctionPattern.java @@ -13,6 +13,7 @@ public class FieldFunctionPattern extends Pattern { private final SpaceSize readSpaceSize; @Nonnull private final List delimiters; + @Nonnull private final Density.Context rDensityContext; public FieldFunctionPattern(@Nonnull Density field) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/GapPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/GapPattern.java index ca57bc31..496228e0 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/GapPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/GapPattern.java @@ -19,7 +19,9 @@ public class GapPattern extends Pattern { private Pattern gapPattern; private Pattern anchorPattern; private SpaceSize readSpaceSize; + @Nonnull private final Vector3i rChildPosition; + @Nonnull private final Pattern.Context rChildContext; public GapPattern( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialPattern.java index f11956b6..05fe09ff 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialPattern.java @@ -6,7 +6,9 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class MaterialPattern extends Pattern { + @Nonnull private static final SpaceSize READ_SPACE_SIZE = new SpaceSize(new Vector3i(0, 0, 0), new Vector3i(1, 0, 1)); + @Nonnull private final Material material; public MaterialPattern(@Nonnull Material material) { @@ -23,6 +25,7 @@ public class MaterialPattern extends Pattern { } } + @Nonnull @Override public SpaceSize readSpace() { return READ_SPACE_SIZE.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialSetPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialSetPattern.java index 7692c2fe..87f90b9a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialSetPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/MaterialSetPattern.java @@ -7,7 +7,9 @@ import com.hypixel.hytale.math.vector.Vector3i; import javax.annotation.Nonnull; public class MaterialSetPattern extends Pattern { + @Nonnull private static final SpaceSize READ_SPACE_SIZE = new SpaceSize(new Vector3i(0, 0, 0), new Vector3i(1, 0, 1)); + @Nonnull private final MaterialSet materialSet; public MaterialSetPattern(@Nonnull MaterialSet materialSet) { @@ -25,6 +27,7 @@ public class MaterialSetPattern extends Pattern { } } + @Nonnull @Override public SpaceSize readSpace() { return READ_SPACE_SIZE.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/OffsetPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/OffsetPattern.java index 1198bdb1..352bde64 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/OffsetPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/OffsetPattern.java @@ -11,7 +11,9 @@ public class OffsetPattern extends Pattern { private final Vector3i offset; @Nonnull private final SpaceSize readSpaceSize; + @Nonnull private final Vector3i rChildPosition; + @Nonnull private final Pattern.Context rChildContext; public OffsetPattern(@Nonnull Pattern pattern, @Nonnull Vector3i offset) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/SurfacePattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/SurfacePattern.java index 7ee1a21b..f6f38c7e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/SurfacePattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/SurfacePattern.java @@ -20,7 +20,9 @@ public class SurfacePattern extends Pattern { private final List surfacePositions; @Nonnull private final List originPositions; + @Nonnull private final Vector3i rChildPosition; + @Nonnull private final Pattern.Context rChildContext; public SurfacePattern( diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/WallPattern.java b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/WallPattern.java index 39ff6716..d50f54e2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/WallPattern.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/patterns/WallPattern.java @@ -17,7 +17,9 @@ public class WallPattern extends Pattern { private final List directions; private final boolean matchAll; private final SpaceSize readSpaceSize; + @Nonnull private final Vector3i rWallPosition; + @Nonnull private final Pattern.Context rWallContext; public WallPattern(@Nonnull Pattern wallPattern, @Nonnull Pattern originPattern, @Nonnull List wallDirections, boolean matchAll) { @@ -93,6 +95,7 @@ public class WallPattern extends Pattern { E, W; + @Nonnull public static final Codec CODEC = new EnumCodec<>(WallPattern.WallDirection.class, EnumCodec.EnumStyle.LEGACY); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/Handle.java b/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/Handle.java index 130783dc..e4a0d058 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/Handle.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/Handle.java @@ -2,10 +2,12 @@ package com.hypixel.hytale.builtin.hytalegenerator.plugin; import com.hypixel.hytale.builtin.hytalegenerator.chunkgenerator.ChunkRequest; import com.hypixel.hytale.math.vector.Transform; +import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.server.core.universe.world.spawn.ISpawnProvider; import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedChunk; import com.hypixel.hytale.server.core.universe.world.worldgen.IWorldGen; import com.hypixel.hytale.server.core.universe.world.worldgen.WorldGenTimingsCollector; +import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.function.LongPredicate; @@ -26,6 +28,7 @@ public class Handle implements IWorldGen { this.seedOverride = seedOverride; } + @Nonnull @Override public CompletableFuture generate(int seed, long index, int x, int z, LongPredicate stillNeeded) { ChunkRequest.Arguments arguments = new ChunkRequest.Arguments(seed, index, x, z, stillNeeded); @@ -43,9 +46,20 @@ public class Handle implements IWorldGen { return this.profile; } + @Nonnull @Override public Transform[] getSpawnPoints(int seed) { - return new Transform[]{new Transform(0.0, 140.0, 0.0)}; + ChunkRequest.GeneratorProfile seededProfile = this.profile.clone(); + seededProfile.setSeed(seed); + int MAX_SPAWN_POINTS = 1000000; + List positions = this.plugin.getSpawnPositions(seededProfile, 1000000); + Transform[] positionsArray = new Transform[positions.size()]; + + for (int i = 0; i < positions.size(); i++) { + positionsArray[i] = new Transform(positions.get(i)); + } + + return positions.isEmpty() ? new Transform[]{new Transform(0.0, 140.0, 0.0)} : positionsArray; } @Nonnull diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HandleProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HandleProvider.java index 92995875..0656623c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HandleProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HandleProvider.java @@ -8,7 +8,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class HandleProvider implements IWorldGenProvider { + @Nonnull public static final String ID = "HytaleGenerator"; + @Nonnull public static final String DEFAULT_WORLD_STRUCTURE_NAME = "Default"; @Nonnull private final HytaleGenerator plugin; @@ -41,6 +43,7 @@ public class HandleProvider implements IWorldGenProvider { return this.seedOverride; } + @Nonnull @Override public IWorldGen getGenerator() throws WorldGenLoadException { return new Handle(this.plugin, new ChunkRequest.GeneratorProfile(this.worldStructureName, 0, this.worldCounter), this.seedOverride); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HytaleGenerator.java b/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HytaleGenerator.java index e547c5cf..ef14bc91 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HytaleGenerator.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/plugin/HytaleGenerator.java @@ -5,6 +5,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.LoggerUtil; import com.hypixel.hytale.builtin.hytalegenerator.PropField; import com.hypixel.hytale.builtin.hytalegenerator.assets.AssetManager; import com.hypixel.hytale.builtin.hytalegenerator.assets.SettingsAsset; +import com.hypixel.hytale.builtin.hytalegenerator.assets.positionproviders.PositionProviderAsset; import com.hypixel.hytale.builtin.hytalegenerator.assets.worldstructures.WorldStructureAsset; import com.hypixel.hytale.builtin.hytalegenerator.biome.Biome; import com.hypixel.hytale.builtin.hytalegenerator.chunkgenerator.ChunkGenerator; @@ -26,12 +27,15 @@ import com.hypixel.hytale.builtin.hytalegenerator.newsystem.stages.NPropStage; import com.hypixel.hytale.builtin.hytalegenerator.newsystem.stages.NStage; import com.hypixel.hytale.builtin.hytalegenerator.newsystem.stages.NTerrainStage; import com.hypixel.hytale.builtin.hytalegenerator.newsystem.stages.NTintStage; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; +import com.hypixel.hytale.builtin.hytalegenerator.referencebundle.ReferenceBundle; import com.hypixel.hytale.builtin.hytalegenerator.seed.SeedBox; import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer; import com.hypixel.hytale.builtin.hytalegenerator.worldstructure.WorldStructure; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.universe.world.events.RemoveWorldEvent; @@ -56,12 +60,16 @@ import javax.annotation.Nonnull; public class HytaleGenerator extends JavaPlugin { private AssetManager assetManager; private Runnable assetReloadListener; + @Nonnull private final Map generators = new HashMap<>(); + @Nonnull private final Semaphore chunkGenerationSemaphore = new Semaphore(1); private int concurrency; private ExecutorService mainExecutor; private ThreadPoolExecutor concurrentExecutor; private int worldCounter; + @Nonnull + public static Vector3d DEFAULT_SPAWN_POSITION = new Vector3d(0.0, 140.0, 0.0); @Override protected void start() { @@ -76,6 +84,39 @@ public class HytaleGenerator extends JavaPlugin { } } + @Nonnull + public List getSpawnPositions(@Nonnull ChunkRequest.GeneratorProfile profile, int maxPositionsCount) { + assert maxPositionsCount >= 0; + + if (profile.worldStructureName() == null) { + LoggerUtil.getLogger().warning("World Structure asset not loaded."); + return List.of(DEFAULT_SPAWN_POSITION); + } else { + WorldStructureAsset worldStructureAsset = this.assetManager.getWorldStructureAsset(profile.worldStructureName()); + if (worldStructureAsset == null) { + LoggerUtil.getLogger().warning("World Structure asset not found: " + profile.worldStructureName()); + return List.of(DEFAULT_SPAWN_POSITION); + } else { + SeedBox seed = new SeedBox(profile.seed()); + PositionProvider spawnPositionProvider = worldStructureAsset.getSpawnPositionsAsset() + .build(new PositionProviderAsset.Argument(seed, new ReferenceBundle(), WorkerIndexer.Id.MAIN)); + List positions = new ArrayList<>(maxPositionsCount); + PositionProvider.Context context = new PositionProvider.Context( + new Vector3d(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), + new Vector3d(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY), + position -> { + if (positions.size() < maxPositionsCount) { + positions.add(position); + } + }, + null + ); + spawnPositionProvider.positionsIn(context); + return positions; + } + } + } + @Nonnull public CompletableFuture submitChunkRequest(@Nonnull ChunkRequest request) { return CompletableFuture.supplyAsync(() -> { @@ -134,7 +175,7 @@ public class HytaleGenerator extends JavaPlugin { while (workerSession.hasNext()) { WorkerIndexer.Id workerId = workerSession.next(); CompletableFuture future = CompletableFuture.runAsync(() -> { - WorldStructure worldStructure = worldStructureAsset.build(new WorldStructureAsset.Argument(materialCache, seed)); + WorldStructure worldStructure = worldStructureAsset.build(new WorldStructureAsset.Argument(materialCache, seed, workerId)); worldStructure_workerData.set(workerId, worldStructure); }, this.concurrentExecutor).handle((r, e) -> { if (e == null) { @@ -263,6 +304,7 @@ public class HytaleGenerator extends JavaPlugin { .withMaterialCache(materialCache) .withConcurrentExecutor(this.concurrentExecutor, workerIndexer) .withBufferCapacity(bufferCapacityFactor, targetViewDistance, targetPlayerCount) + .withSpawnPositions(worldStructure_worker0.getSpawnPositions()) .build(); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BaseHeightPositionProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BaseHeightPositionProvider.java index 73b7c1a5..390bbb09 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BaseHeightPositionProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BaseHeightPositionProvider.java @@ -1,23 +1,20 @@ package com.hypixel.hytale.builtin.hytalegenerator.positionproviders; import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; import com.hypixel.hytale.math.vector.Vector3d; import javax.annotation.Nonnull; public class BaseHeightPositionProvider extends PositionProvider { @Nonnull - private final BiDouble2DoubleFunction baseHeightFunction; + private final double baseHeight; private final double maxYInput; private final double minYInput; @Nonnull private final PositionProvider positionProvider; - public BaseHeightPositionProvider( - @Nonnull BiDouble2DoubleFunction baseHeightFunction, @Nonnull PositionProvider positionProvider, double minYInput, double maxYInput - ) { + public BaseHeightPositionProvider(double baseHeight, @Nonnull PositionProvider positionProvider, double minYInput, double maxYInput) { maxYInput = Math.max(minYInput, maxYInput); - this.baseHeightFunction = baseHeightFunction; + this.baseHeight = baseHeight; this.positionProvider = positionProvider; this.maxYInput = maxYInput; this.minYInput = minYInput; @@ -28,7 +25,7 @@ public class BaseHeightPositionProvider extends PositionProvider { PositionProvider.Context childContext = new PositionProvider.Context(context); childContext.consumer = position -> { Vector3d offsetP = position.clone(); - offsetP.y = offsetP.y + this.baseHeightFunction.apply(position.x, position.z); + offsetP.y = offsetP.y + this.baseHeight; if (VectorUtil.isInside(offsetP, context.minInclusive, context.maxExclusive)) { context.consumer.accept(offsetP); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BoundPositionProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BoundPositionProvider.java new file mode 100644 index 00000000..3ce37b28 --- /dev/null +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/BoundPositionProvider.java @@ -0,0 +1,23 @@ +package com.hypixel.hytale.builtin.hytalegenerator.positionproviders; + +import com.hypixel.hytale.builtin.hytalegenerator.bounds.Bounds3d; +import javax.annotation.Nonnull; + +public class BoundPositionProvider extends PositionProvider { + @Nonnull + private final PositionProvider positionProvider; + private final Bounds3d bounds; + + public BoundPositionProvider(@Nonnull PositionProvider positionProvider, @Nonnull Bounds3d bounds) { + this.positionProvider = positionProvider; + this.bounds = bounds; + } + + @Override + public void positionsIn(@Nonnull PositionProvider.Context context) { + PositionProvider.Context childContext = new PositionProvider.Context(context); + childContext.minInclusive = this.bounds.min; + childContext.maxExclusive = this.bounds.max; + this.positionProvider.positionsIn(childContext); + } +} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/PositionProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/PositionProvider.java index 7f6a8eae..c60f344a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/PositionProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/PositionProvider.java @@ -18,6 +18,7 @@ public abstract class PositionProvider { } public static class Context { + @Nonnull public static final Consumer EMPTY_CONSUMER = p -> {}; public Vector3d minInclusive; public Vector3d maxExclusive; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SimpleHorizontalPositionProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SimpleHorizontalPositionProvider.java index 306f11a6..2623bfc6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SimpleHorizontalPositionProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SimpleHorizontalPositionProvider.java @@ -4,6 +4,7 @@ import com.hypixel.hytale.builtin.hytalegenerator.delimiters.RangeDouble; import javax.annotation.Nonnull; public class SimpleHorizontalPositionProvider extends PositionProvider { + @Nonnull private final RangeDouble rangeY; @Nonnull private final PositionProvider positionProvider; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SpherePositionProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SpherePositionProvider.java deleted file mode 100644 index f16b33c1..00000000 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/positionproviders/SpherePositionProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.hypixel.hytale.builtin.hytalegenerator.positionproviders; - -import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil; -import javax.annotation.Nonnull; - -public class SpherePositionProvider extends PositionProvider { - @Nonnull - private final PositionProvider positionProvider; - private final double range; - - public SpherePositionProvider(@Nonnull PositionProvider positionProvider, double range) { - this.positionProvider = positionProvider; - this.range = range; - } - - @Override - public void positionsIn(@Nonnull PositionProvider.Context context) { - PositionProvider.Context childContext = new PositionProvider.Context(context); - childContext.consumer = position -> { - double distance = position.length(); - if (VectorUtil.isInside(position, context.minInclusive, context.maxExclusive) && distance <= this.range) { - context.consumer.accept(position); - } - }; - this.positionProvider.positionsIn(childContext); - } -} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/BoxProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/BoxProp.java index 997c84b5..397cd3d2 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/BoxProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/BoxProp.java @@ -16,16 +16,24 @@ import javax.annotation.Nonnull; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class BoxProp extends Prop { + @Nonnull private final Vector3i range; + @Nonnull private final Material material; + @Nonnull private final Scanner scanner; + @Nonnull private final Pattern pattern; + @Nonnull private final ContextDependency contextDependency; + @Nonnull private final Bounds3i readBounds_voxelGrid; + @Nonnull private final Bounds3i writeBounds_voxelGrid; + @Nonnull private final Bounds3i boxBounds_voxelGrid; - public BoxProp(Vector3i range, @Nonnull Material material, @Nonnull Scanner scanner, @Nonnull Pattern pattern) { + public BoxProp(@Nonnull Vector3i range, @Nonnull Material material, @Nonnull Scanner scanner, @Nonnull Pattern pattern) { if (VectorUtil.isAnySmaller(range, new Vector3i())) { throw new IllegalArgumentException("negative range"); } else { @@ -44,6 +52,7 @@ public class BoxProp extends Prop { } } + @Nonnull public PositionListScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Scanner.Context scannerContext = new Scanner.Context(position, this.pattern, materialSpace, id); List validPositions = this.scanner.scan(scannerContext); @@ -80,6 +89,7 @@ public class BoxProp extends Prop { } } + @Nonnull @Override public ContextDependency getContextDependency() { return this.contextDependency.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/ClusterProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/ClusterProp.java index 72715fd5..5f6da4d5 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/ClusterProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/ClusterProp.java @@ -20,14 +20,22 @@ import javax.annotation.Nonnull; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class ClusterProp extends Prop { + @Nonnull private final Double2DoubleFunction weightCurve; + @Nonnull private final SeedGenerator seedGenerator; + @Nonnull private final WeightedMap propWeightedMap; private final int range; + @Nonnull private final ContextDependency contextDependency; + @Nonnull private final Pattern pattern; + @Nonnull private final Scanner scanner; + @Nonnull private final Bounds3i readBounds_voxelGrid; + @Nonnull private final Bounds3i writeBounds_voxelGrid; public ClusterProp( @@ -63,6 +71,7 @@ public class ClusterProp extends Prop { } } + @Nonnull public PositionListScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Scanner.Context scannerContext = new Scanner.Context(position, this.pattern, materialSpace, id); List validPositions = this.scanner.scan(scannerContext); @@ -106,6 +115,7 @@ public class ClusterProp extends Prop { } } + @Nonnull @Override public ContextDependency getContextDependency() { return this.contextDependency.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/ColumnProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/ColumnProp.java index 48b61bff..5acc4a38 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/ColumnProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/ColumnProp.java @@ -22,14 +22,23 @@ import javax.annotation.Nonnull; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class ColumnProp extends Prop { + @Nonnull private final int[] yPositions; + @Nonnull private final Material[] blocks0; + @Nonnull private final Material[] blocks90; + @Nonnull private final Material[] blocks180; + @Nonnull private final Material[] blocks270; + @Nonnull private final BlockMask blockMask; + @Nonnull private final Scanner scanner; + @Nonnull private final ContextDependency contextDependency; + @Nonnull private final Directionality directionality; @Nonnull private final Bounds3i readBounds_voxelGrid; @@ -74,6 +83,7 @@ public class ColumnProp extends Prop { } } + @Nonnull @Override public ScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Scanner.Context scannerContext = new Scanner.Context(position, this.directionality.getGeneralPattern(), materialSpace, id); @@ -126,6 +136,7 @@ public class ColumnProp extends Prop { } } + @Nonnull @Override public ContextDependency getContextDependency() { return this.contextDependency.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/DensityProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/DensityProp.java index 7cee9f06..9782c98a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/DensityProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/DensityProp.java @@ -18,15 +18,25 @@ import javax.annotation.Nonnull; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class DensityProp extends Prop { + @Nonnull private final Vector3i range; + @Nonnull private final Density density; + @Nonnull private final MaterialProvider materialProvider; + @Nonnull private final Scanner scanner; + @Nonnull private final Pattern pattern; + @Nonnull private final ContextDependency contextDependency; + @Nonnull private final BlockMask placementMask; + @Nonnull private final Material defaultMaterial; + @Nonnull private final Bounds3i readBounds_voxelGrid; + @Nonnull private final Bounds3i writeBounds_voxelGrid; public DensityProp( @@ -54,6 +64,7 @@ public class DensityProp extends Prop { this.writeBounds_voxelGrid = this.contextDependency.getWriteBounds_voxelGrid(); } + @Nonnull public PositionListScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Scanner.Context scannerContext = new Scanner.Context(position, this.pattern, materialSpace, id); List validPositions = this.scanner.scan(scannerContext); @@ -70,7 +81,7 @@ public class DensityProp extends Prop { } } - private void place(Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { + private void place(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Vector3i min = position.clone().add(-this.range.x, -this.range.y, -this.range.z); Vector3i max = position.clone().add(this.range.x, this.range.y, this.range.z); Vector3i writeMin = Vector3i.max(min, new Vector3i(materialSpace.minX(), materialSpace.minY(), materialSpace.minZ())); @@ -185,6 +196,7 @@ public class DensityProp extends Prop { } } + @Nonnull @Override public ContextDependency getContextDependency() { return this.contextDependency.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/OffsetProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/OffsetProp.java index ef87ac2a..9d3bb033 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/OffsetProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/OffsetProp.java @@ -10,10 +10,15 @@ import javax.annotation.Nonnull; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class OffsetProp extends Prop { + @Nonnull private final Vector3i offset_voxelGrid; + @Nonnull private final Prop childProp; + @Nonnull private final Bounds3i readBounds_voxelGrid; + @Nonnull private final Bounds3i writeBounds_voxelGrid; + @Nonnull private final ContextDependency contextDependency; public OffsetProp(@Nonnull Vector3i offset_voxelGrid, @Nonnull Prop childProp) { @@ -35,6 +40,7 @@ public class OffsetProp extends Prop { this.childProp.place(context); } + @Nonnull @Override public ContextDependency getContextDependency() { return this.contextDependency; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/ScanResult.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/ScanResult.java index 97a63466..622f969a 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/ScanResult.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/ScanResult.java @@ -3,6 +3,7 @@ package com.hypixel.hytale.builtin.hytalegenerator.props; import javax.annotation.Nonnull; public interface ScanResult { + @Nonnull ScanResult NONE = new ScanResult() { @Override public boolean isNegative() { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/directionality/OrthogonalDirection.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/directionality/OrthogonalDirection.java index d4632f0e..f3dd0e18 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/directionality/OrthogonalDirection.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/directionality/OrthogonalDirection.java @@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.hytalegenerator.props.directionality; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.codecs.EnumCodec; +import javax.annotation.Nonnull; public enum OrthogonalDirection { N, @@ -11,5 +12,6 @@ public enum OrthogonalDirection { U, D; + @Nonnull public static final Codec CODEC = new EnumCodec<>(OrthogonalDirection.class, EnumCodec.EnumStyle.LEGACY); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/filler/PondFillerProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/filler/PondFillerProp.java index a4de2e39..d05ef307 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/filler/PondFillerProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/filler/PondFillerProp.java @@ -24,14 +24,23 @@ public class PondFillerProp extends Prop { private static final int LEAKS = 16; private static final int SOLID = 256; private static final int STACKED = 4096; + @Nonnull private final Vector3i boundingMin; + @Nonnull private final Vector3i boundingMax; + @Nonnull private final MaterialProvider filledMaterialProvider; + @Nonnull private final MaterialSet solidSet; + @Nonnull private final Scanner scanner; + @Nonnull private final Pattern pattern; + @Nonnull private final ContextDependency contextDependency; + @Nonnull private final Bounds3i readBounds_voxelGrid; + @Nonnull private final Bounds3i writeBounds_voxelGrid; public PondFillerProp( @@ -57,6 +66,7 @@ public class PondFillerProp extends Prop { this.writeBounds_voxelGrid = this.contextDependency.getWriteBounds_voxelGrid(); } + @Nonnull public FillerPropScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Scanner.Context scannerContext = new Scanner.Context(position, this.pattern, materialSpace, id); List scanResults = this.scanner.scan(scannerContext); @@ -75,6 +85,7 @@ public class PondFillerProp extends Prop { } } + @Nonnull private List renderFluidBlocks(@Nonnull Vector3i origin, @Nonnull VoxelSpace materialSpace) { Vector3i min = this.boundingMin.clone().add(origin); Vector3i max = this.boundingMax.clone().add(origin); @@ -217,6 +228,7 @@ public class PondFillerProp extends Prop { } } + @Nonnull @Override public ContextDependency getContextDependency() { return this.contextDependency.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/MoldingDirection.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/MoldingDirection.java index d197d469..ae1de3e4 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/MoldingDirection.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/MoldingDirection.java @@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.hytalegenerator.props.prefab; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.codecs.EnumCodec; +import javax.annotation.Nonnull; public enum MoldingDirection { NONE, @@ -12,5 +13,6 @@ public enum MoldingDirection { EAST, WEST; + @Nonnull public static final Codec CODEC = new EnumCodec<>(MoldingDirection.class, EnumCodec.EnumStyle.LEGACY); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/PrefabProp.java b/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/PrefabProp.java index 9fdd2af1..08c20a4c 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/PrefabProp.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/props/prefab/PrefabProp.java @@ -46,18 +46,30 @@ import javax.annotation.Nullable; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class PrefabProp extends Prop { + @Nonnull private final WeightedMap> prefabPool; + @Nonnull private final Scanner scanner; private ContextDependency contextDependency; + @Nonnull private final MaterialCache materialCache; + @Nonnull private final SeedGenerator seedGenerator; + @Nonnull private final BlockMask materialMask; + @Nonnull private final Directionality directionality; + @Nonnull private final Bounds3i readBounds_voxelGrid; + @Nonnull private final Bounds3i writeBounds_voxelGrid; + @Nonnull private final Bounds3i prefabBounds_voxelGrid; + @Nonnull private final List childProps; + @Nonnull private final List childPositions; + @Nonnull private final Function> childPrefabLoader; private final Scanner moldingScanner; private final Pattern moldingPattern; @@ -157,7 +169,8 @@ public class PrefabProp extends Prop { this.prefabBounds_voxelGrid.max.assign(this.contextDependency.getWriteRange()).add(Vector3i.ALL_ONES); } - private Vector3i getWriteRange(PrefabBuffer.PrefabBufferAccessor prefabAccess) { + @Nonnull + private Vector3i getWriteRange(@Nonnull PrefabBuffer.PrefabBufferAccessor prefabAccess) { SpaceSize space = new SpaceSize(); for (PrefabRotation rotation : this.directionality.getPossibleRotations()) { @@ -171,6 +184,7 @@ public class PrefabProp extends Prop { return space.getRange(); } + @Nonnull @Override public ScanResult scan(@Nonnull Vector3i position, @Nonnull VoxelSpace materialSpace, @Nonnull WorkerIndexer.Id id) { Scanner.Context scannerContext = new Scanner.Context(position, this.directionality.getGeneralPattern(), materialSpace, id); @@ -207,14 +221,14 @@ public class PrefabProp extends Prop { } } - private PrefabBuffer pickPrefab(Random rand) { + private PrefabBuffer pickPrefab(@Nonnull Random rand) { List list = this.prefabPool.pick(rand); int randomIndex = rand.nextInt(list.size()); return list.get(randomIndex); } private void place( - RotatedPosition position, @Nonnull VoxelSpace materialSpace, @Nonnull EntityContainer entityBuffer, @Nonnull WorkerIndexer.Id id + @Nonnull RotatedPosition position, @Nonnull VoxelSpace materialSpace, @Nonnull EntityContainer entityBuffer, @Nonnull WorkerIndexer.Id id ) { Random random = new Random(this.seedGenerator.seedAt((long)position.x, (long)position.y, (long)position.z)); PrefabBufferCall callInstance = new PrefabBufferCall(random, position.rotation); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/BaseHeightReference.java b/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/BaseHeightReference.java deleted file mode 100644 index 0b851311..00000000 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/BaseHeightReference.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.hypixel.hytale.builtin.hytalegenerator.referencebundle; - -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; -import javax.annotation.Nonnull; - -public class BaseHeightReference extends Reference { - @Nonnull - private final BiDouble2DoubleFunction heightFunction; - - public BaseHeightReference(@Nonnull BiDouble2DoubleFunction heightFunction) { - this.heightFunction = heightFunction; - } - - @Nonnull - public BiDouble2DoubleFunction getHeightFunction() { - return this.heightFunction; - } -} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/Reference.java b/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/Reference.java deleted file mode 100644 index f3c6ba4e..00000000 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/Reference.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.hypixel.hytale.builtin.hytalegenerator.referencebundle; - -public class Reference { -} diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/ReferenceBundle.java b/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/ReferenceBundle.java index 22a8cc8a..34d144cb 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/ReferenceBundle.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/referencebundle/ReferenceBundle.java @@ -7,27 +7,23 @@ import javax.annotation.Nullable; public class ReferenceBundle { @Nonnull - private final Map dataLayerMap = new HashMap<>(); + private final Map dataLayerMap = new HashMap<>(); @Nonnull - private final Map layerTypeMap = new HashMap<>(); + private final Map> layerTypeMap = new HashMap<>(); - public void put(@Nonnull String name, @Nonnull Reference reference, @Nonnull Class type) { + public void put(@Nonnull String name, @Nonnull T reference, @Nonnull Class type) { this.dataLayerMap.put(name, reference); - this.layerTypeMap.put(name, type.getName()); + this.layerTypeMap.put(name, type); } @Nullable - public Reference getLayerWithName(@Nonnull String name) { - return this.dataLayerMap.get(name); - } + public T get(@Nonnull String name, @Nonnull Class type) { + Class storedType = this.layerTypeMap.get(name); - @Nullable - public T getLayerWithName(@Nonnull String name, @Nonnull Class type) { - String storedType = this.layerTypeMap.get(name); - if (storedType == null) { - return null; - } else { - return (T)(!storedType.equals(type.getName()) ? null : this.dataLayerMap.get(name)); - } + assert storedType != null; + + assert type.isAssignableFrom(storedType); + + return (T)this.dataLayerMap.get(name); } } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/AreaScanner.java b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/AreaScanner.java index 5aef4a10..ba1f004e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/AreaScanner.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/AreaScanner.java @@ -81,6 +81,7 @@ public class AreaScanner extends Scanner { CIRCLE, SQUARE; + @Nonnull public static final Codec CODEC = new EnumCodec<>(AreaScanner.ScanShape.class, EnumCodec.EnumStyle.LEGACY); } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnLinearScanner.java b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnLinearScanner.java index e0fc87ff..d25209e6 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnLinearScanner.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnLinearScanner.java @@ -1,32 +1,27 @@ package com.hypixel.hytale.builtin.hytalegenerator.scanners; import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; import com.hypixel.hytale.builtin.hytalegenerator.patterns.Pattern; import com.hypixel.hytale.math.vector.Vector3i; import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class ColumnLinearScanner extends Scanner { private final int minY; private final int maxY; private final boolean isRelativeToPosition; - @Nullable - private final BiDouble2DoubleFunction baseHeightFunction; + private final double baseHeight; private final int resultsCap; private final boolean topDownOrder; @Nonnull private final SpaceSize scanSpaceSize; - public ColumnLinearScanner( - int minY, int maxY, int resultsCap, boolean topDownOrder, boolean isRelativeToPosition, @Nullable BiDouble2DoubleFunction baseHeightFunction - ) { + public ColumnLinearScanner(int minY, int maxY, int resultsCap, boolean topDownOrder, boolean isRelativeToPosition, double baseHeight) { if (resultsCap < 0) { throw new IllegalArgumentException(); } else { - this.baseHeightFunction = baseHeightFunction; + this.baseHeight = baseHeight; this.minY = minY; this.maxY = maxY; this.isRelativeToPosition = isRelativeToPosition; @@ -45,13 +40,10 @@ public class ColumnLinearScanner extends Scanner { if (this.isRelativeToPosition) { scanMinY = Math.max(context.position.y + this.minY, context.materialSpace.minY()); scanMaxY = Math.min(context.position.y + this.maxY, context.materialSpace.maxY()); - } else if (this.baseHeightFunction != null) { - int bedY = (int)this.baseHeightFunction.apply(context.position.x, context.position.z); + } else { + int bedY = (int)this.baseHeight; scanMinY = Math.max(bedY + this.minY, context.materialSpace.minY()); scanMaxY = Math.min(bedY + this.maxY, context.materialSpace.maxY()); - } else { - scanMinY = Math.max(this.minY, context.materialSpace.minY()); - scanMaxY = Math.min(this.maxY, context.materialSpace.maxY()); } Vector3i patternPosition = context.position.clone(); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnRandomScanner.java b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnRandomScanner.java index feb16c0c..592b968e 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnRandomScanner.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/ColumnRandomScanner.java @@ -1,7 +1,6 @@ package com.hypixel.hytale.builtin.hytalegenerator.scanners; import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize; -import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiDouble2DoubleFunction; import com.hypixel.hytale.builtin.hytalegenerator.framework.math.SeedGenerator; import com.hypixel.hytale.builtin.hytalegenerator.patterns.Pattern; import com.hypixel.hytale.math.util.FastRandom; @@ -10,14 +9,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class ColumnRandomScanner extends Scanner { private final int minY; private final int maxY; private final boolean isRelativeToPosition; - @Nullable - private final BiDouble2DoubleFunction bedFunction; + private final double baseHeight; private final int resultsCap; @Nonnull private final SeedGenerator seedGenerator; @@ -27,18 +24,12 @@ public class ColumnRandomScanner extends Scanner { private final SpaceSize scanSpaceSize; public ColumnRandomScanner( - int minY, - int maxY, - int resultsCap, - int seed, - @Nonnull ColumnRandomScanner.Strategy strategy, - boolean isRelativeToPosition, - @Nullable BiDouble2DoubleFunction bedFunction + int minY, int maxY, int resultsCap, int seed, @Nonnull ColumnRandomScanner.Strategy strategy, boolean isRelativeToPosition, double baseHeight ) { if (resultsCap < 0) { throw new IllegalArgumentException(); } else { - this.bedFunction = bedFunction; + this.baseHeight = baseHeight; this.minY = minY; this.maxY = maxY; this.isRelativeToPosition = isRelativeToPosition; @@ -68,13 +59,10 @@ public class ColumnRandomScanner extends Scanner { if (this.isRelativeToPosition) { scanMinY = Math.max(context.position.y + this.minY, context.materialSpace.minY()); scanMaxY = Math.min(context.position.y + this.maxY, context.materialSpace.maxY()); - } else if (this.bedFunction != null) { - int bedY = (int)this.bedFunction.apply(context.position.x, context.position.z); + } else { + int bedY = (int)this.baseHeight; scanMinY = Math.max(bedY + this.minY, context.materialSpace.minY()); scanMaxY = Math.min(bedY + this.maxY, context.materialSpace.maxY()); - } else { - scanMinY = Math.max(this.minY, context.materialSpace.minY()); - scanMaxY = Math.min(this.maxY, context.materialSpace.maxY()); } int numberOfPossiblePositions = Math.max(0, scanMaxY - scanMinY); diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/OriginScanner.java b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/OriginScanner.java index dbf087be..ba9475e8 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/OriginScanner.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/scanners/OriginScanner.java @@ -8,7 +8,9 @@ import java.util.List; import javax.annotation.Nonnull; public class OriginScanner extends Scanner { + @Nonnull private static final OriginScanner instance = new OriginScanner(); + @Nonnull private static final SpaceSize SCAN_SPACE_SIZE = new SpaceSize(new Vector3i(0, 0, 0), new Vector3i(1, 0, 1)); private OriginScanner() { @@ -27,6 +29,7 @@ public class OriginScanner extends Scanner { return SCAN_SPACE_SIZE.clone(); } + @Nonnull public static OriginScanner getInstance() { return instance; } diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/threadindexer/WorkerIndexer.java b/src/com/hypixel/hytale/builtin/hytalegenerator/threadindexer/WorkerIndexer.java index f7059f20..1f77facb 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/threadindexer/WorkerIndexer.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/threadindexer/WorkerIndexer.java @@ -95,8 +95,11 @@ public class WorkerIndexer { public static class Id { public static final int UNKNOWN_THREAD_ID = -1; + public static final int MAIN_THREAD_ID = 0; + @Nonnull public static final WorkerIndexer.Id UNKNOWN = new WorkerIndexer.Id(-1); - public static final WorkerIndexer.Id TEMP_0 = new WorkerIndexer.Id(0); + @Nonnull + public static final WorkerIndexer.Id MAIN = new WorkerIndexer.Id(0); public final int id; private Id(int id) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/tintproviders/TintProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/tintproviders/TintProvider.java index cb976044..ebca3db7 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/tintproviders/TintProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/tintproviders/TintProvider.java @@ -32,6 +32,7 @@ public abstract class TintProvider { } public static class Result { + @Nonnull public static final TintProvider.Result WITHOUT_VALUE = new TintProvider.Result(); public final int tint; public final boolean hasValue; diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/vectorproviders/DensityGradientVectorProvider.java b/src/com/hypixel/hytale/builtin/hytalegenerator/vectorproviders/DensityGradientVectorProvider.java index 8dae8019..fec45e17 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/vectorproviders/DensityGradientVectorProvider.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/vectorproviders/DensityGradientVectorProvider.java @@ -8,7 +8,9 @@ public class DensityGradientVectorProvider extends VectorProvider { @Nonnull private final Density density; private final double sampleDistance; + @Nonnull private final Density.Context rChildContext; + @Nonnull private final Vector3d rPosition; public DensityGradientVectorProvider(@Nonnull Density density, double sampleDistance) { diff --git a/src/com/hypixel/hytale/builtin/hytalegenerator/worldstructure/WorldStructure.java b/src/com/hypixel/hytale/builtin/hytalegenerator/worldstructure/WorldStructure.java index 6bc83b6a..5c549bfa 100644 --- a/src/com/hypixel/hytale/builtin/hytalegenerator/worldstructure/WorldStructure.java +++ b/src/com/hypixel/hytale/builtin/hytalegenerator/worldstructure/WorldStructure.java @@ -3,19 +3,31 @@ package com.hypixel.hytale.builtin.hytalegenerator.worldstructure; import com.hypixel.hytale.builtin.hytalegenerator.Registry; import com.hypixel.hytale.builtin.hytalegenerator.biome.Biome; import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.BiCarta; +import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider; import javax.annotation.Nonnull; public class WorldStructure { + @Nonnull private final BiCarta biomeMap; + @Nonnull private final Registry biomeRegistry; private final int biomeTransitionDistance; private final int maxBiomeEdgeDistance; + @Nonnull + private final PositionProvider spawnPositions; - public WorldStructure(@Nonnull BiCarta biomeMap, @Nonnull Registry biomeRegistry, int biomeTransitionDistance, int maxBiomeEdgeDistance) { + public WorldStructure( + @Nonnull BiCarta biomeMap, + @Nonnull Registry biomeRegistry, + int biomeTransitionDistance, + int maxBiomeEdgeDistance, + @Nonnull PositionProvider spawnPositions + ) { this.biomeMap = biomeMap; this.biomeRegistry = biomeRegistry; this.biomeTransitionDistance = biomeTransitionDistance; this.maxBiomeEdgeDistance = maxBiomeEdgeDistance; + this.spawnPositions = spawnPositions; } @Nonnull @@ -35,4 +47,9 @@ public class WorldStructure { public int getMaxBiomeEdgeDistance() { return this.maxBiomeEdgeDistance; } + + @Nonnull + public PositionProvider getSpawnPositions() { + return this.spawnPositions; + } } diff --git a/src/com/hypixel/hytale/builtin/instances/InstanceValidator.java b/src/com/hypixel/hytale/builtin/instances/InstanceValidator.java index bb81cf6f..031ae5c1 100644 --- a/src/com/hypixel/hytale/builtin/instances/InstanceValidator.java +++ b/src/com/hypixel/hytale/builtin/instances/InstanceValidator.java @@ -7,7 +7,10 @@ import com.hypixel.hytale.codec.validation.Validator; import javax.annotation.Nonnull; public class InstanceValidator implements Validator { + @Nonnull public static final InstanceValidator INSTANCE = new InstanceValidator(); + @Nonnull + public static final String CUSTOM_ASSET_NAME = "Instance"; public void accept(@Nonnull String s, @Nonnull ValidationResults results) { if (!InstancesPlugin.doesInstanceAssetExist(s)) { diff --git a/src/com/hypixel/hytale/builtin/instances/InstancesPlugin.java b/src/com/hypixel/hytale/builtin/instances/InstancesPlugin.java index 64a5eabe..64a11b1b 100644 --- a/src/com/hypixel/hytale/builtin/instances/InstancesPlugin.java +++ b/src/com/hypixel/hytale/builtin/instances/InstancesPlugin.java @@ -25,6 +25,7 @@ import com.hypixel.hytale.codec.schema.config.ObjectSchema; import com.hypixel.hytale.codec.schema.config.Schema; import com.hypixel.hytale.codec.schema.config.StringSchema; import com.hypixel.hytale.common.util.FormatUtil; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; @@ -171,7 +172,7 @@ public class InstancesPlugin extends JavaPlugin { worldKey = "instance-" + safeName(name) + "-" + uuid; } - Path worldPath = path.resolve("worlds").resolve(worldKey); + Path worldPath = universe.validateWorldPath(worldKey); String finalWorldKey = worldKey; return WorldConfig.load(assetPath.resolve("instance.bson")) .thenApplyAsync( @@ -302,7 +303,7 @@ public class InstancesPlugin extends JavaPlugin { } } - public static void exitInstance(@Nonnull Ref targetRef, @Nonnull ComponentAccessor componentAccessor) { + public static CompletableFuture exitInstance(@Nonnull Ref targetRef, @Nonnull ComponentAccessor componentAccessor) { World world = componentAccessor.getExternalData().getWorld(); InstanceEntityConfig entityConfig = componentAccessor.getComponent(targetRef, InstanceEntityConfig.getComponentType()); WorldReturnPoint returnPoint = entityConfig != null ? entityConfig.getReturnPoint() : null; @@ -321,7 +322,10 @@ public class InstancesPlugin extends JavaPlugin { throw new IllegalArgumentException("Missing return world"); } else { Teleport teleportComponent = Teleport.createForPlayer(targetWorld, returnPoint.getReturnPoint()); + CompletableFuture future = new CompletableFuture<>(); + teleportComponent.setOnComplete(future); componentAccessor.addComponent(targetRef, Teleport.getComponentType(), teleportComponent); + return future; } } @@ -350,13 +354,24 @@ public class InstancesPlugin extends JavaPlugin { @Nonnull public static Path getInstanceAssetPath(@Nonnull String name) { for (AssetPack pack : AssetModule.get().getAssetPacks()) { - Path path = pack.getRoot().resolve("Server").resolve("Instances").resolve(name); + Path instancesDir = pack.getRoot().resolve("Server").resolve("Instances"); + Path path = PathUtil.resolvePathWithinDir(instancesDir, name); + if (path == null) { + throw new IllegalArgumentException("Invalid instance name"); + } + if (Files.exists(path)) { return path; } } - return AssetModule.get().getBaseAssetPack().getRoot().resolve("Server").resolve("Instances").resolve(name); + Path instancesDirx = AssetModule.get().getBaseAssetPack().getRoot().resolve("Server").resolve("Instances"); + Path pathx = PathUtil.resolvePathWithinDir(instancesDirx, name); + if (pathx == null) { + throw new IllegalArgumentException("Invalid instance name"); + } else { + return pathx; + } } public static boolean doesInstanceAssetExist(@Nonnull String name) { diff --git a/src/com/hypixel/hytale/builtin/instances/blocks/ConfigurableInstanceBlock.java b/src/com/hypixel/hytale/builtin/instances/blocks/ConfigurableInstanceBlock.java index b9cf14b0..55076203 100644 --- a/src/com/hypixel/hytale/builtin/instances/blocks/ConfigurableInstanceBlock.java +++ b/src/com/hypixel/hytale/builtin/instances/blocks/ConfigurableInstanceBlock.java @@ -76,6 +76,7 @@ public class ConfigurableInstanceBlock implements Component { private boolean personalReturnPoint = false; private double removeBlockAfter = -1.0; + @Nonnull public static ComponentType getComponentType() { return InstancesPlugin.get().getConfigurableInstanceBlockComponentType(); } diff --git a/src/com/hypixel/hytale/builtin/instances/blocks/InstanceBlock.java b/src/com/hypixel/hytale/builtin/instances/blocks/InstanceBlock.java index 546b5569..48e852b7 100644 --- a/src/com/hypixel/hytale/builtin/instances/blocks/InstanceBlock.java +++ b/src/com/hypixel/hytale/builtin/instances/blocks/InstanceBlock.java @@ -21,6 +21,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class InstanceBlock implements Component { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(InstanceBlock.class, InstanceBlock::new) .appendInherited(new KeyedCodec<>("WorldName", Codec.UUID_BINARY), (o, i) -> o.worldUUID = i, o -> o.worldUUID, (o, p) -> o.worldUUID = p.worldUUID) .add() @@ -36,6 +37,7 @@ public class InstanceBlock implements Component { protected CompletableFuture worldFuture; protected boolean closeOnRemove = true; + @Nonnull public static ComponentType getComponentType() { return InstancesPlugin.get().getInstanceBlockComponentType(); } diff --git a/src/com/hypixel/hytale/builtin/instances/command/InstanceEditCopyCommand.java b/src/com/hypixel/hytale/builtin/instances/command/InstanceEditCopyCommand.java index 8441891e..7fffee97 100644 --- a/src/com/hypixel/hytale/builtin/instances/command/InstanceEditCopyCommand.java +++ b/src/com/hypixel/hytale/builtin/instances/command/InstanceEditCopyCommand.java @@ -1,6 +1,7 @@ package com.hypixel.hytale.builtin.instances.command; import com.hypixel.hytale.builtin.instances.InstancesPlugin; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.command.system.CommandContext; @@ -41,9 +42,11 @@ public class InstanceEditCopyCommand extends AbstractAsyncCommand { context.sendMessage(Message.translation("server.commands.instances.edit.copy.originNotFound").param("path", originPath.toAbsolutePath().toString())); return CompletableFuture.completedFuture(null); } else { - String destinationName = this.destinationNameArg.get(context); - Path destinationPath = originPath.getParent().resolve(destinationName); - if (Files.exists(destinationPath)) { + Path destinationPath = PathUtil.resolveName(originPath.getParent(), this.destinationNameArg.get(context)); + if (destinationPath == null) { + context.sendMessage(Message.translation("server.commands.instances.edit.copy.invalidPath")); + return CompletableFuture.completedFuture(null); + } else if (Files.exists(destinationPath)) { context.sendMessage( Message.translation("server.commands.instances.edit.copy.destinationExists").param("path", destinationPath.toAbsolutePath().toString()) ); @@ -52,9 +55,9 @@ public class InstanceEditCopyCommand extends AbstractAsyncCommand { WorldConfig worldConfig; try { worldConfig = WorldConfig.load(originPath.resolve("instance.bson")).join(); - } catch (Throwable var10) { + } catch (Throwable var9) { context.sendMessage(Message.translation("server.commands.instances.edit.copy.errorLoading")); - InstancesPlugin.get().getLogger().at(Level.SEVERE).log("Error loading origin instance config for copy", var10); + InstancesPlugin.get().getLogger().at(Level.SEVERE).log("Error loading origin instance config for copy", var9); return CompletableFuture.completedFuture(null); } @@ -64,9 +67,9 @@ public class InstanceEditCopyCommand extends AbstractAsyncCommand { try { FileUtil.copyDirectory(originPath, destinationPath); Files.deleteIfExists(destinationConfigFile); - } catch (Throwable var9) { + } catch (Throwable var8) { context.sendMessage(Message.translation("server.commands.instances.edit.copy.errorCopying")); - InstancesPlugin.get().getLogger().at(Level.SEVERE).log("Error copying instance folder for copy", var9); + InstancesPlugin.get().getLogger().at(Level.SEVERE).log("Error copying instance folder for copy", var8); return CompletableFuture.completedFuture(null); } @@ -75,7 +78,7 @@ public class InstanceEditCopyCommand extends AbstractAsyncCommand { () -> context.sendMessage( Message.translation("server.commands.instances.copiedInstanceAssetConfig") .param("origin", instanceToCopy) - .param("destination", destinationName) + .param("destination", destinationPath.getFileName().toString()) ) ); } diff --git a/src/com/hypixel/hytale/builtin/instances/command/InstanceEditNewCommand.java b/src/com/hypixel/hytale/builtin/instances/command/InstanceEditNewCommand.java index a107f81a..de72c2d3 100644 --- a/src/com/hypixel/hytale/builtin/instances/command/InstanceEditNewCommand.java +++ b/src/com/hypixel/hytale/builtin/instances/command/InstanceEditNewCommand.java @@ -1,6 +1,7 @@ package com.hypixel.hytale.builtin.instances.command; import com.hypixel.hytale.assetstore.AssetPack; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.command.system.CommandContext; @@ -16,7 +17,11 @@ import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; public class InstanceEditNewCommand extends AbstractAsyncCommand { + @Nonnull + private static final Message MESSAGE_SERVER_COMMANDS_INSTANCES_EDIT_ASSETS_IMMUTABLE = Message.translation("server.commands.instances.edit.assetsImmutable"); + @Nonnull private final RequiredArg instanceNameArg = this.withRequiredArg("instanceName", "server.commands.instances.edit.arg.name", ArgTypes.STRING); + @Nonnull private final OptionalArg packName = this.withOptionalArg("pack", "server.commands.instances.edit.arg.packName", ArgTypes.STRING); public InstanceEditNewCommand() { @@ -27,7 +32,7 @@ public class InstanceEditNewCommand extends AbstractAsyncCommand { @Override public CompletableFuture executeAsync(@Nonnull CommandContext context) { if (AssetModule.get().getBaseAssetPack().isImmutable()) { - context.sendMessage(Message.translation("server.commands.instances.edit.assetsImmutable")); + context.sendMessage(MESSAGE_SERVER_COMMANDS_INSTANCES_EDIT_ASSETS_IMMUTABLE); return CompletableFuture.completedFuture(null); } else { String packId = this.packName.get(context); @@ -41,19 +46,25 @@ public class InstanceEditNewCommand extends AbstractAsyncCommand { pack = AssetModule.get().getBaseAssetPack(); } - String name = this.instanceNameArg.get(context); - Path path = pack.getRoot().resolve("Server").resolve("Instances").resolve(name); - WorldConfig defaultConfig = new WorldConfig(); - - try { - Files.createDirectories(path); - } catch (IOException var8) { - context.sendMessage(Message.translation("server.commands.instances.createDirectory.failed").param("errormsg", var8.getMessage())); + Path path = PathUtil.resolveName(pack.getRoot().resolve("Server").resolve("Instances"), this.instanceNameArg.get(context)); + if (path == null) { + context.sendMessage(Message.translation("server.commands.instances.edit.new.invalidPath")); return CompletableFuture.completedFuture(null); - } + } else { + try { + Files.createDirectories(path); + } catch (IOException var6) { + context.sendMessage(Message.translation("server.commands.instances.createDirectory.failed").param("errormsg", var6.getMessage())); + return CompletableFuture.completedFuture(null); + } - return WorldConfig.save(path.resolve("instance.bson"), defaultConfig) - .thenRun(() -> context.sendMessage(Message.translation("server.commands.instances.createdInstanceAssetConfig").param("name", name))); + return WorldConfig.save(path.resolve("instance.bson"), new WorldConfig()) + .thenRun( + () -> context.sendMessage( + Message.translation("server.commands.instances.createdInstanceAssetConfig").param("name", path.getFileName().toString()) + ) + ); + } } } } diff --git a/src/com/hypixel/hytale/builtin/instances/command/InstanceMigrateCommand.java b/src/com/hypixel/hytale/builtin/instances/command/InstanceMigrateCommand.java index 667f23de..e1885b7f 100644 --- a/src/com/hypixel/hytale/builtin/instances/command/InstanceMigrateCommand.java +++ b/src/com/hypixel/hytale/builtin/instances/command/InstanceMigrateCommand.java @@ -45,7 +45,7 @@ public class InstanceMigrateCommand extends AbstractAsyncCommand { private static final long CHUNK_UPDATE_INTERVAL = 100L; public InstanceMigrateCommand() { - super("migrate", ""); + super("migrate", "server.commands.instances.migrate.desc"); } @Nonnull diff --git a/src/com/hypixel/hytale/builtin/instances/config/ExitInstance.java b/src/com/hypixel/hytale/builtin/instances/config/ExitInstance.java index b9e46d35..81b7d717 100644 --- a/src/com/hypixel/hytale/builtin/instances/config/ExitInstance.java +++ b/src/com/hypixel/hytale/builtin/instances/config/ExitInstance.java @@ -30,8 +30,7 @@ public class ExitInstance implements RespawnController { @Nonnull World world, @Nonnull Ref playerReference, @Nonnull ComponentAccessor commandBuffer ) { try { - InstancesPlugin.exitInstance(playerReference, commandBuffer); - return CompletableFuture.completedFuture(null); + return InstancesPlugin.exitInstance(playerReference, commandBuffer); } catch (Exception var6) { PlayerRef playerRefComponent = commandBuffer.getComponent(playerReference, PlayerRef.getComponentType()); diff --git a/src/com/hypixel/hytale/builtin/instances/config/InstanceEntityConfig.java b/src/com/hypixel/hytale/builtin/instances/config/InstanceEntityConfig.java index b17e38c2..8f6d1b86 100644 --- a/src/com/hypixel/hytale/builtin/instances/config/InstanceEntityConfig.java +++ b/src/com/hypixel/hytale/builtin/instances/config/InstanceEntityConfig.java @@ -11,7 +11,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class InstanceEntityConfig implements Component { + @Nonnull public static final String ID = "Instance"; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(InstanceEntityConfig.class, InstanceEntityConfig::new) .appendInherited( new KeyedCodec<>("ReturnPoint", WorldReturnPoint.CODEC), (o, i) -> o.returnPoint = i, o -> o.returnPoint, (o, p) -> o.returnPoint = p.returnPoint @@ -58,9 +60,9 @@ public class InstanceEntityConfig implements Component { @Nonnull public InstanceEntityConfig clone() { - InstanceEntityConfig v = new InstanceEntityConfig(); - v.returnPoint = v.returnPoint.clone(); - v.returnPointOverride = v.returnPointOverride.clone(); - return v; + InstanceEntityConfig config = new InstanceEntityConfig(); + config.returnPoint = config.returnPoint.clone(); + config.returnPointOverride = config.returnPointOverride.clone(); + return config; } } diff --git a/src/com/hypixel/hytale/builtin/instances/config/InstanceWorldConfig.java b/src/com/hypixel/hytale/builtin/instances/config/InstanceWorldConfig.java index f6a26c1a..e9cfdd14 100644 --- a/src/com/hypixel/hytale/builtin/instances/config/InstanceWorldConfig.java +++ b/src/com/hypixel/hytale/builtin/instances/config/InstanceWorldConfig.java @@ -11,6 +11,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class InstanceWorldConfig { + @Nonnull public static final String ID = "Instance"; @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(InstanceWorldConfig.class, InstanceWorldConfig::new) @@ -40,7 +41,7 @@ public class InstanceWorldConfig { private RemovalCondition[] removalConditions = RemovalCondition.EMPTY; @Nullable private WorldReturnPoint returnPoint; - private boolean preventReconnection = false; + private boolean preventReconnection; @Nullable private InstanceDiscoveryConfig discovery; diff --git a/src/com/hypixel/hytale/builtin/instances/config/WorldReturnPoint.java b/src/com/hypixel/hytale/builtin/instances/config/WorldReturnPoint.java index 93fe8079..3036cdb6 100644 --- a/src/com/hypixel/hytale/builtin/instances/config/WorldReturnPoint.java +++ b/src/com/hypixel/hytale/builtin/instances/config/WorldReturnPoint.java @@ -9,6 +9,7 @@ import java.util.UUID; import javax.annotation.Nonnull; public class WorldReturnPoint { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(WorldReturnPoint.class, WorldReturnPoint::new) .documentation("A world/location pair that is used as a place to return players to.") .append(new KeyedCodec<>("World", Codec.UUID_BINARY), (o, i) -> o.world = i, o -> o.world) diff --git a/src/com/hypixel/hytale/builtin/instances/interactions/ExitInstanceInteraction.java b/src/com/hypixel/hytale/builtin/instances/interactions/ExitInstanceInteraction.java index 022e4a98..97c091c8 100644 --- a/src/com/hypixel/hytale/builtin/instances/interactions/ExitInstanceInteraction.java +++ b/src/com/hypixel/hytale/builtin/instances/interactions/ExitInstanceInteraction.java @@ -17,6 +17,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; public class ExitInstanceInteraction extends SimpleInstantInteraction { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( ExitInstanceInteraction.class, ExitInstanceInteraction::new, SimpleInstantInteraction.CODEC ) @@ -31,8 +32,11 @@ public class ExitInstanceInteraction extends SimpleInstantInteraction { @Override protected void firstRun(@Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler) { - Ref ref = context.getEntity(); CommandBuffer commandBuffer = context.getCommandBuffer(); + + assert commandBuffer != null; + + Ref ref = context.getEntity(); Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType()); if (playerComponent == null || !playerComponent.isWaitingForClientReady()) { Archetype archetype = commandBuffer.getArchetype(ref); diff --git a/src/com/hypixel/hytale/builtin/instances/interactions/TeleportConfigInstanceInteraction.java b/src/com/hypixel/hytale/builtin/instances/interactions/TeleportConfigInstanceInteraction.java index 7831124e..6af985f7 100644 --- a/src/com/hypixel/hytale/builtin/instances/interactions/TeleportConfigInstanceInteraction.java +++ b/src/com/hypixel/hytale/builtin/instances/interactions/TeleportConfigInstanceInteraction.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.math.Axis; import com.hypixel.hytale.math.shape.Box; import com.hypixel.hytale.math.util.ChunkUtil; @@ -45,6 +46,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class TeleportConfigInstanceInteraction extends SimpleBlockInteraction { + @Nonnull + private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); @Nonnull private static final Message MESSAGE_GENERAL_INTERACTION_CONFIGURE_INSTANCE_NO_INSTANCE_NAME = Message.translation( "server.general.interaction.configureInstance.noInstanceName" @@ -139,16 +142,31 @@ public class TeleportConfigInstanceInteraction extends SimpleBlockInteraction { if (removeBlockAfter == 0.0) { long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z); WorldChunk worldChunk = world.getChunk(chunkIndex); - worldChunk.setBlock(targetBlock.x, targetBlock.y, targetBlock.z, 0, 256); + if (worldChunk != null) { + worldChunk.setBlock(targetBlock.x, targetBlock.y, targetBlock.z, 0, 256); + } else { + LOGGER.atWarning() + .log("Failed to remove block at %s,%s,%s as chunk is not loaded", targetBlock.x, targetBlock.y, targetBlock.z); + } } else { int block = world.getBlock(targetBlock); - new CompletableFuture().completeOnTimeout(null, (long)(removeBlockAfter * 1.0E9), TimeUnit.NANOSECONDS).thenRunAsync(() -> { - if (world.getBlock(targetBlock) == block) { - long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z); - WorldChunk worldChunkx = world.getChunk(chunkIndex); - worldChunkx.setBlock(targetBlock.x, targetBlock.y, targetBlock.z, 0, 256); - } - }, world); + new CompletableFuture() + .completeOnTimeout(null, (long)(removeBlockAfter * 1.0E9), TimeUnit.NANOSECONDS) + .thenRunAsync( + () -> { + if (world.getBlock(targetBlock) == block) { + long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z); + WorldChunk worldChunkx = world.getChunk(chunkIndex); + if (worldChunkx != null) { + worldChunkx.setBlock(targetBlock.x, targetBlock.y, targetBlock.z, 0, 256); + } else { + LOGGER.atWarning() + .log("Failed to remove block at %s,%s,%s as chunk is not loaded", targetBlock.x, targetBlock.y, targetBlock.z); + } + } + }, + world + ); } } } @@ -194,34 +212,41 @@ public class TeleportConfigInstanceInteraction extends SimpleBlockInteraction { Ref chunkRef = chunkStore.getChunkReference(chunkIndex); if (chunkRef != null && chunkRef.isValid()) { BlockChunk blockChunkComponent = chunkComponentStore.getComponent(chunkRef, BlockChunk.getComponentType()); - - assert blockChunkComponent != null; - - WorldChunk worldChunkComponent = chunkComponentStore.getComponent(chunkRef, WorldChunk.getComponentType()); - - assert worldChunkComponent != null; - - BlockType blockType = worldChunkComponent.getBlockType(targetBlock.x, targetBlock.y, targetBlock.z); - if (blockType == null) { - throw new IllegalArgumentException("Block type not found"); + if (blockChunkComponent == null) { + throw new IllegalArgumentException("Block chunk component not found"); } else { - IndexedLookupTableAssetMap hitboxAssetMap = BlockBoundingBoxes.getAssetMap(); - BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.y); - int rotationIndex = section.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z); - RotationTuple rotation = RotationTuple.get(rotationIndex); - Box hitbox = hitboxAssetMap.getAsset(blockType.getHitboxTypeIndex()).get(rotationIndex).getBoundingBox(); - Vector3d position = state.getPositionOffset() != null ? rotation.rotate(state.getPositionOffset()) : new Vector3d(); - position.x = position.x + (hitbox.middleX() + targetBlock.x); - position.y = position.y + (hitbox.middleY() + targetBlock.y); - position.z = position.z + (hitbox.middleZ() + targetBlock.z); - Vector3f rotationOutput = Vector3f.NaN; - if (state.getRotation() != null) { - rotationOutput = state.getRotation().clone(); - rotationOutput.addRotationOnAxis(Axis.Y, rotation.yaw().getDegrees()); - rotationOutput.addRotationOnAxis(Axis.X, rotation.pitch().getDegrees()); - } + WorldChunk worldChunkComponent = chunkComponentStore.getComponent(chunkRef, WorldChunk.getComponentType()); + if (worldChunkComponent == null) { + throw new IllegalArgumentException("World chunk component not found"); + } else { + BlockType blockType = worldChunkComponent.getBlockType(targetBlock.x, targetBlock.y, targetBlock.z); + if (blockType == null) { + throw new IllegalArgumentException("Block type not found"); + } else { + IndexedLookupTableAssetMap hitboxAssetMap = BlockBoundingBoxes.getAssetMap(); + BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.y); + int rotationIndex = section.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z); + RotationTuple rotation = RotationTuple.get(rotationIndex); + BlockBoundingBoxes hitboxAsset = hitboxAssetMap.getAsset(blockType.getHitboxTypeIndex()); + if (hitboxAsset == null) { + throw new IllegalArgumentException("Hitbox asset not found for block type: " + blockType.getId()); + } else { + Box hitbox = hitboxAsset.get(rotationIndex).getBoundingBox(); + Vector3d position = state.getPositionOffset() != null ? rotation.rotate(state.getPositionOffset()) : new Vector3d(); + position.x = position.x + (hitbox.middleX() + targetBlock.x); + position.y = position.y + (hitbox.middleY() + targetBlock.y); + position.z = position.z + (hitbox.middleZ() + targetBlock.z); + Vector3f rotationOutput = Vector3f.NaN; + if (state.getRotation() != null) { + rotationOutput = state.getRotation().clone(); + rotationOutput.addRotationOnAxis(Axis.Y, rotation.yaw().getDegrees()); + rotationOutput.addRotationOnAxis(Axis.X, rotation.pitch().getDegrees()); + } - return new Transform(position, rotationOutput); + return new Transform(position, rotationOutput); + } + } + } } } else { throw new IllegalArgumentException("Chunk not loaded"); diff --git a/src/com/hypixel/hytale/builtin/instances/interactions/TeleportInstanceInteraction.java b/src/com/hypixel/hytale/builtin/instances/interactions/TeleportInstanceInteraction.java index a16b7509..8607b6fe 100644 --- a/src/com/hypixel/hytale/builtin/instances/interactions/TeleportInstanceInteraction.java +++ b/src/com/hypixel/hytale/builtin/instances/interactions/TeleportInstanceInteraction.java @@ -48,6 +48,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class TeleportInstanceInteraction extends SimpleInstantInteraction { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( TeleportInstanceInteraction.class, TeleportInstanceInteraction::new, SimpleInstantInteraction.CODEC ) diff --git a/src/com/hypixel/hytale/builtin/instances/page/ConfigureInstanceBlockPage.java b/src/com/hypixel/hytale/builtin/instances/page/ConfigureInstanceBlockPage.java index b7fe4274..7025dbf9 100644 --- a/src/com/hypixel/hytale/builtin/instances/page/ConfigureInstanceBlockPage.java +++ b/src/com/hypixel/hytale/builtin/instances/page/ConfigureInstanceBlockPage.java @@ -204,18 +204,31 @@ public class ConfigureInstanceBlockPage extends InteractiveCustomUIPage CODEC = BuilderCodec.builder( ConfigureInstanceBlockPage.PageData.class, ConfigureInstanceBlockPage.PageData::new diff --git a/src/com/hypixel/hytale/builtin/instances/page/InstanceListPage.java b/src/com/hypixel/hytale/builtin/instances/page/InstanceListPage.java index 5df6f8b7..456251f6 100644 --- a/src/com/hypixel/hytale/builtin/instances/page/InstanceListPage.java +++ b/src/com/hypixel/hytale/builtin/instances/page/InstanceListPage.java @@ -16,7 +16,6 @@ import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCu import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport; -import com.hypixel.hytale.server.core.ui.Value; import com.hypixel.hytale.server.core.ui.browser.FileBrowserConfig; import com.hypixel.hytale.server.core.ui.browser.FileBrowserEventData; import com.hypixel.hytale.server.core.ui.browser.ServerFileBrowser; @@ -33,9 +32,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class InstanceListPage extends InteractiveCustomUIPage { - private static final String COMMON_TEXT_BUTTON_DOCUMENT = "Pages/BasicTextButton.ui"; - private static final Value BUTTON_LABEL_STYLE = Value.ref("Pages/BasicTextButton.ui", "LabelStyle"); - private static final Value BUTTON_LABEL_STYLE_SELECTED = Value.ref("Pages/BasicTextButton.ui", "SelectedLabelStyle"); + @Nonnull private static final String ASSET_PACK_SUB_PATH = "Server/Instances"; @Nullable private String selectedInstance; @@ -211,8 +208,11 @@ public class InstanceListPage extends InteractiveCustomUIPage CODEC = BuilderCodec.builder(InstanceListPage.PageData.class, InstanceListPage.PageData::new) .addField(new KeyedCodec<>("Instance", BuilderCodec.STRING), (o, i) -> o.instance = i, o -> o.instance) .addField(new KeyedCodec<>("Action", new EnumCodec<>(InstanceListPage.Action.class)), (o, i) -> o.action = i, o -> o.action) diff --git a/src/com/hypixel/hytale/builtin/instances/removal/IdleTimeoutCondition.java b/src/com/hypixel/hytale/builtin/instances/removal/IdleTimeoutCondition.java index 2983cd33..dd4b79b1 100644 --- a/src/com/hypixel/hytale/builtin/instances/removal/IdleTimeoutCondition.java +++ b/src/com/hypixel/hytale/builtin/instances/removal/IdleTimeoutCondition.java @@ -12,6 +12,7 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; public class IdleTimeoutCondition implements RemovalCondition { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(IdleTimeoutCondition.class, IdleTimeoutCondition::new) .documentation("A condition that triggers after the world has be idle (without players) for a set time.") .append(new KeyedCodec<>("TimeoutSeconds", Codec.DOUBLE), (o, i) -> o.timeoutSeconds = i, o -> o.timeoutSeconds) diff --git a/src/com/hypixel/hytale/builtin/instances/removal/InstanceDataResource.java b/src/com/hypixel/hytale/builtin/instances/removal/InstanceDataResource.java index 50890ce3..589915a8 100644 --- a/src/com/hypixel/hytale/builtin/instances/removal/InstanceDataResource.java +++ b/src/com/hypixel/hytale/builtin/instances/removal/InstanceDataResource.java @@ -9,8 +9,10 @@ import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import java.time.Instant; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class InstanceDataResource implements Resource { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(InstanceDataResource.class, InstanceDataResource::new) .append(new KeyedCodec<>("TimeoutTimer", Codec.INSTANT), (o, i) -> o.timeoutTimer = i, o -> o.timeoutTimer) .add() @@ -25,6 +27,7 @@ public class InstanceDataResource implements Resource { private Instant timeoutTimer; private Instant idleTimeoutTimer; private boolean hadPlayer; + @Nullable private Instant worldTimeoutTimer; @Nonnull @@ -64,11 +67,12 @@ public class InstanceDataResource implements Resource { this.hadPlayer = hadPlayer; } + @Nullable public Instant getWorldTimeoutTimer() { return this.worldTimeoutTimer; } - public void setWorldTimeoutTimer(Instant worldTimeoutTimer) { + public void setWorldTimeoutTimer(@Nullable Instant worldTimeoutTimer) { this.worldTimeoutTimer = worldTimeoutTimer; } diff --git a/src/com/hypixel/hytale/builtin/instances/removal/RemovalCondition.java b/src/com/hypixel/hytale/builtin/instances/removal/RemovalCondition.java index caffb3e7..99aee605 100644 --- a/src/com/hypixel/hytale/builtin/instances/removal/RemovalCondition.java +++ b/src/com/hypixel/hytale/builtin/instances/removal/RemovalCondition.java @@ -8,6 +8,7 @@ import javax.annotation.Nonnull; public interface RemovalCondition { @Nonnull CodecMapCodec CODEC = new CodecMapCodec<>("Type"); + @Nonnull RemovalCondition[] EMPTY = new RemovalCondition[0]; boolean shouldRemoveWorld(@Nonnull Store var1); diff --git a/src/com/hypixel/hytale/builtin/instances/removal/RemovalSystem.java b/src/com/hypixel/hytale/builtin/instances/removal/RemovalSystem.java index 366a4f5e..e9bf97d0 100644 --- a/src/com/hypixel/hytale/builtin/instances/removal/RemovalSystem.java +++ b/src/com/hypixel/hytale/builtin/instances/removal/RemovalSystem.java @@ -1,6 +1,7 @@ package com.hypixel.hytale.builtin.instances.removal; import com.hypixel.hytale.builtin.instances.config.InstanceWorldConfig; +import com.hypixel.hytale.common.util.CompletableFutureUtil; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.system.tick.RunWhenPausedSystem; import com.hypixel.hytale.component.system.tick.TickingSystem; @@ -13,10 +14,10 @@ import javax.annotation.Nonnull; public class RemovalSystem extends TickingSystem implements RunWhenPausedSystem { @Override public void tick(float dt, int systemIndex, @Nonnull Store store) { - InstanceDataResource data = store.getResource(InstanceDataResource.getResourceType()); - if (!data.isRemoving() && shouldRemoveWorld(store)) { - data.setRemoving(true); - CompletableFuture.runAsync(() -> Universe.get().removeWorld(store.getExternalData().getWorld().getName())); + InstanceDataResource instanceDataResource = store.getResource(InstanceDataResource.getResourceType()); + if (!instanceDataResource.isRemoving() && shouldRemoveWorld(store)) { + instanceDataResource.setRemoving(true); + CompletableFutureUtil._catch(CompletableFuture.runAsync(() -> Universe.get().removeWorld(store.getExternalData().getWorld().getName()))); } } diff --git a/src/com/hypixel/hytale/builtin/instances/removal/TimeoutCondition.java b/src/com/hypixel/hytale/builtin/instances/removal/TimeoutCondition.java index 01a96db6..b1b866eb 100644 --- a/src/com/hypixel/hytale/builtin/instances/removal/TimeoutCondition.java +++ b/src/com/hypixel/hytale/builtin/instances/removal/TimeoutCondition.java @@ -11,6 +11,7 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; public class TimeoutCondition implements RemovalCondition { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(TimeoutCondition.class, TimeoutCondition::new) .documentation("A condition that triggers after a set time limit.") .append(new KeyedCodec<>("TimeoutSeconds", Codec.DOUBLE), (o, i) -> o.timeoutSeconds = i, o -> o.timeoutSeconds) diff --git a/src/com/hypixel/hytale/builtin/instances/removal/WorldEmptyCondition.java b/src/com/hypixel/hytale/builtin/instances/removal/WorldEmptyCondition.java index 7bf9bd71..c0e70436 100644 --- a/src/com/hypixel/hytale/builtin/instances/removal/WorldEmptyCondition.java +++ b/src/com/hypixel/hytale/builtin/instances/removal/WorldEmptyCondition.java @@ -11,8 +11,11 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; public class WorldEmptyCondition implements RemovalCondition { + @Nonnull public static final WorldEmptyCondition INSTANCE = new WorldEmptyCondition(); + @Nonnull public static final RemovalCondition[] REMOVE_WHEN_EMPTY = new RemovalCondition[]{INSTANCE}; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(WorldEmptyCondition.class, WorldEmptyCondition::new) .documentation( "A condition that triggers when the world is empty.\n\nIt will only trigger after at least one player has joined. As a safety measure it provides a timeout for waiting for a player to join in case the player disconnected before entering the world." diff --git a/src/com/hypixel/hytale/builtin/landiscovery/LANDiscoveryCommand.java b/src/com/hypixel/hytale/builtin/landiscovery/LANDiscoveryCommand.java index fc89d3a5..6a680344 100644 --- a/src/com/hypixel/hytale/builtin/landiscovery/LANDiscoveryCommand.java +++ b/src/com/hypixel/hytale/builtin/landiscovery/LANDiscoveryCommand.java @@ -5,7 +5,6 @@ import com.hypixel.hytale.server.core.command.system.CommandContext; import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg; import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase; -import com.hypixel.hytale.server.core.util.message.MessageFormat; import javax.annotation.Nonnull; public class LANDiscoveryCommand extends CommandBase { @@ -32,7 +31,7 @@ public class LANDiscoveryCommand extends CommandBase { context.sendMessage(MESSAGE_IO_LAN_DISCOVERY_DISABLED); } } else { - boolean enabled = this.enabledArg.get(context); + Boolean enabled = this.enabledArg.get(context); LANDiscoveryPlugin plugin = LANDiscoveryPlugin.get(); if (!enabled && plugin.getLanDiscoveryThread() != null) { plugin.setLANDiscoveryEnabled(false); @@ -41,7 +40,7 @@ public class LANDiscoveryCommand extends CommandBase { plugin.setLANDiscoveryEnabled(true); context.sendMessage(MESSAGE_IO_LAN_DISCOVERY_ENABLED); } else { - context.sendMessage(Message.translation("server.io.landiscovery.alreadyToggled").param("status", MessageFormat.enabled(enabled))); + context.sendMessage(Message.translation("server.io.landiscovery.alreadyToggled").param("enabled", enabled.toString())); } } } diff --git a/src/com/hypixel/hytale/builtin/model/pages/ChangeModelPage.java b/src/com/hypixel/hytale/builtin/model/pages/ChangeModelPage.java index e46684ad..02469289 100644 --- a/src/com/hypixel/hytale/builtin/model/pages/ChangeModelPage.java +++ b/src/com/hypixel/hytale/builtin/model/pages/ChangeModelPage.java @@ -44,8 +44,11 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ChangeModelPage extends InteractiveCustomUIPage { + @Nonnull private static final String COMMON_TEXT_BUTTON_DOCUMENT = "Common/TextButton.ui"; + @Nonnull private static final Value BUTTON_LABEL_STYLE = Value.ref("Common/TextButton.ui", "LabelStyle"); + @Nonnull private static final Value BUTTON_LABEL_STYLE_SELECTED = Value.ref("Common/TextButton.ui", "SelectedLabelStyle"); @Nonnull private String searchQuery = ""; @@ -227,10 +230,15 @@ public class ChangeModelPage extends InteractiveCustomUIPage CODEC = BuilderCodec.builder( ChangeModelPage.PageEventData.class, ChangeModelPage.PageEventData::new ) diff --git a/src/com/hypixel/hytale/builtin/mounts/BlockMountAPI.java b/src/com/hypixel/hytale/builtin/mounts/BlockMountAPI.java index 6ea982e4..6677b984 100644 --- a/src/com/hypixel/hytale/builtin/mounts/BlockMountAPI.java +++ b/src/com/hypixel/hytale/builtin/mounts/BlockMountAPI.java @@ -17,13 +17,15 @@ import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import javax.annotation.Nonnull; public final class BlockMountAPI { private BlockMountAPI() { } + @Nonnull public static BlockMountAPI.BlockMountResult mountOnBlock( - Ref entity, CommandBuffer commandBuffer, Vector3i targetBlock, Vector3f interactPos + @Nonnull Ref entity, @Nonnull CommandBuffer commandBuffer, @Nonnull Vector3i targetBlock, @Nonnull Vector3f interactPos ) { MountedComponent existingMounted = commandBuffer.getComponent(entity, MountedComponent.getComponentType()); if (existingMounted != null) { diff --git a/src/com/hypixel/hytale/builtin/mounts/MountPlugin.java b/src/com/hypixel/hytale/builtin/mounts/MountPlugin.java index dad01c5d..61fafe88 100644 --- a/src/com/hypixel/hytale/builtin/mounts/MountPlugin.java +++ b/src/com/hypixel/hytale/builtin/mounts/MountPlugin.java @@ -7,15 +7,27 @@ import com.hypixel.hytale.builtin.mounts.interactions.SpawnMinecartInteraction; import com.hypixel.hytale.builtin.mounts.minecart.MinecartComponent; import com.hypixel.hytale.builtin.mounts.npc.builders.BuilderActionMount; import com.hypixel.hytale.component.ComponentAccessor; +import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.protocol.packets.interaction.DismountNPC; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.player.movement.MovementManager; +import com.hypixel.hytale.server.core.entity.movement.MovementStatesComponent; import com.hypixel.hytale.server.core.io.ServerManager; +import com.hypixel.hytale.server.core.modules.entity.component.Interactable; +import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; +import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent; +import com.hypixel.hytale.server.core.modules.entity.player.PlayerInput; +import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport; +import com.hypixel.hytale.server.core.modules.entity.tracker.EntityTrackerSystems; +import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; +import com.hypixel.hytale.server.core.modules.time.TimeResource; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import com.hypixel.hytale.server.core.prefab.PrefabCopyableComponent; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; @@ -58,32 +70,51 @@ public class MountPlugin extends JavaPlugin { @Override protected void setup() { + ComponentRegistryProxy entityStoreRegistry = this.getEntityStoreRegistry(); instance = this; this.blockMountComponentType = this.getChunkStoreRegistry().registerComponent(BlockMountComponent.class, BlockMountComponent::new); NPCPlugin.get().registerCoreComponentType("Mount", BuilderActionMount::new); - this.mountComponentType = this.getEntityStoreRegistry().registerComponent(NPCMountComponent.class, "Mount", NPCMountComponent.CODEC); - this.mountedComponentType = this.getEntityStoreRegistry().registerComponent(MountedComponent.class, () -> { + this.mountComponentType = entityStoreRegistry.registerComponent(NPCMountComponent.class, "Mount", NPCMountComponent.CODEC); + this.mountedComponentType = entityStoreRegistry.registerComponent(MountedComponent.class, () -> { throw new UnsupportedOperationException("Mounted component cannot be default constructed"); }); - this.mountedByComponentType = this.getEntityStoreRegistry().registerComponent(MountedByComponent.class, MountedByComponent::new); - this.minecartComponentType = this.getEntityStoreRegistry().registerComponent(MinecartComponent.class, "Minecart", MinecartComponent.CODEC); - this.getEntityStoreRegistry().registerSystem(new NPCMountSystems.OnAdd(this.mountComponentType)); - this.getEntityStoreRegistry().registerSystem(new NPCMountSystems.DismountOnPlayerDeath()); - this.getEntityStoreRegistry().registerSystem(new NPCMountSystems.DismountOnMountDeath()); - this.getEntityStoreRegistry().registerSystem(new NPCMountSystems.OnPlayerRemove()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.TrackerUpdate()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.TrackerRemove()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.RemoveMountedBy()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.RemoveMounted()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.RemoveMountedHolder()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.TeleportMountedEntity()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.MountedEntityDeath()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.PlayerMount()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.HandleMountInput()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.TrackedMounted()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.EnsureMinecartComponents()); - this.getEntityStoreRegistry().registerSystem(new MountSystems.OnMinecartHit()); - this.getChunkStoreRegistry().registerSystem(new MountSystems.RemoveBlockSeat()); + this.mountedByComponentType = entityStoreRegistry.registerComponent(MountedByComponent.class, MountedByComponent::new); + this.minecartComponentType = entityStoreRegistry.registerComponent(MinecartComponent.class, "Minecart", MinecartComponent.CODEC); + ComponentType npcEntityComponentType = NPCEntity.getComponentType(); + ComponentType networkIdComponentType = NetworkId.getComponentType(); + ComponentType playerComponentType = Player.getComponentType(); + ComponentType visibleComponentType = EntityTrackerSystems.Visible.getComponentType(); + ComponentType playerInputComponentType = PlayerInput.getComponentType(); + ComponentType movementStatesComponentType = MovementStatesComponent.getComponentType(); + ComponentType transformComponentType = TransformComponent.getComponentType(); + ComponentType teleportComponentType = Teleport.getComponentType(); + ComponentType deathComponentType = DeathComponent.getComponentType(); + ComponentType interactableComponentType = Interactable.getComponentType(); + ComponentType prefabCopyableComponentType = PrefabCopyableComponent.getComponentType(); + ResourceType timeResourceType = TimeResource.getResourceType(); + entityStoreRegistry.registerSystem(new NPCMountSystems.OnAdd(this.mountComponentType, npcEntityComponentType, networkIdComponentType)); + entityStoreRegistry.registerSystem(new NPCMountSystems.DismountOnPlayerDeath(playerComponentType)); + entityStoreRegistry.registerSystem(new NPCMountSystems.DismountOnMountDeath(this.mountComponentType)); + entityStoreRegistry.registerSystem(new NPCMountSystems.OnPlayerRemove(playerComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.TrackerUpdate(visibleComponentType, this.mountedComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.TrackerRemove(this.mountedComponentType, visibleComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.RemoveMountedBy(this.mountedByComponentType, this.mountedComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.RemoveMounted(this.mountedComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.RemoveMountedHolder(this.mountedComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.TeleportMountedEntity(this.mountedComponentType, teleportComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.MountedEntityDeath(this.mountedComponentType, deathComponentType)); + entityStoreRegistry.registerSystem(new MountSystems.PlayerMount(this.mountedComponentType, playerInputComponentType, networkIdComponentType)); + entityStoreRegistry.registerSystem( + new MountSystems.HandleMountInput(this.mountedComponentType, playerInputComponentType, movementStatesComponentType, transformComponentType) + ); + entityStoreRegistry.registerSystem(new MountSystems.TrackedMounted(this.mountedComponentType, this.mountedByComponentType)); + entityStoreRegistry.registerSystem( + new MountSystems.EnsureMinecartComponents(this.minecartComponentType, interactableComponentType, networkIdComponentType, prefabCopyableComponentType) + ); + entityStoreRegistry.registerSystem( + new MountSystems.OnMinecartHit(this.minecartComponentType, transformComponentType, playerComponentType, timeResourceType) + ); + this.getChunkStoreRegistry().registerSystem(new MountSystems.RemoveBlockSeat(this.blockMountComponentType, this.mountedComponentType)); ServerManager.get().registerSubPacketHandlers(MountGamePacketHandler::new); this.getCommandRegistry().registerCommand(new MountCommand()); Interaction.CODEC.register("SpawnMinecart", SpawnMinecartInteraction.class, SpawnMinecartInteraction.CODEC); diff --git a/src/com/hypixel/hytale/builtin/mounts/MountSystems.java b/src/com/hypixel/hytale/builtin/mounts/MountSystems.java index b893c56e..fa022e04 100644 --- a/src/com/hypixel/hytale/builtin/mounts/MountSystems.java +++ b/src/com/hypixel/hytale/builtin/mounts/MountSystems.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.RemoveReason; +import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.SystemGroup; import com.hypixel.hytale.component.dependency.Dependency; @@ -63,10 +64,11 @@ import java.util.Map; import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class MountSystems { - private static void handleMountedRemoval(Ref ref, @Nonnull CommandBuffer commandBuffer, @Nonnull MountedComponent component) { + private static void handleMountedRemoval( + @Nonnull Ref ref, @Nonnull CommandBuffer commandBuffer, @Nonnull MountedComponent component + ) { Ref mountedToEntity = component.getMountedToEntity(); if (mountedToEntity != null && mountedToEntity.isValid()) { MountedByComponent mountedBy = commandBuffer.getComponent(mountedToEntity, MountedByComponent.getComponentType()); @@ -89,20 +91,42 @@ public class MountSystems { } public static class EnsureMinecartComponents extends HolderSystem { + @Nonnull + private final ComponentType minecartComponentType; + @Nonnull + private final ComponentType interactableComponentType; + @Nonnull + private final ComponentType networkIdComponentType; + @Nonnull + private final ComponentType prefabCopyableComponentType; + + public EnsureMinecartComponents( + @Nonnull ComponentType minecartComponentType, + @Nonnull ComponentType interactableComponentType, + @Nonnull ComponentType networkIdComponentType, + @Nonnull ComponentType prefabCopyableComponentType + ) { + this.minecartComponentType = minecartComponentType; + this.interactableComponentType = interactableComponentType; + this.networkIdComponentType = networkIdComponentType; + this.prefabCopyableComponentType = prefabCopyableComponentType; + } + @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - holder.ensureComponent(Interactable.getComponentType()); - holder.putComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId())); - holder.ensureComponent(PrefabCopyableComponent.getComponentType()); + holder.ensureComponent(this.interactableComponentType); + holder.putComponent(this.networkIdComponentType, new NetworkId(store.getExternalData().takeNextNetworkId())); + holder.ensureComponent(this.prefabCopyableComponentType); } @Override public void onEntityRemoved(@Nonnull Holder holder, @Nonnull RemoveReason reason, @Nonnull Store store) { } + @Nonnull @Override public Query getQuery() { - return MinecartComponent.getComponentType(); + return this.minecartComponentType; } @Nonnull @@ -113,9 +137,32 @@ public class MountSystems { } public static class HandleMountInput extends EntityTickingSystem { - private final Query query = Query.and(MountedComponent.getComponentType(), PlayerInput.getComponentType()); + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType playerInputComponentType; + @Nonnull + private final ComponentType movementStatesComponentType; + @Nonnull + private final ComponentType transformComponentType; + @Nonnull + private final Query query; + @Nonnull private final Set> deps = Set.of(new SystemDependency<>(Order.BEFORE, PlayerSystems.ProcessPlayerInput.class)); + public HandleMountInput( + @Nonnull ComponentType mountedComponentType, + @Nonnull ComponentType playerInputComponentType, + @Nonnull ComponentType movementStatesComponentType, + @Nonnull ComponentType transformComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.playerInputComponentType = playerInputComponentType; + this.movementStatesComponentType = movementStatesComponentType; + this.transformComponentType = transformComponentType; + this.query = Query.and(mountedComponentType, playerInputComponentType); + } + @Override public void tick( float dt, @@ -124,61 +171,62 @@ public class MountSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - MountedComponent mounted = archetypeChunk.getComponent(index, MountedComponent.getComponentType()); + MountedComponent mountedComponent = archetypeChunk.getComponent(index, this.mountedComponentType); - assert mounted != null; + assert mountedComponent != null; - PlayerInput input = archetypeChunk.getComponent(index, PlayerInput.getComponentType()); + PlayerInput playerInputComponent = archetypeChunk.getComponent(index, this.playerInputComponentType); - assert input != null; + assert playerInputComponent != null; - MountController controller = mounted.getControllerType(); - Ref targetRef = controller == MountController.BlockMount ? archetypeChunk.getReferenceTo(index) : mounted.getMountedToEntity(); - List queue = input.getMovementUpdateQueue(); + MountController controller = mountedComponent.getControllerType(); + Ref targetRef = controller == MountController.BlockMount ? archetypeChunk.getReferenceTo(index) : mountedComponent.getMountedToEntity(); + List queue = playerInputComponent.getMovementUpdateQueue(); for (int i = 0; i < queue.size(); i++) { - PlayerInput.InputUpdate q = queue.get(i); - if (controller == MountController.BlockMount && (q instanceof PlayerInput.RelativeMovement || q instanceof PlayerInput.AbsoluteMovement)) { - if (mounted.getMountedDurationMs() < 600L) { + PlayerInput.InputUpdate inputUpdate = queue.get(i); + if (controller == MountController.BlockMount + && (inputUpdate instanceof PlayerInput.RelativeMovement || inputUpdate instanceof PlayerInput.AbsoluteMovement)) { + if (mountedComponent.getMountedDurationMs() < 600L) { continue; } Ref ref = archetypeChunk.getReferenceTo(index); - commandBuffer.removeComponent(ref, MountedComponent.getComponentType()); + commandBuffer.tryRemoveComponent(ref, this.mountedComponentType); } - if (q instanceof PlayerInput.SetRiderMovementStates s) { + if (inputUpdate instanceof PlayerInput.SetRiderMovementStates s) { MovementStates states = s.movementStates(); - MovementStatesComponent movementStatesComponent = archetypeChunk.getComponent(index, MovementStatesComponent.getComponentType()); + MovementStatesComponent movementStatesComponent = archetypeChunk.getComponent(index, this.movementStatesComponentType); if (movementStatesComponent != null) { movementStatesComponent.setMovementStates(states); } - } else if (!(q instanceof PlayerInput.WishMovement)) { - if (q instanceof PlayerInput.RelativeMovement relative) { + } else if (!(inputUpdate instanceof PlayerInput.WishMovement)) { + if (inputUpdate instanceof PlayerInput.RelativeMovement relative) { relative.apply(commandBuffer, archetypeChunk, index); - TransformComponent transform = commandBuffer.getComponent(targetRef, TransformComponent.getComponentType()); + TransformComponent transform = commandBuffer.getComponent(targetRef, this.transformComponentType); if (transform != null) { transform.getPosition().add(relative.getX(), relative.getY(), relative.getZ()); } - } else if (q instanceof PlayerInput.AbsoluteMovement absolute) { + } else if (inputUpdate instanceof PlayerInput.AbsoluteMovement absolute) { absolute.apply(commandBuffer, archetypeChunk, index); - TransformComponent transform = commandBuffer.getComponent(targetRef, TransformComponent.getComponentType()); + TransformComponent transform = commandBuffer.getComponent(targetRef, this.transformComponentType); if (transform != null) { transform.getPosition().assign(absolute.getX(), absolute.getY(), absolute.getZ()); } - } else if (q instanceof PlayerInput.SetMovementStates sx) { + } else if (inputUpdate instanceof PlayerInput.SetMovementStates sx) { MovementStates states = sx.movementStates(); - MovementStatesComponent movementStatesComponent = commandBuffer.getComponent(targetRef, MovementStatesComponent.getComponentType()); + MovementStatesComponent movementStatesComponent = commandBuffer.getComponent(targetRef, this.movementStatesComponentType); if (movementStatesComponent != null) { movementStatesComponent.setMovementStates(states); } - } else if (q instanceof PlayerInput.SetBody body) { + } else if (inputUpdate instanceof PlayerInput.SetBody body) { body.apply(commandBuffer, archetypeChunk, index); - TransformComponent transform = commandBuffer.getComponent(targetRef, TransformComponent.getComponentType()); + TransformComponent transform = commandBuffer.getComponent(targetRef, this.transformComponentType); if (transform != null) { transform.getRotation().assign(body.direction().pitch, body.direction().yaw, body.direction().roll); } - } else if (q instanceof PlayerInput.SetHead head) { + } else if (inputUpdate instanceof PlayerInput.SetHead head) { head.apply(commandBuffer, archetypeChunk, index); } } @@ -201,21 +249,34 @@ public class MountSystems { } public static class MountedEntityDeath extends RefChangeSystem { + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType deathComponentType; + + public MountedEntityDeath( + @Nonnull ComponentType mountedComponentType, @Nonnull ComponentType deathComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.deathComponentType = deathComponentType; + } + + @Nonnull @Override public Query getQuery() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } @Nonnull @Override public ComponentType componentType() { - return DeathComponent.getComponentType(); + return this.deathComponentType; } public void onComponentAdded( @Nonnull Ref ref, @Nonnull DeathComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - commandBuffer.removeComponent(ref, MountedComponent.getComponentType()); + commandBuffer.removeComponent(ref, this.mountedComponentType); } public void onComponentSet( @@ -237,23 +298,45 @@ public class MountSystems { private static final Duration HIT_RESET_TIME = Duration.ofSeconds(10L); private static final int NUMBER_OF_HITS = 3; @Nonnull - private static final Query QUERY = Archetype.of(MinecartComponent.getComponentType(), TransformComponent.getComponentType()); + private final ComponentType minecartComponentType; @Nonnull - private static final Set> DEPENDENCIES = Set.of( + private final ComponentType transformComponentType; + @Nonnull + private final ComponentType playerComponentType; + @Nonnull + private final ResourceType timeResourceType; + @Nonnull + private final Query query; + @Nonnull + private final Set> dependencies = Set.of( new SystemGroupDependency<>(Order.AFTER, DamageModule.get().getGatherDamageGroup()), new SystemGroupDependency<>(Order.AFTER, DamageModule.get().getFilterDamageGroup()), new SystemGroupDependency<>(Order.BEFORE, DamageModule.get().getInspectDamageGroup()) ); + public OnMinecartHit( + @Nonnull ComponentType minecartComponentType, + @Nonnull ComponentType transformComponentType, + @Nonnull ComponentType playerComponentType, + @Nonnull ResourceType timeResourceType + ) { + this.minecartComponentType = minecartComponentType; + this.transformComponentType = transformComponentType; + this.playerComponentType = playerComponentType; + this.timeResourceType = timeResourceType; + this.query = Archetype.of(minecartComponentType, transformComponentType); + } + + @Nonnull @Override public Query getQuery() { - return QUERY; + return this.query; } @Nonnull @Override public Set> getDependencies() { - return DEPENDENCIES; + return this.dependencies; } public void handle( @@ -263,11 +346,11 @@ public class MountSystems { @Nonnull CommandBuffer commandBuffer, @Nonnull Damage damage ) { - MinecartComponent minecartComponent = archetypeChunk.getComponent(index, MinecartComponent.getComponentType()); + MinecartComponent minecartComponent = archetypeChunk.getComponent(index, this.minecartComponentType); assert minecartComponent != null; - Instant currentTime = commandBuffer.getResource(TimeResource.getResourceType()).getNow(); + Instant currentTime = commandBuffer.getResource(this.timeResourceType).getNow(); if (minecartComponent.getLastHit() != null && currentTime.isAfter(minecartComponent.getLastHit().plus(HIT_RESET_TIME))) { minecartComponent.setLastHit(null); minecartComponent.setNumberOfHits(0); @@ -280,14 +363,14 @@ public class MountSystems { commandBuffer.removeEntity(archetypeChunk.getReferenceTo(index), RemoveReason.REMOVE); boolean shouldDropItem = true; if (damage.getSource() instanceof Damage.EntitySource source) { - Player playerComponent = source.getRef().isValid() ? commandBuffer.getComponent(source.getRef(), Player.getComponentType()) : null; + Player playerComponent = source.getRef().isValid() ? commandBuffer.getComponent(source.getRef(), this.playerComponentType) : null; if (playerComponent != null) { shouldDropItem = playerComponent.getGameMode() != GameMode.Creative; } } if (shouldDropItem && minecartComponent.getSourceItem() != null) { - TransformComponent transform = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + TransformComponent transform = archetypeChunk.getComponent(index, this.transformComponentType); assert transform != null; @@ -304,8 +387,27 @@ public class MountSystems { } public static class PlayerMount extends RefChangeSystem { - private final Query query = PlayerInput.getComponentType(); + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType playerInputComponentType; + @Nonnull + private final ComponentType networkIdComponentType; + @Nonnull + private final Query query; + public PlayerMount( + @Nonnull ComponentType mountedComponentType, + @Nonnull ComponentType playerInputComponentType, + @Nonnull ComponentType networkIdComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.playerInputComponentType = playerInputComponentType; + this.networkIdComponentType = networkIdComponentType; + this.query = playerInputComponentType; + } + + @Nonnull @Override public Query getQuery() { return this.query; @@ -314,7 +416,7 @@ public class MountSystems { @Nonnull @Override public ComponentType componentType() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } public void onComponentAdded( @@ -323,21 +425,21 @@ public class MountSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - MountedComponent mounted = commandBuffer.getComponent(ref, MountedComponent.getComponentType()); + MountedComponent mountedComponent = commandBuffer.getComponent(ref, this.mountedComponentType); - assert mounted != null; + assert mountedComponent != null; - PlayerInput input = commandBuffer.getComponent(ref, PlayerInput.getComponentType()); + PlayerInput playerInputComponent = commandBuffer.getComponent(ref, this.playerInputComponentType); - assert input != null; + assert playerInputComponent != null; - Ref mountRef = mounted.getMountedToEntity(); + Ref mountRef = mountedComponent.getMountedToEntity(); if (mountRef != null && mountRef.isValid()) { - NetworkId mountNetworkIdComponent = commandBuffer.getComponent(mountRef, NetworkId.getComponentType()); + NetworkId mountNetworkIdComponent = commandBuffer.getComponent(mountRef, this.networkIdComponentType); if (mountNetworkIdComponent != null) { int mountNetworkId = mountNetworkIdComponent.getId(); - input.setMountId(mountNetworkId); - input.getMovementUpdateQueue().clear(); + playerInputComponent.setMountId(mountNetworkId); + playerInputComponent.getMovementUpdateQueue().clear(); } } } @@ -357,15 +459,28 @@ public class MountSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - PlayerInput input = commandBuffer.getComponent(ref, PlayerInput.getComponentType()); + PlayerInput playerInputComponent = commandBuffer.getComponent(ref, this.playerInputComponentType); - assert input != null; + assert playerInputComponent != null; - input.setMountId(0); + playerInputComponent.setMountId(0); } } public static class RemoveBlockSeat extends RefSystem { + @Nonnull + private final ComponentType blockMountComponentType; + @Nonnull + private final ComponentType mountedComponentType; + + public RemoveBlockSeat( + @Nonnull ComponentType blockMountComponentType, + @Nonnull ComponentType mountedComponentType + ) { + this.blockMountComponentType = blockMountComponentType; + this.mountedComponentType = mountedComponentType; + } + @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer @@ -376,7 +491,7 @@ public class MountSystems { public void onEntityRemove( @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - BlockMountComponent blockSeatComponent = commandBuffer.getComponent(ref, BlockMountComponent.getComponentType()); + BlockMountComponent blockSeatComponent = commandBuffer.getComponent(ref, this.blockMountComponentType); assert blockSeatComponent != null; @@ -387,19 +502,27 @@ public class MountSystems { blockSeatComponent.removeSeatedEntity(seated); world.execute(() -> { if (seated.isValid()) { - seated.getStore().tryRemoveComponent(seated, MountedComponent.getComponentType()); + seated.getStore().tryRemoveComponent(seated, this.mountedComponentType); } }); } } + @Nonnull @Override public Query getQuery() { - return BlockMountComponent.getComponentType(); + return this.blockMountComponentType; } } public static class RemoveMounted extends RefSystem { + @Nonnull + private final ComponentType mountedComponentType; + + public RemoveMounted(@Nonnull ComponentType mountedComponentType) { + this.mountedComponentType = mountedComponentType; + } + @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer @@ -410,17 +533,31 @@ public class MountSystems { public void onEntityRemove( @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - MountedComponent mounted = commandBuffer.getComponent(ref, MountedComponent.getComponentType()); + MountedComponent mounted = commandBuffer.getComponent(ref, this.mountedComponentType); MountSystems.handleMountedRemoval(ref, commandBuffer, mounted); } + @Nonnull @Override public Query getQuery() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } } public static class RemoveMountedBy extends RefSystem { + @Nonnull + private final ComponentType mountedByComponentType; + @Nonnull + private final ComponentType mountedComponentType; + + public RemoveMountedBy( + @Nonnull ComponentType mountedByComponentType, + @Nonnull ComponentType mountedComponentType + ) { + this.mountedByComponentType = mountedByComponentType; + this.mountedComponentType = mountedComponentType; + } + @Override public void onEntityAdded( @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer @@ -431,64 +568,88 @@ public class MountSystems { public void onEntityRemove( @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - MountedByComponent by = commandBuffer.getComponent(ref, MountedByComponent.getComponentType()); + MountedByComponent mountedByComponent = commandBuffer.getComponent(ref, this.mountedByComponentType); - for (Ref p : by.getPassengers()) { + assert mountedByComponent != null; + + for (Ref p : mountedByComponent.getPassengers()) { if (p.isValid()) { - MountedComponent mounted = commandBuffer.getComponent(p, MountedComponent.getComponentType()); - if (mounted != null) { - Ref target = mounted.getMountedToEntity(); - if (!target.isValid() || target.equals(ref)) { - commandBuffer.removeComponent(p, MountedComponent.getComponentType()); + MountedComponent mountedComponent = commandBuffer.getComponent(p, this.mountedComponentType); + if (mountedComponent != null) { + Ref targetRef = mountedComponent.getMountedToEntity(); + if (targetRef != null && (!targetRef.isValid() || targetRef.equals(ref))) { + commandBuffer.removeComponent(p, this.mountedComponentType); } } } } } + @Nonnull @Override public Query getQuery() { - return MountedByComponent.getComponentType(); + return this.mountedByComponentType; } } public static class RemoveMountedHolder extends HolderSystem { + @Nonnull + private final ComponentType mountedComponentType; + + public RemoveMountedHolder(@Nonnull ComponentType mountedComponentType) { + this.mountedComponentType = mountedComponentType; + } + + @Nonnull @Override public Query getQuery() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } @Override - public void onEntityAdd(@NonNullDecl Holder holder, @NonNullDecl AddReason reason, @NonNullDecl Store store) { + public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { } @Override - public void onEntityRemoved(@NonNullDecl Holder holder, @NonNullDecl RemoveReason reason, @NonNullDecl Store store) { - holder.removeComponent(MountedComponent.getComponentType()); + public void onEntityRemoved(@Nonnull Holder holder, @Nonnull RemoveReason reason, @Nonnull Store store) { + holder.removeComponent(this.mountedComponentType); } } public static class TeleportMountedEntity extends RefChangeSystem { - private static final Set> DEPENDENCIES = Set.of( + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType teleportComponentType; + @Nonnull + private final Set> dependencies = Set.of( new SystemDependency<>(Order.BEFORE, TeleportSystems.MoveSystem.class, OrderPriority.CLOSEST), new SystemDependency<>(Order.BEFORE, TeleportSystems.PlayerMoveSystem.class, OrderPriority.CLOSEST) ); + public TeleportMountedEntity( + @Nonnull ComponentType mountedComponentType, @Nonnull ComponentType teleportComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.teleportComponentType = teleportComponentType; + } + + @Nonnull @Override public Query getQuery() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } @Nonnull @Override public ComponentType componentType() { - return Teleport.getComponentType(); + return this.teleportComponentType; } public void onComponentAdded( @Nonnull Ref ref, @Nonnull Teleport component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - commandBuffer.removeComponent(ref, MountedComponent.getComponentType()); + commandBuffer.removeComponent(ref, this.mountedComponentType); } public void onComponentSet( @@ -508,20 +669,34 @@ public class MountSystems { @Nonnull @Override public Set> getDependencies() { - return DEPENDENCIES; + return this.dependencies; } } public static class TrackedMounted extends RefChangeSystem { + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType mountedByComponentType; + + public TrackedMounted( + @Nonnull ComponentType mountedComponentType, + @Nonnull ComponentType mountedByComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.mountedByComponentType = mountedByComponentType; + } + + @Nonnull @Override public Query getQuery() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } @Nonnull @Override public ComponentType componentType() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } public void onComponentAdded( @@ -532,7 +707,7 @@ public class MountSystems { ) { Ref target = component.getMountedToEntity(); if (target != null && target.isValid()) { - MountedByComponent mountedBy = commandBuffer.ensureAndGetComponent(target, MountedByComponent.getComponentType()); + MountedByComponent mountedBy = commandBuffer.ensureAndGetComponent(target, this.mountedByComponentType); mountedBy.addPassenger(ref); } } @@ -557,15 +732,29 @@ public class MountSystems { } public static class TrackerRemove extends RefChangeSystem { + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final ComponentType visibleComponentType; + + public TrackerRemove( + @Nonnull ComponentType mountedComponentType, + @Nonnull ComponentType visibleComponentType + ) { + this.mountedComponentType = mountedComponentType; + this.visibleComponentType = visibleComponentType; + } + + @Nonnull @Override public Query getQuery() { - return EntityTrackerSystems.Visible.getComponentType(); + return this.visibleComponentType; } @Nonnull @Override public ComponentType componentType() { - return MountedComponent.getComponentType(); + return this.mountedComponentType; } public void onComponentAdded( @@ -595,7 +784,7 @@ public class MountSystems { AnimationUtils.stopAnimation(ref, AnimationSlot.Movement, true, commandBuffer); } - EntityTrackerSystems.Visible visibleComponent = store.getComponent(ref, EntityTrackerSystems.Visible.getComponentType()); + EntityTrackerSystems.Visible visibleComponent = store.getComponent(ref, this.visibleComponentType); assert visibleComponent != null; @@ -606,9 +795,21 @@ public class MountSystems { } public static class TrackerUpdate extends EntityTickingSystem { - private final ComponentType componentType = EntityTrackerSystems.Visible.getComponentType(); @Nonnull - private final Query query = Query.and(this.componentType, MountedComponent.getComponentType()); + private final ComponentType visibleComponentType; + @Nonnull + private final ComponentType mountedComponentType; + @Nonnull + private final Query query; + + public TrackerUpdate( + @Nonnull ComponentType visibleComponentType, + @Nonnull ComponentType mountedComponentType + ) { + this.visibleComponentType = visibleComponentType; + this.mountedComponentType = mountedComponentType; + this.query = Query.and(visibleComponentType, mountedComponentType); + } @Nullable @Override @@ -635,13 +836,19 @@ public class MountSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - EntityTrackerSystems.Visible visible = archetypeChunk.getComponent(index, this.componentType); - MountedComponent mounted = archetypeChunk.getComponent(index, MountedComponent.getComponentType()); + EntityTrackerSystems.Visible visibleComponent = archetypeChunk.getComponent(index, this.visibleComponentType); + + assert visibleComponent != null; + + MountedComponent mountedComponent = archetypeChunk.getComponent(index, this.mountedComponentType); + + assert mountedComponent != null; + Ref ref = archetypeChunk.getReferenceTo(index); - if (mounted.consumeNetworkOutdated()) { - queueUpdatesFor(ref, visible.visibleTo, mounted); - } else if (!visible.newlyVisibleTo.isEmpty()) { - queueUpdatesFor(ref, visible.newlyVisibleTo, mounted); + if (mountedComponent.consumeNetworkOutdated()) { + queueUpdatesFor(ref, visibleComponent.visibleTo, mountedComponent); + } else if (!visibleComponent.newlyVisibleTo.isEmpty()) { + queueUpdatesFor(ref, visibleComponent.newlyVisibleTo, mountedComponent); } } diff --git a/src/com/hypixel/hytale/builtin/mounts/NPCMountSystems.java b/src/com/hypixel/hytale/builtin/mounts/NPCMountSystems.java index 3231b4ec..2dbd4e7b 100644 --- a/src/com/hypixel/hytale/builtin/mounts/NPCMountSystems.java +++ b/src/com/hypixel/hytale/builtin/mounts/NPCMountSystems.java @@ -18,20 +18,26 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.systems.RoleChangeSystem; import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.checkerframework.checker.nullness.compatqual.NonNullDecl; public class NPCMountSystems { public static class DismountOnMountDeath extends DeathSystems.OnDeathSystem { + @Nonnull + private final ComponentType npcMountComponentType; + + public DismountOnMountDeath(@Nonnull ComponentType npcMountComponentType) { + this.npcMountComponentType = npcMountComponentType; + } + + @Nonnull @Override public Query getQuery() { - return NPCMountComponent.getComponentType(); + return this.npcMountComponentType; } public void onComponentAdded( @Nonnull Ref ref, @Nonnull DeathComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - NPCMountComponent mountComponent = store.getComponent(ref, NPCMountComponent.getComponentType()); + NPCMountComponent mountComponent = store.getComponent(ref, this.npcMountComponentType); assert mountComponent != null; @@ -46,16 +52,23 @@ public class NPCMountSystems { } public static class DismountOnPlayerDeath extends DeathSystems.OnDeathSystem { + @Nonnull + private final ComponentType playerComponentType; + + public DismountOnPlayerDeath(@Nonnull ComponentType playerComponentType) { + this.playerComponentType = playerComponentType; + } + @Nonnull @Override public Query getQuery() { - return Player.getComponentType(); + return this.playerComponentType; } public void onComponentAdded( @Nonnull Ref ref, @Nonnull DeathComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + Player playerComponent = store.getComponent(ref, this.playerComponentType); assert playerComponent != null; @@ -66,14 +79,28 @@ public class NPCMountSystems { public static class OnAdd extends RefSystem { @Nonnull private final ComponentType mountComponentType; + @Nonnull + private final ComponentType npcEntityComponentType; + @Nonnull + private final ComponentType networkIdComponentType; + @Nonnull + private final Query query; - public OnAdd(@Nonnull ComponentType mountRoleChangeComponentType) { - this.mountComponentType = mountRoleChangeComponentType; + public OnAdd( + @Nonnull ComponentType mountComponentType, + @Nonnull ComponentType npcEntityComponentType, + @Nonnull ComponentType networkIdComponentType + ) { + this.mountComponentType = mountComponentType; + this.npcEntityComponentType = npcEntityComponentType; + this.networkIdComponentType = networkIdComponentType; + this.query = Query.and(mountComponentType, npcEntityComponentType, networkIdComponentType); } + @Nonnull @Override public Query getQuery() { - return this.mountComponentType; + return this.query; } @Override @@ -86,35 +113,38 @@ public class NPCMountSystems { PlayerRef playerRef = mountComponent.getOwnerPlayerRef(); if (playerRef == null) { - resetOriginalRoleMount(ref, store, commandBuffer, mountComponent); + this.resetOriginalRoleMount(ref, store, commandBuffer, mountComponent); } else { - NPCEntity npcComponent = store.getComponent(ref, NPCEntity.getComponentType()); - if (npcComponent != null) { - NetworkId networkIdComponent = store.getComponent(ref, NetworkId.getComponentType()); - if (networkIdComponent != null) { - int networkId = networkIdComponent.getId(); - MountNPC packet = new MountNPC(mountComponent.getAnchorX(), mountComponent.getAnchorY(), mountComponent.getAnchorZ(), networkId); - Player playerComponent = playerRef.getComponent(Player.getComponentType()); - if (playerComponent != null) { - playerComponent.setMountEntityId(networkId); - playerRef.getPacketHandler().write(packet); - } - } + NPCEntity npcComponent = store.getComponent(ref, this.npcEntityComponentType); + + assert npcComponent != null; + + NetworkId networkIdComponent = store.getComponent(ref, this.networkIdComponentType); + + assert networkIdComponent != null; + + int networkId = networkIdComponent.getId(); + MountNPC packet = new MountNPC(mountComponent.getAnchorX(), mountComponent.getAnchorY(), mountComponent.getAnchorZ(), networkId); + Player playerComponent = playerRef.getComponent(Player.getComponentType()); + if (playerComponent != null) { + playerComponent.setMountEntityId(networkId); + playerRef.getPacketHandler().write(packet); } } } - private static void resetOriginalRoleMount( + private void resetOriginalRoleMount( @Nonnull Ref ref, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer, @Nonnull NPCMountComponent mountComponent ) { - NPCEntity npcComponent = store.getComponent(ref, NPCEntity.getComponentType()); - if (npcComponent != null) { - RoleChangeSystem.requestRoleChange(ref, npcComponent.getRole(), mountComponent.getOriginalRoleIndex(), false, "Idle", null, store); - commandBuffer.removeComponent(ref, NPCMountComponent.getComponentType()); - } + NPCEntity npcComponent = store.getComponent(ref, this.npcEntityComponentType); + + assert npcComponent != null; + + RoleChangeSystem.requestRoleChange(ref, npcComponent.getRole(), mountComponent.getOriginalRoleIndex(), false, "Idle", null, store); + commandBuffer.removeComponent(ref, this.mountComponentType); } @Override @@ -125,33 +155,34 @@ public class NPCMountSystems { } public static class OnPlayerRemove extends RefSystem { + @Nonnull + private final ComponentType playerComponentType; + + public OnPlayerRemove(@Nonnull ComponentType playerComponentType) { + this.playerComponentType = playerComponentType; + } + @Override public void onEntityAdded( - @NonNullDecl Ref ref, - @NonNullDecl AddReason reason, - @NonNullDecl Store store, - @NonNullDecl CommandBuffer commandBuffer + @Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { } @Override public void onEntityRemove( - @NonNullDecl Ref ref, - @NonNullDecl RemoveReason reason, - @NonNullDecl Store store, - @NonNullDecl CommandBuffer commandBuffer + @Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Player player = commandBuffer.getComponent(ref, Player.getComponentType()); + Player player = commandBuffer.getComponent(ref, this.playerComponentType); assert player != null; MountPlugin.checkDismountNpc(commandBuffer, ref, player); } - @Nullable + @Nonnull @Override public Query getQuery() { - return Player.getComponentType(); + return this.playerComponentType; } } } diff --git a/src/com/hypixel/hytale/builtin/mounts/minecart/MinecartComponent.java b/src/com/hypixel/hytale/builtin/mounts/minecart/MinecartComponent.java index 818f55d6..0adccb73 100644 --- a/src/com/hypixel/hytale/builtin/mounts/minecart/MinecartComponent.java +++ b/src/com/hypixel/hytale/builtin/mounts/minecart/MinecartComponent.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.component.Component; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.time.Instant; +import javax.annotation.Nullable; public class MinecartComponent implements Component { public static final BuilderCodec CODEC = BuilderCodec.builder(MinecartComponent.class, MinecartComponent::new) @@ -15,6 +16,7 @@ public class MinecartComponent implements Component { .add() .build(); private int numberOfHits = 0; + @Nullable private Instant lastHit; private String sourceItem = "Rail_Kart"; @@ -37,11 +39,12 @@ public class MinecartComponent implements Component { this.numberOfHits = numberOfHits; } + @Nullable public Instant getLastHit() { return this.lastHit; } - public void setLastHit(Instant lastHit) { + public void setLastHit(@Nullable Instant lastHit) { this.lastHit = lastHit; } diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/CombatActionEvaluatorSystems.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/CombatActionEvaluatorSystems.java index 65d03b6f..c96ad1f4 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/CombatActionEvaluatorSystems.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/CombatActionEvaluatorSystems.java @@ -50,6 +50,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class CombatActionEvaluatorSystems { + @Nonnull private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); public static class CombatConstructionData implements Component { @@ -129,6 +130,7 @@ public class CombatActionEvaluatorSystems { @Nonnull private final ComponentType playerComponentType; private final ComponentType valueStoreComponentType; + @Nonnull private final ComponentType transformComponentType; private final Query query; @Nonnull @@ -362,7 +364,7 @@ public class CombatActionEvaluatorSystems { public static class OnAdded extends HolderSystem { @Nullable - private final ComponentType componentType = NPCEntity.getComponentType(); + private final ComponentType npcComponentType = NPCEntity.getComponentType(); private final ComponentType combatConstructionDataComponentType; @Nonnull private final Set> dependencies; @@ -377,8 +379,12 @@ public class CombatActionEvaluatorSystems { @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - Role role = holder.getComponent(this.componentType).getRole(); - if (role.getBalanceAsset() != null) { + NPCEntity npcComponent = holder.getComponent(this.npcComponentType); + + assert npcComponent != null; + + Role role = npcComponent.getRole(); + if (role != null && role.getBalanceAsset() != null) { BalanceAsset balancingAsset = BalanceAsset.getAssetMap().getAsset(role.getBalanceAsset()); if (balancingAsset instanceof CombatBalanceAsset combatBalance) { CombatActionEvaluatorSystems.CombatConstructionData constructionData = holder.getComponent(this.combatConstructionDataComponentType); diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/NPCCombatActionEvaluatorPlugin.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/NPCCombatActionEvaluatorPlugin.java index bda41a7f..1687d8c8 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/NPCCombatActionEvaluatorPlugin.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/NPCCombatActionEvaluatorPlugin.java @@ -30,9 +30,13 @@ import com.hypixel.hytale.server.npc.decisionmaker.core.conditions.base.Conditio import javax.annotation.Nonnull; public class NPCCombatActionEvaluatorPlugin extends JavaPlugin { + @Nonnull public static final String CAE_MARKED_TARGET_SLOT = "CAETargetSlot"; + @Nonnull public static final String CAE_MIN_RANGE_PARAMETER = "CAEMinRange"; + @Nonnull public static final String CAE_MAX_RANGE_PARAMETER = "CAEMaxRange"; + @Nonnull public static final String CAE_POSITIONING_ANGLE_PARAMETER = "CAEPositioningAngle"; private static NPCCombatActionEvaluatorPlugin instance; private ComponentType targetMemoryComponentType; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/RecentSustainedDamageCondition.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/RecentSustainedDamageCondition.java index 01155ea7..58806210 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/RecentSustainedDamageCondition.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/RecentSustainedDamageCondition.java @@ -13,11 +13,13 @@ import com.hypixel.hytale.server.npc.decisionmaker.core.conditions.base.ScaledCu import javax.annotation.Nonnull; public class RecentSustainedDamageCondition extends ScaledCurveCondition { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( RecentSustainedDamageCondition.class, RecentSustainedDamageCondition::new, ScaledCurveCondition.ABSTRACT_CODEC ) .documentation("A scaled curve condition that returns a utility value based on damage taken since the combat action evaluator was last run.") .build(); + @Nonnull protected static final ComponentType DAMAGE_MEMORY_COMPONENT_TYPE = DamageMemory.getComponentType(); @Override @@ -28,8 +30,8 @@ public class RecentSustainedDamageCondition extends ScaledCurveCondition { CommandBuffer commandBuffer, EvaluationContext context ) { - DamageMemory memory = archetypeChunk.getComponent(selfIndex, DAMAGE_MEMORY_COMPONENT_TYPE); - return memory.getRecentDamage(); + DamageMemory damageMemoryComponent = archetypeChunk.getComponent(selfIndex, DAMAGE_MEMORY_COMPONENT_TYPE); + return damageMemoryComponent == null ? Double.MAX_VALUE : damageMemoryComponent.getRecentDamage(); } @Override diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TargetMemoryCountCondition.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TargetMemoryCountCondition.java index 11a244f4..bc984e0e 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TargetMemoryCountCondition.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TargetMemoryCountCondition.java @@ -14,10 +14,12 @@ import com.hypixel.hytale.server.npc.decisionmaker.core.conditions.base.ScaledCu import javax.annotation.Nonnull; public class TargetMemoryCountCondition extends ScaledCurveCondition { + @Nonnull public static final EnumCodec TARGET_TYPE_CODEC = new EnumCodec<>(TargetMemoryCountCondition.TargetType.class) .documentKey(TargetMemoryCountCondition.TargetType.All, "All known targets.") .documentKey(TargetMemoryCountCondition.TargetType.Friendly, "Known friendly targets.") .documentKey(TargetMemoryCountCondition.TargetType.Hostile, "Known hostile targets."); + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( TargetMemoryCountCondition.class, TargetMemoryCountCondition::new, ScaledCurveCondition.ABSTRACT_CODEC ) @@ -31,6 +33,7 @@ public class TargetMemoryCountCondition extends ScaledCurveCondition { .documentation("The type of targets to count.") .add() .build(); + @Nonnull protected static final ComponentType TARGET_MEMORY_COMPONENT_TYPE = TargetMemory.getComponentType(); protected TargetMemoryCountCondition.TargetType targetType = TargetMemoryCountCondition.TargetType.Hostile; @@ -42,12 +45,14 @@ public class TargetMemoryCountCondition extends ScaledCurveCondition { CommandBuffer commandBuffer, EvaluationContext context ) { - TargetMemory memory = archetypeChunk.getComponent(selfIndex, TARGET_MEMORY_COMPONENT_TYPE); + TargetMemory targetMemoryComponent = archetypeChunk.getComponent(selfIndex, TARGET_MEMORY_COMPONENT_TYPE); + + assert targetMemoryComponent != null; return switch (this.targetType) { - case Hostile -> memory.getKnownHostiles().size(); - case Friendly -> memory.getKnownFriendlies().size(); - case All -> memory.getKnownFriendlies().size() + memory.getKnownHostiles().size(); + case Hostile -> targetMemoryComponent.getKnownHostiles().size(); + case Friendly -> targetMemoryComponent.getKnownFriendlies().size(); + case All -> targetMemoryComponent.getKnownFriendlies().size() + targetMemoryComponent.getKnownHostiles().size(); }; } diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TotalSustainedDamageCondition.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TotalSustainedDamageCondition.java index 4155b44f..ac4b1f8c 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TotalSustainedDamageCondition.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/conditions/TotalSustainedDamageCondition.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.server.npc.decisionmaker.core.conditions.base.ScaledCu import javax.annotation.Nonnull; public class TotalSustainedDamageCondition extends ScaledCurveCondition { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( TotalSustainedDamageCondition.class, TotalSustainedDamageCondition::new, ScaledCurveCondition.ABSTRACT_CODEC ) @@ -28,8 +29,8 @@ public class TotalSustainedDamageCondition extends ScaledCurveCondition { CommandBuffer commandBuffer, EvaluationContext context ) { - DamageMemory memory = archetypeChunk.getComponent(selfIndex, DAMAGE_MEMORY_COMPONENT_TYPE); - return memory.getTotalCombatDamage(); + DamageMemory damageMemoryComponent = archetypeChunk.getComponent(selfIndex, DAMAGE_MEMORY_COMPONENT_TYPE); + return damageMemoryComponent == null ? Double.MAX_VALUE : damageMemoryComponent.getTotalCombatDamage(); } @Override diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/config/CombatBalanceAsset.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/config/CombatBalanceAsset.java index 4bd5e75f..2f0ba141 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/config/CombatBalanceAsset.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/config/CombatBalanceAsset.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.server.npc.config.balancing.BalanceAsset; import javax.annotation.Nonnull; public class CombatBalanceAsset extends BalanceAsset { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder(CombatBalanceAsset.class, CombatBalanceAsset::new, BASE_CODEC) .documentation("A balance asset which also configures a combat action evaluator.") .appendInherited( diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionAddToTargetMemory.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionAddToTargetMemory.java index a1c6503b..5a39b6fd 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionAddToTargetMemory.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionAddToTargetMemory.java @@ -8,12 +8,14 @@ import com.hypixel.hytale.component.Store; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.corecomponents.ActionBase; import com.hypixel.hytale.server.npc.role.Role; +import com.hypixel.hytale.server.npc.sensorinfo.IPositionProvider; import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ActionAddToTargetMemory extends ActionBase { + @Nonnull private static final ComponentType TARGET_MEMORY = TargetMemory.getComponentType(); public ActionAddToTargetMemory(@Nonnull BuilderActionAddToTargetMemory builder) { @@ -28,17 +30,26 @@ public class ActionAddToTargetMemory extends ActionBase { @Override public boolean execute(@Nonnull Ref ref, @Nonnull Role role, @Nonnull InfoProvider sensorInfo, double dt, @Nonnull Store store) { super.execute(ref, role, sensorInfo, dt, store); - TargetMemory targetMemory = ref.getStore().getComponent(ref, TARGET_MEMORY); - if (targetMemory == null) { + TargetMemory targetMemoryComponent = ref.getStore().getComponent(ref, TARGET_MEMORY); + if (targetMemoryComponent == null) { return true; } else { - Ref target = sensorInfo.getPositionProvider().getTarget(); - Int2FloatOpenHashMap hostiles = targetMemory.getKnownHostiles(); - if (hostiles.put(target.getIndex(), targetMemory.getRememberFor()) <= 0.0F) { - targetMemory.getKnownHostilesList().add(target); - } + IPositionProvider positionProvider = sensorInfo.getPositionProvider(); + if (positionProvider == null) { + return true; + } else { + Ref targetRef = positionProvider.getTarget(); + if (targetRef != null && targetRef.isValid()) { + Int2FloatOpenHashMap hostiles = targetMemoryComponent.getKnownHostiles(); + if (hostiles.put(targetRef.getIndex(), targetMemoryComponent.getRememberFor()) <= 0.0F) { + targetMemoryComponent.getKnownHostilesList().add(targetRef); + } - return true; + return true; + } else { + return true; + } + } } } } diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionCombatAbility.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionCombatAbility.java index 65319fc3..3b389b9c 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionCombatAbility.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/ActionCombatAbility.java @@ -34,6 +34,7 @@ import javax.annotation.Nullable; public class ActionCombatAbility extends ActionBase { protected static final ComponentType COMPONENT_TYPE = CombatActionEvaluator.getComponentType(); + @Nonnull protected static final ComponentType TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); protected static final float POSITIONING_ANGLE_THRESHOLD = 0.08726646F; protected final int id; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/CombatTargetCollector.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/CombatTargetCollector.java index 1d9f0471..8ec1d152 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/CombatTargetCollector.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/CombatTargetCollector.java @@ -18,6 +18,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class CombatTargetCollector implements ISensorEntityCollector { + @Nonnull private static final ComponentType TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); @Nullable private Role role; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/SensorCombatActionEvaluator.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/SensorCombatActionEvaluator.java index 809687b0..be66a365 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/SensorCombatActionEvaluator.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/SensorCombatActionEvaluator.java @@ -20,6 +20,7 @@ import com.hypixel.hytale.server.npc.valuestore.ValueStore; import javax.annotation.Nonnull; public class SensorCombatActionEvaluator extends SensorBase { + @Nonnull protected static final ComponentType TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); protected final boolean targetInRange; protected final double allowableDeviation; @@ -33,7 +34,9 @@ public class SensorCombatActionEvaluator extends SensorBase { protected final SingleDoubleParameterProvider maxRangeParameterProvider; @Nonnull protected final SingleDoubleParameterProvider positioningAngleParameterProvider; + @Nonnull protected final MultipleParameterProvider parameterProvider = new MultipleParameterProvider(); + @Nonnull protected final EntityPositionProvider positionProvider = new EntityPositionProvider(this.parameterProvider); protected final ComponentType valueStoreComponentType; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/builders/BuilderSensorCombatActionEvaluator.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/builders/BuilderSensorCombatActionEvaluator.java index 534331b2..db9e7783 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/builders/BuilderSensorCombatActionEvaluator.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/corecomponents/builders/BuilderSensorCombatActionEvaluator.java @@ -19,7 +19,9 @@ import java.util.function.ToIntFunction; import javax.annotation.Nonnull; public class BuilderSensorCombatActionEvaluator extends BuilderSensorBase { + @Nonnull protected final BooleanHolder targetInRange = new BooleanHolder(); + @Nonnull protected final DoubleHolder allowableDeviation = new DoubleHolder(); protected ToIntFunction minRangeStoreSlot; protected ToIntFunction maxRangeStoreSlot; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluator.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluator.java index e80a9a10..28cc7556 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluator.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluator.java @@ -42,7 +42,9 @@ public class CombatActionEvaluator extends Evaluator impleme protected int runInState; protected float predictability; protected double minActionUtility; + @Nonnull protected final Int2ObjectMap.OptionHolder>> optionsBySubState = new Int2ObjectOpenHashMap<>(); + @Nonnull protected final Int2ObjectMap basicAttacksBySubState = new Int2ObjectOpenHashMap<>(); protected int currentBasicAttackSubState = Integer.MIN_VALUE; protected CombatActionEvaluatorConfig.BasicAttacks currentBasicAttackSet; @@ -77,6 +79,7 @@ public class CombatActionEvaluator extends Evaluator impleme protected boolean positionFirst; protected double chargeDistance; protected float timeout; + @Nonnull protected final EvaluationContext evaluationContext = new EvaluationContext(); public static ComponentType getComponentType() { @@ -356,13 +359,13 @@ public class CombatActionEvaluator extends Evaluator impleme index, archetypeChunk, commandBuffer, this.evaluationContext ); if (option != null) { - Ref target = option.getOptionTarget(); - if (target != null) { + Ref targetRef = option.getOptionTarget(); + if (targetRef != null && targetRef.isValid()) { if (((CombatActionOption)option.getOption()).getActionTarget() == CombatActionOption.Target.Friendly) { this.previousTarget = this.primaryTarget; } - this.primaryTarget = target; + this.primaryTarget = targetRef; role.getMarkedEntitySupport().setMarkedEntity(this.markedTargetSlot, this.primaryTarget); } @@ -377,7 +380,7 @@ public class CombatActionEvaluator extends Evaluator impleme public void completeCurrentAction(boolean forceClearAbility, boolean clearBasicAttack) { if (forceClearAbility || this.currentBasicAttack == null) { this.terminateCurrentAction(); - this.setLastRunNanos(System.nanoTime()); + this.lastRunNanos = System.nanoTime(); } if (clearBasicAttack) { @@ -486,6 +489,7 @@ public class CombatActionEvaluator extends Evaluator impleme public class MultipleTargetCombatOptionHolder extends CombatActionEvaluator.CombatOptionHolder { protected List> targets; + @Nonnull protected final DoubleList targetUtilities = new DoubleArrayList(); @Nullable protected Ref pickedTarget; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluatorConfig.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluatorConfig.java index ab699d60..e26f6d55 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluatorConfig.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/CombatActionEvaluatorConfig.java @@ -17,6 +17,7 @@ import java.util.Map; import javax.annotation.Nonnull; public class CombatActionEvaluatorConfig { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CombatActionEvaluatorConfig.class, CombatActionEvaluatorConfig::new ) @@ -79,6 +80,7 @@ public class CombatActionEvaluatorConfig { .documentation("A random range from which to pick the NPC's predictability factor.") .add() .build(); + @Nonnull private static final double[] DEFAULT_PREDICTABILITY_RANGE = new double[]{1.0, 1.0}; protected Map availableActions = Collections.emptyMap(); protected Map actionSets; @@ -130,6 +132,7 @@ public class CombatActionEvaluatorConfig { } public static class ActionSet { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CombatActionEvaluatorConfig.ActionSet.class, CombatActionEvaluatorConfig.ActionSet::new ) @@ -170,6 +173,7 @@ public class CombatActionEvaluatorConfig { } public static class BasicAttacks { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( CombatActionEvaluatorConfig.BasicAttacks.class, CombatActionEvaluatorConfig.BasicAttacks::new ) diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/AbilityCombatAction.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/AbilityCombatAction.java index 1148a945..ea2ee20e 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/AbilityCombatAction.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/AbilityCombatAction.java @@ -37,14 +37,17 @@ import java.util.logging.Level; import javax.annotation.Nonnull; public class AbilityCombatAction extends CombatActionOption { + @Nonnull public static final EnumCodec MODE_CODEC = new EnumCodec<>(AbilityCombatAction.AbilityType.class) .documentKey(AbilityCombatAction.AbilityType.Primary, "Use primary attack.") .documentKey(AbilityCombatAction.AbilityType.Secondary, "Use secondary attack."); + @Nonnull public static final EnumCodec POSITIONING_CODEC = new EnumCodec<>(Positioning.class) .documentKey(Positioning.Any, "Don't care about positioning.") .documentKey(Positioning.Front, "Try to be in front of the target.") .documentKey(Positioning.Behind, "Try to be behind the target.") .documentKey(Positioning.Flank, "Try to be on the target's flank."); + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( AbilityCombatAction.class, AbilityCombatAction::new, CombatActionOption.BASE_CODEC ) @@ -170,6 +173,7 @@ public class AbilityCombatAction extends CombatActionOption { .addValidator(Validators.greaterThanOrEqual(0.0)) .add() .build(); + @Nonnull protected static final ComponentType TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); protected String ability; protected AbilityCombatAction.AbilityType abilityType = AbilityCombatAction.AbilityType.Primary; diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/BasicAttackTargetCombatAction.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/BasicAttackTargetCombatAction.java index 958545f4..d723cf55 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/BasicAttackTargetCombatAction.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/BasicAttackTargetCombatAction.java @@ -19,6 +19,7 @@ import javax.annotation.Nonnull; public class BasicAttackTargetCombatAction extends CombatActionOption { private static final double BASIC_ATTACK_DISTANCE_OFFSET = 0.1; + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( BasicAttackTargetCombatAction.class, BasicAttackTargetCombatAction::new, Option.ABSTRACT_CODEC ) diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/CombatActionOption.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/CombatActionOption.java index 5dfa7929..9697510f 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/CombatActionOption.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/CombatActionOption.java @@ -27,9 +27,11 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public abstract class CombatActionOption extends Option implements JsonAssetWithMap> { + @Nonnull public static final AssetCodecMapCodec CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.extraData = data, t -> t.extraData ); + @Nonnull public static final BuilderCodec BASE_CODEC = BuilderCodec.abstractBuilder(CombatActionOption.class, Option.ABSTRACT_CODEC) .appendInherited( new KeyedCodec<>("Target", CombatActionOption.Target.CODEC), @@ -51,8 +53,11 @@ public abstract class CombatActionOption extends Option implements JsonAssetWith .documentation("An optional range the NPC will try to maintain from the target after executing the combat action.") .add() .build(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(CombatActionOption.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final ValidatorCache VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(CombatActionOption::getAssetStore)); private static AssetStore> ASSET_STORE; protected AssetExtraInfo.Data extraData; @@ -60,6 +65,7 @@ public abstract class CombatActionOption extends Option implements JsonAssetWith protected CombatActionOption.Target actionTarget; protected double[] postExecuteDistanceRange; + @Nonnull public static AssetStore> getAssetStore() { if (ASSET_STORE == null) { ASSET_STORE = AssetRegistry.getAssetStore(CombatActionOption.class); @@ -161,6 +167,7 @@ public abstract class CombatActionOption extends Option implements JsonAssetWith Hostile, Friendly; + @Nonnull public static final EnumCodec CODEC = new EnumCodec<>(CombatActionOption.Target.class) .documentKey(Self, "Action targets self.") .documentKey(Hostile, "Action targets any hostile target.") diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/StateCombatAction.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/StateCombatAction.java index c78bb166..f984650b 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/StateCombatAction.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/evaluator/combatactions/StateCombatAction.java @@ -16,6 +16,7 @@ import java.util.logging.Level; import javax.annotation.Nonnull; public class StateCombatAction extends CombatActionOption { + @Nonnull public static final BuilderCodec CODEC = BuilderCodec.builder( StateCombatAction.class, StateCombatAction::new, CombatActionOption.BASE_CODEC ) @@ -46,7 +47,7 @@ public class StateCombatAction extends CombatActionOption { public void execute( int index, @Nonnull ArchetypeChunk archetypeChunk, - CommandBuffer commandBuffer, + @Nonnull CommandBuffer commandBuffer, @Nonnull Role role, @Nonnull CombatActionEvaluator evaluator, ValueStore valueStore diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/DamageMemorySystems.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/DamageMemorySystems.java index a3775041..d3a069a3 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/DamageMemorySystems.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/DamageMemorySystems.java @@ -15,11 +15,12 @@ import javax.annotation.Nullable; public class DamageMemorySystems { public static class CollectDamage extends DamageEventSystem { + @Nonnull private final ComponentType damageMemoryComponentType; @Nonnull private final Query query; - public CollectDamage(ComponentType damageMemoryComponentType) { + public CollectDamage(@Nonnull ComponentType damageMemoryComponentType) { this.damageMemoryComponentType = damageMemoryComponentType; this.query = damageMemoryComponentType; } @@ -37,8 +38,11 @@ public class DamageMemorySystems { @Nonnull CommandBuffer commandBuffer, @Nonnull Damage damage ) { - DamageMemory memory = archetypeChunk.getComponent(index, this.damageMemoryComponentType); - memory.addDamage(damage.getAmount()); + DamageMemory damageMemoryComponent = archetypeChunk.getComponent(index, this.damageMemoryComponentType); + + assert damageMemoryComponent != null; + + damageMemoryComponent.addDamage(damage.getAmount()); } @Nullable diff --git a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/TargetMemory.java b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/TargetMemory.java index 1ec7f716..15eeced1 100644 --- a/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/TargetMemory.java +++ b/src/com/hypixel/hytale/builtin/npccombatactionevaluator/memory/TargetMemory.java @@ -9,13 +9,19 @@ import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class TargetMemory implements Component { + @Nonnull private final Int2FloatOpenHashMap knownFriendlies = new Int2FloatOpenHashMap(); + @Nonnull private final List> knownFriendliesList = new ObjectArrayList<>(); + @Nonnull private final Int2FloatOpenHashMap knownHostiles = new Int2FloatOpenHashMap(); + @Nonnull private final List> knownHostilesList = new ObjectArrayList<>(); private final float rememberFor; + @Nullable private Ref closestHostile; public static ComponentType getComponentType() { @@ -52,11 +58,12 @@ public class TargetMemory implements Component { return this.rememberFor; } + @Nullable public Ref getClosestHostile() { return this.closestHostile; } - public void setClosestHostile(Ref ref) { + public void setClosestHostile(@Nullable Ref ref) { this.closestHostile = ref; } diff --git a/src/com/hypixel/hytale/builtin/path/path/PatrolPath.java b/src/com/hypixel/hytale/builtin/path/path/PatrolPath.java index 4106906a..fdc69ab8 100644 --- a/src/com/hypixel/hytale/builtin/path/path/PatrolPath.java +++ b/src/com/hypixel/hytale/builtin/path/path/PatrolPath.java @@ -83,7 +83,9 @@ public class PatrolPath implements IPrefabPath { for (int i = 0; i < index; i++) { PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.get(i); - wp.markNeedsSave(); + if (wp != null) { + wp.markNeedsSave(); + } } this.pathChanged.set(true); @@ -94,13 +96,19 @@ public class PatrolPath implements IPrefabPath { public void registerNewWaypointAt(int index, @Nonnull IPrefabPathWaypoint waypoint, int worldGenId) { for (int i = 0; i < index; i++) { PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.get(i); - wp.markNeedsSave(); + if (wp != null) { + wp.markNeedsSave(); + } } - for (int i = this.waypoints.size() - 1; i >= index; i--) { - PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.remove(i); - wp.setOrder((short)(i + 1)); - this.waypoints.put(i + 1, wp); + for (int ix = this.waypoints.size() - 1; ix >= index; ix--) { + PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.remove(ix); + if (wp == null) { + this.waypoints.remove(ix + 1); + } else { + wp.setOrder((short)(ix + 1)); + this.waypoints.put(ix + 1, wp); + } } this.length.getAndIncrement(); @@ -130,13 +138,19 @@ public class PatrolPath implements IPrefabPath { for (int i = 0; i < index; i++) { PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.get(i); - wp.markNeedsSave(); + if (wp != null) { + wp.markNeedsSave(); + } } - for (int i = index; i < this.waypoints.size(); i++) { - PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.remove(i + 1); - wp.setOrder(i); - this.waypoints.put(i, wp); + for (int ix = index; ix < this.waypoints.size(); ix++) { + PatrolPathMarkerEntity wp = (PatrolPathMarkerEntity)this.waypoints.remove(ix + 1); + if (wp == null) { + this.waypoints.remove(ix); + } else { + wp.setOrder(ix); + this.waypoints.put(ix, wp); + } } this.pathChanged.set(true); diff --git a/src/com/hypixel/hytale/builtin/portals/ui/PortalDeviceSummonPage.java b/src/com/hypixel/hytale/builtin/portals/ui/PortalDeviceSummonPage.java index ef655d46..4deb8bc9 100644 --- a/src/com/hypixel/hytale/builtin/portals/ui/PortalDeviceSummonPage.java +++ b/src/com/hypixel/hytale/builtin/portals/ui/PortalDeviceSummonPage.java @@ -65,8 +65,6 @@ public class PortalDeviceSummonPage extends InteractiveCustomUIPage blockRef; @Nullable private final ItemStack offeredItemStack; - @Nonnull - private static final Transform DEFAULT_WORLDGEN_SPAWN = new Transform(0.0, 140.0, 0.0); public PortalDeviceSummonPage(@Nonnull PlayerRef playerRef, PortalDeviceConfig config, Ref blockRef, @Nullable ItemStack offeredItemStack) { super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction, PortalDeviceSummonPage.Data.CODEC); @@ -320,15 +318,15 @@ public class PortalDeviceSummonPage extends InteractiveCustomUIPage { Transform computedSpawn = PortalSpawnFinder.computeSpawnTransform(world, portalSpawn); return computedSpawn == null ? worldSpawnPoint : computedSpawn; }, world); - } else { - Transform uppedSpawnPoint = worldSpawnPoint.clone(); - uppedSpawnPoint.getPosition().add(0.0, 0.5, 0.0); - return CompletableFuture.completedFuture(uppedSpawnPoint); } } } diff --git a/src/com/hypixel/hytale/builtin/worldgen/WorldGenPlugin.java b/src/com/hypixel/hytale/builtin/worldgen/WorldGenPlugin.java index 26c79fe8..631b2cb2 100644 --- a/src/com/hypixel/hytale/builtin/worldgen/WorldGenPlugin.java +++ b/src/com/hypixel/hytale/builtin/worldgen/WorldGenPlugin.java @@ -26,7 +26,6 @@ import java.nio.file.Path; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.logging.Level; import javax.annotation.Nonnull; @@ -36,8 +35,6 @@ public class WorldGenPlugin extends JavaPlugin { private static final String VERSIONS_DIR_NAME = "$Versions"; private static final String MANIFEST_FILENAME = "manifest.json"; private static WorldGenPlugin instance; - private final Object lock = new Object(); - private final Map versions = new Object2ObjectOpenHashMap<>(); public static WorldGenPlugin get() { return instance; @@ -67,16 +64,7 @@ public class WorldGenPlugin extends JavaPlugin { } } - synchronized (this.lock) { - this.versions.clear(); - this.versions.putAll(versions); - } - } - } - - public Semver getLatestVersion(@Nonnull String name, @Nonnull Semver minVersion) { - synchronized (this.lock) { - return this.versions.getOrDefault(name, minVersion); + HytaleWorldGenProvider.CODEC.setVersions(versions); } } diff --git a/src/com/hypixel/hytale/codec/builder/BuilderCodec.java b/src/com/hypixel/hytale/codec/builder/BuilderCodec.java index 66f75ea1..4bd7fa24 100644 --- a/src/com/hypixel/hytale/codec/builder/BuilderCodec.java +++ b/src/com/hypixel/hytale/codec/builder/BuilderCodec.java @@ -262,15 +262,16 @@ public class BuilderCodec implements Codec, DirectDecodeCodec, RawJsonC @Override public void decode(@Nonnull BsonValue bsonValue, T t, @Nonnull ExtraInfo extraInfo) { - this.decode0(bsonValue.asDocument(), t, extraInfo); - this.afterDecodeAndValidate(t, extraInfo); - } - - protected void decode0(@Nonnull BsonDocument document, T t, ExtraInfo extraInfo) { + BsonDocument document = bsonValue.asDocument(); if (this.versioned) { extraInfo = this.decodeVersion(document, extraInfo); } + this.decode0(document, t, extraInfo); + this.afterDecodeAndValidate(t, extraInfo); + } + + protected void decode0(@Nonnull BsonDocument document, T t, ExtraInfo extraInfo) { for (Entry entry : document.entrySet()) { String key = entry.getKey(); BuilderField field = findEntry(this, key, extraInfo); @@ -304,6 +305,10 @@ public class BuilderCodec implements Codec, DirectDecodeCodec, RawJsonC throw new CodecException("This BuilderCodec is for an abstract or direct codec. To use this codec you must specify an existing object to decode into."); } else { T t = this.supplier.get(); + if (this.versioned) { + extraInfo = this.decodeVersion(reader, extraInfo); + } + this.decodeJson0(reader, t, extraInfo); this.afterDecodeAndValidate(t, extraInfo); return t; @@ -311,10 +316,6 @@ public class BuilderCodec implements Codec, DirectDecodeCodec, RawJsonC } public void decodeJson0(@Nonnull RawJsonReader reader, T t, ExtraInfo extraInfo) throws IOException { - if (this.versioned) { - extraInfo = this.decodeVersion(reader, extraInfo); - } - reader.expect('{'); reader.consumeWhiteSpace(); if (!reader.tryConsume('}')) { @@ -409,6 +410,10 @@ public class BuilderCodec implements Codec, DirectDecodeCodec, RawJsonC } public void decodeJson(@Nonnull RawJsonReader reader, T t, @Nonnull ExtraInfo extraInfo) throws IOException { + if (this.versioned) { + extraInfo = this.decodeVersion(reader, extraInfo); + } + this.decodeJson0(reader, t, extraInfo); this.afterDecodeAndValidate(t, extraInfo); } diff --git a/src/com/hypixel/hytale/common/plugin/PluginIdentifier.java b/src/com/hypixel/hytale/common/plugin/PluginIdentifier.java index 3b1fbbda..4e8a1851 100644 --- a/src/com/hypixel/hytale/common/plugin/PluginIdentifier.java +++ b/src/com/hypixel/hytale/common/plugin/PluginIdentifier.java @@ -5,6 +5,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class PluginIdentifier { + public static final String THIRD_PARTY_LOADER_NAME = "ThirdParty"; @Nonnull private final String group; @Nonnull @@ -19,6 +20,30 @@ public class PluginIdentifier { this(manifest.getGroup(), manifest.getName()); } + @Nullable + public static PluginIdentifier identifyThirdPartyPlugin(Throwable t) { + Throwable current = t; + String prefix = "ThirdParty("; + + PluginIdentifier possibleFailureCause; + for (possibleFailureCause = null; current != null; current = current.getCause()) { + StackTraceElement[] stack = current.getStackTrace(); + + for (StackTraceElement entry : stack) { + String loader = entry.getClassLoaderName(); + if (loader != null && loader.startsWith(prefix)) { + int end = loader.lastIndexOf(41); + if (end != -1) { + possibleFailureCause = fromString(loader.substring(prefix.length(), end)); + return possibleFailureCause; + } + } + } + } + + return possibleFailureCause; + } + @Nonnull public String getGroup() { return this.group; diff --git a/src/com/hypixel/hytale/common/plugin/PluginManifest.java b/src/com/hypixel/hytale/common/plugin/PluginManifest.java index b65d9c28..511f6cac 100644 --- a/src/com/hypixel/hytale/common/plugin/PluginManifest.java +++ b/src/com/hypixel/hytale/common/plugin/PluginManifest.java @@ -43,7 +43,7 @@ public class PluginManifest { .add() .append(new KeyedCodec<>("Main", Codec.STRING), (manifest, o) -> manifest.main = o, manifest -> manifest.main) .add() - .append(new KeyedCodec<>("ServerVersion", SemverRange.CODEC), (manifest, o) -> manifest.serverVersion = o, manifest -> manifest.serverVersion) + .append(new KeyedCodec<>("ServerVersion", Codec.STRING), (manifest, o) -> manifest.serverVersion = o, manifest -> manifest.serverVersion) .add() .append( new KeyedCodec<>( @@ -79,8 +79,8 @@ public class PluginManifest { .build(); @Nonnull public static final Codec ARRAY_CODEC = new ArrayCodec<>(CODEC, PluginManifest[]::new); - private static final String CORE_GROUP = "Hytale"; - private static final Semver CORE_VERSION = ManifestUtil.getVersion() == null ? Semver.fromString("0.0.0-dev") : ManifestUtil.getVersion(); + public static final String CORE_GROUP = "Hytale"; + private static final Semver CORE_VERSION = Semver.fromString(ManifestUtil.getVersion() == null ? "0.0.0-dev" : ManifestUtil.getVersion()); private String group; private String name; private Semver version; @@ -92,7 +92,8 @@ public class PluginManifest { private String website; @Nullable private String main; - private SemverRange serverVersion; + @Nullable + private String serverVersion; @Nonnull private Map dependencies = new Object2ObjectLinkedOpenHashMap<>(); @Nonnull @@ -115,7 +116,7 @@ public class PluginManifest { @Nonnull List authors, @Nullable String website, @Nullable String main, - @Nullable SemverRange serverVersion, + @Nonnull String serverVersion, @Nonnull Map dependencies, @Nonnull Map optionalDependencies, @Nonnull Map loadBefore, @@ -193,10 +194,14 @@ public class PluginManifest { return this.main; } - public SemverRange getServerVersion() { + public String getServerVersion() { return this.serverVersion; } + public void setServerVersion(@Nullable String serverVersion) { + this.serverVersion = serverVersion; + } + @Nonnull public Map getDependencies() { return Collections.unmodifiableMap(this.dependencies); @@ -300,8 +305,6 @@ public class PluginManifest { } public static class CoreBuilder { - private static final String CORE_GROUP = "Hytale"; - private static final Semver CORE_VERSION = ManifestUtil.getVersion() == null ? Semver.fromString("0.0.0-dev") : ManifestUtil.getVersion(); @Nonnull private final String group; @Nonnull @@ -321,7 +324,7 @@ public class PluginManifest { @Nonnull public static PluginManifest.CoreBuilder corePlugin(@Nonnull Class pluginClass) { - return new PluginManifest.CoreBuilder("Hytale", pluginClass.getSimpleName(), CORE_VERSION, pluginClass.getName()); + return new PluginManifest.CoreBuilder("Hytale", pluginClass.getSimpleName(), PluginManifest.CORE_VERSION, pluginClass.getName()); } private CoreBuilder(@Nonnull String group, @Nonnull String name, @Nonnull Semver version, @Nonnull String main) { @@ -377,7 +380,7 @@ public class PluginManifest { Collections.emptyList(), null, this.main, - null, + ManifestUtil.getVersion() == null ? "0.0.0-dev" : ManifestUtil.getVersion(), this.dependencies, this.optionalDependencies, this.loadBefore, diff --git a/src/com/hypixel/hytale/common/util/PathUtil.java b/src/com/hypixel/hytale/common/util/PathUtil.java index 8f5da5f9..1fdb8bd2 100644 --- a/src/com/hypixel/hytale/common/util/PathUtil.java +++ b/src/com/hypixel/hytale/common/util/PathUtil.java @@ -5,6 +5,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.regex.Pattern; import javax.annotation.Nonnull; @@ -12,6 +14,23 @@ import javax.annotation.Nullable; public class PathUtil { private static final Pattern PATH_PATTERN = Pattern.compile("[\\\\/]"); + private static final Set TRUSTED_PATH_ROOTS = ConcurrentHashMap.newKeySet(); + + public static void addTrustedRoot(@Nonnull Path root) { + TRUSTED_PATH_ROOTS.add(root.toAbsolutePath().normalize()); + } + + public static boolean isInTrustedRoot(@Nonnull Path path) { + Path normalized = path.toAbsolutePath().normalize(); + + for (Path trusted : TRUSTED_PATH_ROOTS) { + if (isChildOf(trusted, normalized)) { + return true; + } + } + + return false; + } @Nonnull public static Path getParent(@Nonnull Path path) { @@ -51,6 +70,21 @@ public class PathUtil { } } + public static boolean isValidName(@Nonnull String name) { + return !name.isBlank() && name.indexOf(47) < 0 && name.indexOf(92) < 0 && !".".equals(name) && !"..".equals(name); + } + + @Nullable + public static Path resolvePathWithinDir(@Nonnull Path directory, @Nonnull String relativePath) { + Path resolved = directory.resolve(relativePath); + return !isChildOf(directory, resolved) ? null : resolved; + } + + @Nullable + public static Path resolveName(@Nonnull Path directory, @Nonnull String name) { + return !isValidName(name) ? null : directory.resolve(name); + } + @Nonnull public static Path get(@Nonnull String path) { return get(Paths.get(path)); @@ -100,4 +134,9 @@ public class PathUtil { public static String toUnixPathString(@Nonnull Path path) { return "\\".equals(path.getFileSystem().getSeparator()) ? path.toString().replace("\\", "/") : path.toString(); } + + static { + TRUSTED_PATH_ROOTS.add(Path.of("").toAbsolutePath().normalize()); + TRUSTED_PATH_ROOTS.add(Path.of(System.getProperty("java.io.tmpdir")).toAbsolutePath().normalize()); + } } diff --git a/src/com/hypixel/hytale/common/util/java/ManifestUtil.java b/src/com/hypixel/hytale/common/util/java/ManifestUtil.java index 52e5da96..4b541fb2 100644 --- a/src/com/hypixel/hytale/common/util/java/ManifestUtil.java +++ b/src/com/hypixel/hytale/common/util/java/ManifestUtil.java @@ -1,6 +1,5 @@ package com.hypixel.hytale.common.util.java; -import com.hypixel.hytale.common.semver.Semver; import com.hypixel.hytale.function.supplier.CachedSupplier; import com.hypixel.hytale.function.supplier.SupplierUtil; import com.hypixel.hytale.logger.HytaleLogger; @@ -86,9 +85,9 @@ public class ManifestUtil { return "dev"; } }); - private static final CachedSupplier VERSION = SupplierUtil.cache(() -> { + private static final CachedSupplier VERSION = SupplierUtil.cache(() -> { String version = IMPLEMENTATION_VERSION.get(); - return "NoJar".equals(version) ? null : Semver.fromString(version); + return "NoJar".equals(version) ? null : version; }); public static boolean isJar() { @@ -106,7 +105,7 @@ public class ManifestUtil { } @Nullable - public static Semver getVersion() { + public static String getVersion() { return VERSION.get(); } diff --git a/src/com/hypixel/hytale/component/Archetype.java b/src/com/hypixel/hytale/component/Archetype.java index dde85ac6..bd12d655 100644 --- a/src/com/hypixel/hytale/component/Archetype.java +++ b/src/com/hypixel/hytale/component/Archetype.java @@ -158,10 +158,14 @@ public class Archetype implements Query { @Nonnull public static Archetype of(@Nonnull ComponentType componentTypes) { - int index = componentTypes.getIndex(); - ComponentType[] arr = new ComponentType[index + 1]; - arr[index] = componentTypes; - return new Archetype<>(index, 1, arr); + if (componentTypes == null) { + throw new IllegalArgumentException("ComponentType in Archetype cannot be null"); + } else { + int index = componentTypes.getIndex(); + ComponentType[] arr = new ComponentType[index + 1]; + arr[index] = componentTypes; + return new Archetype<>(index, 1, arr); + } } @SafeVarargs @@ -169,13 +173,20 @@ public class Archetype implements Query { if (componentTypes.length == 0) { return EMPTY; } else { + for (int i = 0; i < componentTypes.length; i++) { + ComponentType componentType = componentTypes[i]; + if (componentType == null) { + throw new IllegalArgumentException("ComponentType in Archetype cannot be null (Index: " + i + ")"); + } + } + ComponentRegistry registry = componentTypes[0].getRegistry(); int minIndex = Integer.MAX_VALUE; int maxIndex = Integer.MIN_VALUE; - for (int i = 0; i < componentTypes.length; i++) { - componentTypes[i].validateRegistry(registry); - int index = componentTypes[i].getIndex(); + for (int ix = 0; ix < componentTypes.length; ix++) { + componentTypes[ix].validateRegistry(registry); + int index = componentTypes[ix].getIndex(); if (index < minIndex) { minIndex = index; } @@ -184,8 +195,8 @@ public class Archetype implements Query { maxIndex = index; } - for (int n = i + 1; n < componentTypes.length; n++) { - if (componentTypes[i] == componentTypes[n]) { + for (int n = ix + 1; n < componentTypes.length; n++) { + if (componentTypes[ix] == componentTypes[n]) { throw new IllegalArgumentException("ComponentType provided multiple times! " + Arrays.toString((Object[])componentTypes)); } } diff --git a/src/com/hypixel/hytale/math/shape/Box.java b/src/com/hypixel/hytale/math/shape/Box.java index f68909e6..98a513dc 100644 --- a/src/com/hypixel/hytale/math/shape/Box.java +++ b/src/com/hypixel/hytale/math/shape/Box.java @@ -32,6 +32,7 @@ public class Box implements Shape { }) .build(); public static final Box UNIT = new Box(Vector3d.ZERO, Vector3d.ALL_ONES); + public static final Box ZERO = new Box(Vector3d.ZERO, Vector3d.ZERO); @Nonnull public final Vector3d min = new Vector3d(); @Nonnull diff --git a/src/com/hypixel/hytale/procedurallib/json/JsonLoader.java b/src/com/hypixel/hytale/procedurallib/json/JsonLoader.java index 6e4993a9..4ca5fa8a 100644 --- a/src/com/hypixel/hytale/procedurallib/json/JsonLoader.java +++ b/src/com/hypixel/hytale/procedurallib/json/JsonLoader.java @@ -71,11 +71,14 @@ public abstract class JsonLoader extends Loader protected JsonElement loadFile(@Nonnull String filePath) { Path file = this.dataFolder.resolve(filePath.replace('.', File.separatorChar) + ".json"); - - try { - return FileIO.load(file, JSON_LOADER); - } catch (Throwable var4) { - throw new Error("Error while loading file reference." + file.toString(), var4); + if (!file.normalize().startsWith(this.dataFolder.normalize())) { + throw new IllegalArgumentException("Invalid file reference: " + filePath); + } else { + try { + return FileIO.load(file, JSON_LOADER); + } catch (Throwable var4) { + throw new Error("Error while loading file reference." + file.toString(), var4); + } } } diff --git a/src/com/hypixel/hytale/protocol/BlockPlacementSettings.java b/src/com/hypixel/hytale/protocol/BlockPlacementSettings.java index 9dd0e82b..f7084450 100644 --- a/src/com/hypixel/hytale/protocol/BlockPlacementSettings.java +++ b/src/com/hypixel/hytale/protocol/BlockPlacementSettings.java @@ -7,10 +7,10 @@ import javax.annotation.Nonnull; public class BlockPlacementSettings { public static final int NULLABLE_BIT_FIELD_SIZE = 0; - public static final int FIXED_BLOCK_SIZE = 16; + public static final int FIXED_BLOCK_SIZE = 17; public static final int VARIABLE_FIELD_COUNT = 0; - public static final int VARIABLE_BLOCK_START = 16; - public static final int MAX_SIZE = 16; + public static final int VARIABLE_BLOCK_START = 17; + public static final int MAX_SIZE = 17; public boolean allowRotationKey; public boolean placeInEmptyBlocks; @Nonnull @@ -20,6 +20,7 @@ public class BlockPlacementSettings { public int wallPlacementOverrideBlockId; public int floorPlacementOverrideBlockId; public int ceilingPlacementOverrideBlockId; + public boolean allowBreakReplace; public BlockPlacementSettings() { } @@ -31,7 +32,8 @@ public class BlockPlacementSettings { @Nonnull BlockPlacementRotationMode rotationMode, int wallPlacementOverrideBlockId, int floorPlacementOverrideBlockId, - int ceilingPlacementOverrideBlockId + int ceilingPlacementOverrideBlockId, + boolean allowBreakReplace ) { this.allowRotationKey = allowRotationKey; this.placeInEmptyBlocks = placeInEmptyBlocks; @@ -40,6 +42,7 @@ public class BlockPlacementSettings { this.wallPlacementOverrideBlockId = wallPlacementOverrideBlockId; this.floorPlacementOverrideBlockId = floorPlacementOverrideBlockId; this.ceilingPlacementOverrideBlockId = ceilingPlacementOverrideBlockId; + this.allowBreakReplace = allowBreakReplace; } public BlockPlacementSettings(@Nonnull BlockPlacementSettings other) { @@ -50,6 +53,7 @@ public class BlockPlacementSettings { this.wallPlacementOverrideBlockId = other.wallPlacementOverrideBlockId; this.floorPlacementOverrideBlockId = other.floorPlacementOverrideBlockId; this.ceilingPlacementOverrideBlockId = other.ceilingPlacementOverrideBlockId; + this.allowBreakReplace = other.allowBreakReplace; } @Nonnull @@ -62,11 +66,12 @@ public class BlockPlacementSettings { obj.wallPlacementOverrideBlockId = buf.getIntLE(offset + 4); obj.floorPlacementOverrideBlockId = buf.getIntLE(offset + 8); obj.ceilingPlacementOverrideBlockId = buf.getIntLE(offset + 12); + obj.allowBreakReplace = buf.getByte(offset + 16) != 0; return obj; } public static int computeBytesConsumed(@Nonnull ByteBuf buf, int offset) { - return 16; + return 17; } public void serialize(@Nonnull ByteBuf buf) { @@ -77,14 +82,15 @@ public class BlockPlacementSettings { buf.writeIntLE(this.wallPlacementOverrideBlockId); buf.writeIntLE(this.floorPlacementOverrideBlockId); buf.writeIntLE(this.ceilingPlacementOverrideBlockId); + buf.writeByte(this.allowBreakReplace ? 1 : 0); } public int computeSize() { - return 16; + return 17; } public static ValidationResult validateStructure(@Nonnull ByteBuf buffer, int offset) { - return buffer.readableBytes() - offset < 16 ? ValidationResult.error("Buffer too small: expected at least 16 bytes") : ValidationResult.OK; + return buffer.readableBytes() - offset < 17 ? ValidationResult.error("Buffer too small: expected at least 17 bytes") : ValidationResult.OK; } public BlockPlacementSettings clone() { @@ -96,6 +102,7 @@ public class BlockPlacementSettings { copy.wallPlacementOverrideBlockId = this.wallPlacementOverrideBlockId; copy.floorPlacementOverrideBlockId = this.floorPlacementOverrideBlockId; copy.ceilingPlacementOverrideBlockId = this.ceilingPlacementOverrideBlockId; + copy.allowBreakReplace = this.allowBreakReplace; return copy; } @@ -112,7 +119,8 @@ public class BlockPlacementSettings { && Objects.equals(this.rotationMode, other.rotationMode) && this.wallPlacementOverrideBlockId == other.wallPlacementOverrideBlockId && this.floorPlacementOverrideBlockId == other.floorPlacementOverrideBlockId - && this.ceilingPlacementOverrideBlockId == other.ceilingPlacementOverrideBlockId; + && this.ceilingPlacementOverrideBlockId == other.ceilingPlacementOverrideBlockId + && this.allowBreakReplace == other.allowBreakReplace; } } @@ -125,7 +133,8 @@ public class BlockPlacementSettings { this.rotationMode, this.wallPlacementOverrideBlockId, this.floorPlacementOverrideBlockId, - this.ceilingPlacementOverrideBlockId + this.ceilingPlacementOverrideBlockId, + this.allowBreakReplace ); } } diff --git a/src/com/hypixel/hytale/protocol/BlockType.java b/src/com/hypixel/hytale/protocol/BlockType.java index 854fa7b3..70e3aaa3 100644 --- a/src/com/hypixel/hytale/protocol/BlockType.java +++ b/src/com/hypixel/hytale/protocol/BlockType.java @@ -15,9 +15,9 @@ import javax.annotation.Nullable; public class BlockType { public static final int NULLABLE_BIT_FIELD_SIZE = 4; - public static final int FIXED_BLOCK_SIZE = 163; + public static final int FIXED_BLOCK_SIZE = 164; public static final int VARIABLE_FIELD_COUNT = 24; - public static final int VARIABLE_BLOCK_START = 259; + public static final int VARIABLE_BLOCK_START = 260; public static final int MAX_SIZE = 1677721600; @Nullable public String item; @@ -323,10 +323,10 @@ public class BlockType { obj.placementSettings = BlockPlacementSettings.deserialize(buf, offset + 142); } - obj.ignoreSupportWhenPlaced = buf.getByte(offset + 158) != 0; - obj.transitionToTag = buf.getIntLE(offset + 159); + obj.ignoreSupportWhenPlaced = buf.getByte(offset + 159) != 0; + obj.transitionToTag = buf.getIntLE(offset + 160); if ((nullBits[0] & 128) != 0) { - int varPos0 = offset + 259 + buf.getIntLE(offset + 163); + int varPos0 = offset + 260 + buf.getIntLE(offset + 164); int itemLen = VarInt.peek(buf, varPos0); if (itemLen < 0) { throw ProtocolException.negativeLength("Item", itemLen); @@ -340,7 +340,7 @@ public class BlockType { } if ((nullBits[1] & 1) != 0) { - int varPos1 = offset + 259 + buf.getIntLE(offset + 167); + int varPos1 = offset + 260 + buf.getIntLE(offset + 168); int nameLen = VarInt.peek(buf, varPos1); if (nameLen < 0) { throw ProtocolException.negativeLength("Name", nameLen); @@ -354,7 +354,7 @@ public class BlockType { } if ((nullBits[1] & 2) != 0) { - int varPos2 = offset + 259 + buf.getIntLE(offset + 171); + int varPos2 = offset + 260 + buf.getIntLE(offset + 172); int shaderEffectCount = VarInt.peek(buf, varPos2); if (shaderEffectCount < 0) { throw ProtocolException.negativeLength("ShaderEffect", shaderEffectCount); @@ -379,7 +379,7 @@ public class BlockType { } if ((nullBits[1] & 4) != 0) { - int varPos3 = offset + 259 + buf.getIntLE(offset + 175); + int varPos3 = offset + 260 + buf.getIntLE(offset + 176); int modelLen = VarInt.peek(buf, varPos3); if (modelLen < 0) { throw ProtocolException.negativeLength("Model", modelLen); @@ -393,7 +393,7 @@ public class BlockType { } if ((nullBits[1] & 8) != 0) { - int varPos4 = offset + 259 + buf.getIntLE(offset + 179); + int varPos4 = offset + 260 + buf.getIntLE(offset + 180); int modelTextureCount = VarInt.peek(buf, varPos4); if (modelTextureCount < 0) { throw ProtocolException.negativeLength("ModelTexture", modelTextureCount); @@ -418,7 +418,7 @@ public class BlockType { } if ((nullBits[1] & 16) != 0) { - int varPos5 = offset + 259 + buf.getIntLE(offset + 183); + int varPos5 = offset + 260 + buf.getIntLE(offset + 184); int modelAnimationLen = VarInt.peek(buf, varPos5); if (modelAnimationLen < 0) { throw ProtocolException.negativeLength("ModelAnimation", modelAnimationLen); @@ -432,7 +432,7 @@ public class BlockType { } if ((nullBits[1] & 32) != 0) { - int varPos6 = offset + 259 + buf.getIntLE(offset + 187); + int varPos6 = offset + 260 + buf.getIntLE(offset + 188); int supportCount = VarInt.peek(buf, varPos6); if (supportCount < 0) { throw ProtocolException.negativeLength("Support", supportCount); @@ -477,7 +477,7 @@ public class BlockType { } if ((nullBits[1] & 64) != 0) { - int varPos7 = offset + 259 + buf.getIntLE(offset + 191); + int varPos7 = offset + 260 + buf.getIntLE(offset + 192); int supportingCount = VarInt.peek(buf, varPos7); if (supportingCount < 0) { throw ProtocolException.negativeLength("Supporting", supportingCount); @@ -522,7 +522,7 @@ public class BlockType { } if ((nullBits[1] & 128) != 0) { - int varPos8 = offset + 259 + buf.getIntLE(offset + 195); + int varPos8 = offset + 260 + buf.getIntLE(offset + 196); int cubeTexturesCount = VarInt.peek(buf, varPos8); if (cubeTexturesCount < 0) { throw ProtocolException.negativeLength("CubeTextures", cubeTexturesCount); @@ -547,7 +547,7 @@ public class BlockType { } if ((nullBits[2] & 1) != 0) { - int varPos9 = offset + 259 + buf.getIntLE(offset + 199); + int varPos9 = offset + 260 + buf.getIntLE(offset + 200); int cubeSideMaskTextureLen = VarInt.peek(buf, varPos9); if (cubeSideMaskTextureLen < 0) { throw ProtocolException.negativeLength("CubeSideMaskTexture", cubeSideMaskTextureLen); @@ -561,7 +561,7 @@ public class BlockType { } if ((nullBits[2] & 2) != 0) { - int varPos10 = offset + 259 + buf.getIntLE(offset + 203); + int varPos10 = offset + 260 + buf.getIntLE(offset + 204); int particlesCount = VarInt.peek(buf, varPos10); if (particlesCount < 0) { throw ProtocolException.negativeLength("Particles", particlesCount); @@ -586,7 +586,7 @@ public class BlockType { } if ((nullBits[2] & 4) != 0) { - int varPos11 = offset + 259 + buf.getIntLE(offset + 207); + int varPos11 = offset + 260 + buf.getIntLE(offset + 208); int blockParticleSetIdLen = VarInt.peek(buf, varPos11); if (blockParticleSetIdLen < 0) { throw ProtocolException.negativeLength("BlockParticleSetId", blockParticleSetIdLen); @@ -600,7 +600,7 @@ public class BlockType { } if ((nullBits[2] & 8) != 0) { - int varPos12 = offset + 259 + buf.getIntLE(offset + 211); + int varPos12 = offset + 260 + buf.getIntLE(offset + 212); int blockBreakingDecalIdLen = VarInt.peek(buf, varPos12); if (blockBreakingDecalIdLen < 0) { throw ProtocolException.negativeLength("BlockBreakingDecalId", blockBreakingDecalIdLen); @@ -614,7 +614,7 @@ public class BlockType { } if ((nullBits[2] & 16) != 0) { - int varPos13 = offset + 259 + buf.getIntLE(offset + 215); + int varPos13 = offset + 260 + buf.getIntLE(offset + 216); int transitionTextureLen = VarInt.peek(buf, varPos13); if (transitionTextureLen < 0) { throw ProtocolException.negativeLength("TransitionTexture", transitionTextureLen); @@ -628,7 +628,7 @@ public class BlockType { } if ((nullBits[2] & 32) != 0) { - int varPos14 = offset + 259 + buf.getIntLE(offset + 219); + int varPos14 = offset + 260 + buf.getIntLE(offset + 220); int transitionToGroupsCount = VarInt.peek(buf, varPos14); if (transitionToGroupsCount < 0) { throw ProtocolException.negativeLength("TransitionToGroups", transitionToGroupsCount); @@ -651,7 +651,7 @@ public class BlockType { } if ((nullBits[2] & 64) != 0) { - int varPos15 = offset + 259 + buf.getIntLE(offset + 223); + int varPos15 = offset + 260 + buf.getIntLE(offset + 224); int interactionHintLen = VarInt.peek(buf, varPos15); if (interactionHintLen < 0) { throw ProtocolException.negativeLength("InteractionHint", interactionHintLen); @@ -665,22 +665,22 @@ public class BlockType { } if ((nullBits[2] & 128) != 0) { - int varPos16 = offset + 259 + buf.getIntLE(offset + 227); + int varPos16 = offset + 260 + buf.getIntLE(offset + 228); obj.gathering = BlockGathering.deserialize(buf, varPos16); } if ((nullBits[3] & 1) != 0) { - int varPos17 = offset + 259 + buf.getIntLE(offset + 231); + int varPos17 = offset + 260 + buf.getIntLE(offset + 232); obj.display = ModelDisplay.deserialize(buf, varPos17); } if ((nullBits[3] & 2) != 0) { - int varPos18 = offset + 259 + buf.getIntLE(offset + 235); + int varPos18 = offset + 260 + buf.getIntLE(offset + 236); obj.rail = RailConfig.deserialize(buf, varPos18); } if ((nullBits[3] & 4) != 0) { - int varPos19 = offset + 259 + buf.getIntLE(offset + 239); + int varPos19 = offset + 260 + buf.getIntLE(offset + 240); int interactionsCount = VarInt.peek(buf, varPos19); if (interactionsCount < 0) { throw ProtocolException.negativeLength("Interactions", interactionsCount); @@ -705,7 +705,7 @@ public class BlockType { } if ((nullBits[3] & 8) != 0) { - int varPos20 = offset + 259 + buf.getIntLE(offset + 243); + int varPos20 = offset + 260 + buf.getIntLE(offset + 244); int statesCount = VarInt.peek(buf, varPos20); if (statesCount < 0) { throw ProtocolException.negativeLength("States", statesCount); @@ -741,7 +741,7 @@ public class BlockType { } if ((nullBits[3] & 16) != 0) { - int varPos21 = offset + 259 + buf.getIntLE(offset + 247); + int varPos21 = offset + 260 + buf.getIntLE(offset + 248); int tagIndexesCount = VarInt.peek(buf, varPos21); if (tagIndexesCount < 0) { throw ProtocolException.negativeLength("TagIndexes", tagIndexesCount); @@ -764,12 +764,12 @@ public class BlockType { } if ((nullBits[3] & 32) != 0) { - int varPos22 = offset + 259 + buf.getIntLE(offset + 251); + int varPos22 = offset + 260 + buf.getIntLE(offset + 252); obj.bench = Bench.deserialize(buf, varPos22); } if ((nullBits[3] & 64) != 0) { - int varPos23 = offset + 259 + buf.getIntLE(offset + 255); + int varPos23 = offset + 260 + buf.getIntLE(offset + 256); obj.connectedBlockRuleSet = ConnectedBlockRuleSet.deserialize(buf, varPos23); } @@ -778,10 +778,10 @@ public class BlockType { public static int computeBytesConsumed(@Nonnull ByteBuf buf, int offset) { byte[] nullBits = PacketIO.readBytes(buf, offset, 4); - int maxEnd = 259; + int maxEnd = 260; if ((nullBits[0] & 128) != 0) { - int fieldOffset0 = buf.getIntLE(offset + 163); - int pos0 = offset + 259 + fieldOffset0; + int fieldOffset0 = buf.getIntLE(offset + 164); + int pos0 = offset + 260 + fieldOffset0; int sl = VarInt.peek(buf, pos0); pos0 += VarInt.length(buf, pos0) + sl; if (pos0 - offset > maxEnd) { @@ -790,8 +790,8 @@ public class BlockType { } if ((nullBits[1] & 1) != 0) { - int fieldOffset1 = buf.getIntLE(offset + 167); - int pos1 = offset + 259 + fieldOffset1; + int fieldOffset1 = buf.getIntLE(offset + 168); + int pos1 = offset + 260 + fieldOffset1; int sl = VarInt.peek(buf, pos1); pos1 += VarInt.length(buf, pos1) + sl; if (pos1 - offset > maxEnd) { @@ -800,8 +800,8 @@ public class BlockType { } if ((nullBits[1] & 2) != 0) { - int fieldOffset2 = buf.getIntLE(offset + 171); - int pos2 = offset + 259 + fieldOffset2; + int fieldOffset2 = buf.getIntLE(offset + 172); + int pos2 = offset + 260 + fieldOffset2; int arrLen = VarInt.peek(buf, pos2); pos2 += VarInt.length(buf, pos2) + arrLen * 1; if (pos2 - offset > maxEnd) { @@ -810,8 +810,8 @@ public class BlockType { } if ((nullBits[1] & 4) != 0) { - int fieldOffset3 = buf.getIntLE(offset + 175); - int pos3 = offset + 259 + fieldOffset3; + int fieldOffset3 = buf.getIntLE(offset + 176); + int pos3 = offset + 260 + fieldOffset3; int sl = VarInt.peek(buf, pos3); pos3 += VarInt.length(buf, pos3) + sl; if (pos3 - offset > maxEnd) { @@ -820,8 +820,8 @@ public class BlockType { } if ((nullBits[1] & 8) != 0) { - int fieldOffset4 = buf.getIntLE(offset + 179); - int pos4 = offset + 259 + fieldOffset4; + int fieldOffset4 = buf.getIntLE(offset + 180); + int pos4 = offset + 260 + fieldOffset4; int arrLen = VarInt.peek(buf, pos4); pos4 += VarInt.length(buf, pos4); @@ -835,8 +835,8 @@ public class BlockType { } if ((nullBits[1] & 16) != 0) { - int fieldOffset5 = buf.getIntLE(offset + 183); - int pos5 = offset + 259 + fieldOffset5; + int fieldOffset5 = buf.getIntLE(offset + 184); + int pos5 = offset + 260 + fieldOffset5; int sl = VarInt.peek(buf, pos5); pos5 += VarInt.length(buf, pos5) + sl; if (pos5 - offset > maxEnd) { @@ -845,8 +845,8 @@ public class BlockType { } if ((nullBits[1] & 32) != 0) { - int fieldOffset6 = buf.getIntLE(offset + 187); - int pos6 = offset + 259 + fieldOffset6; + int fieldOffset6 = buf.getIntLE(offset + 188); + int pos6 = offset + 260 + fieldOffset6; int dictLen = VarInt.peek(buf, pos6); pos6 += VarInt.length(buf, pos6); @@ -865,8 +865,8 @@ public class BlockType { } if ((nullBits[1] & 64) != 0) { - int fieldOffset7 = buf.getIntLE(offset + 191); - int pos7 = offset + 259 + fieldOffset7; + int fieldOffset7 = buf.getIntLE(offset + 192); + int pos7 = offset + 260 + fieldOffset7; int dictLen = VarInt.peek(buf, pos7); pos7 += VarInt.length(buf, pos7); @@ -885,8 +885,8 @@ public class BlockType { } if ((nullBits[1] & 128) != 0) { - int fieldOffset8 = buf.getIntLE(offset + 195); - int pos8 = offset + 259 + fieldOffset8; + int fieldOffset8 = buf.getIntLE(offset + 196); + int pos8 = offset + 260 + fieldOffset8; int arrLen = VarInt.peek(buf, pos8); pos8 += VarInt.length(buf, pos8); @@ -900,8 +900,8 @@ public class BlockType { } if ((nullBits[2] & 1) != 0) { - int fieldOffset9 = buf.getIntLE(offset + 199); - int pos9 = offset + 259 + fieldOffset9; + int fieldOffset9 = buf.getIntLE(offset + 200); + int pos9 = offset + 260 + fieldOffset9; int sl = VarInt.peek(buf, pos9); pos9 += VarInt.length(buf, pos9) + sl; if (pos9 - offset > maxEnd) { @@ -910,8 +910,8 @@ public class BlockType { } if ((nullBits[2] & 2) != 0) { - int fieldOffset10 = buf.getIntLE(offset + 203); - int pos10 = offset + 259 + fieldOffset10; + int fieldOffset10 = buf.getIntLE(offset + 204); + int pos10 = offset + 260 + fieldOffset10; int arrLen = VarInt.peek(buf, pos10); pos10 += VarInt.length(buf, pos10); @@ -925,8 +925,8 @@ public class BlockType { } if ((nullBits[2] & 4) != 0) { - int fieldOffset11 = buf.getIntLE(offset + 207); - int pos11 = offset + 259 + fieldOffset11; + int fieldOffset11 = buf.getIntLE(offset + 208); + int pos11 = offset + 260 + fieldOffset11; int sl = VarInt.peek(buf, pos11); pos11 += VarInt.length(buf, pos11) + sl; if (pos11 - offset > maxEnd) { @@ -935,8 +935,8 @@ public class BlockType { } if ((nullBits[2] & 8) != 0) { - int fieldOffset12 = buf.getIntLE(offset + 211); - int pos12 = offset + 259 + fieldOffset12; + int fieldOffset12 = buf.getIntLE(offset + 212); + int pos12 = offset + 260 + fieldOffset12; int sl = VarInt.peek(buf, pos12); pos12 += VarInt.length(buf, pos12) + sl; if (pos12 - offset > maxEnd) { @@ -945,8 +945,8 @@ public class BlockType { } if ((nullBits[2] & 16) != 0) { - int fieldOffset13 = buf.getIntLE(offset + 215); - int pos13 = offset + 259 + fieldOffset13; + int fieldOffset13 = buf.getIntLE(offset + 216); + int pos13 = offset + 260 + fieldOffset13; int sl = VarInt.peek(buf, pos13); pos13 += VarInt.length(buf, pos13) + sl; if (pos13 - offset > maxEnd) { @@ -955,8 +955,8 @@ public class BlockType { } if ((nullBits[2] & 32) != 0) { - int fieldOffset14 = buf.getIntLE(offset + 219); - int pos14 = offset + 259 + fieldOffset14; + int fieldOffset14 = buf.getIntLE(offset + 220); + int pos14 = offset + 260 + fieldOffset14; int arrLen = VarInt.peek(buf, pos14); pos14 += VarInt.length(buf, pos14) + arrLen * 4; if (pos14 - offset > maxEnd) { @@ -965,8 +965,8 @@ public class BlockType { } if ((nullBits[2] & 64) != 0) { - int fieldOffset15 = buf.getIntLE(offset + 223); - int pos15 = offset + 259 + fieldOffset15; + int fieldOffset15 = buf.getIntLE(offset + 224); + int pos15 = offset + 260 + fieldOffset15; int sl = VarInt.peek(buf, pos15); pos15 += VarInt.length(buf, pos15) + sl; if (pos15 - offset > maxEnd) { @@ -975,8 +975,8 @@ public class BlockType { } if ((nullBits[2] & 128) != 0) { - int fieldOffset16 = buf.getIntLE(offset + 227); - int pos16 = offset + 259 + fieldOffset16; + int fieldOffset16 = buf.getIntLE(offset + 228); + int pos16 = offset + 260 + fieldOffset16; pos16 += BlockGathering.computeBytesConsumed(buf, pos16); if (pos16 - offset > maxEnd) { maxEnd = pos16 - offset; @@ -984,8 +984,8 @@ public class BlockType { } if ((nullBits[3] & 1) != 0) { - int fieldOffset17 = buf.getIntLE(offset + 231); - int pos17 = offset + 259 + fieldOffset17; + int fieldOffset17 = buf.getIntLE(offset + 232); + int pos17 = offset + 260 + fieldOffset17; pos17 += ModelDisplay.computeBytesConsumed(buf, pos17); if (pos17 - offset > maxEnd) { maxEnd = pos17 - offset; @@ -993,8 +993,8 @@ public class BlockType { } if ((nullBits[3] & 2) != 0) { - int fieldOffset18 = buf.getIntLE(offset + 235); - int pos18 = offset + 259 + fieldOffset18; + int fieldOffset18 = buf.getIntLE(offset + 236); + int pos18 = offset + 260 + fieldOffset18; pos18 += RailConfig.computeBytesConsumed(buf, pos18); if (pos18 - offset > maxEnd) { maxEnd = pos18 - offset; @@ -1002,8 +1002,8 @@ public class BlockType { } if ((nullBits[3] & 4) != 0) { - int fieldOffset19 = buf.getIntLE(offset + 239); - int pos19 = offset + 259 + fieldOffset19; + int fieldOffset19 = buf.getIntLE(offset + 240); + int pos19 = offset + 260 + fieldOffset19; int dictLen = VarInt.peek(buf, pos19); pos19 += VarInt.length(buf, pos19); @@ -1017,8 +1017,8 @@ public class BlockType { } if ((nullBits[3] & 8) != 0) { - int fieldOffset20 = buf.getIntLE(offset + 243); - int pos20 = offset + 259 + fieldOffset20; + int fieldOffset20 = buf.getIntLE(offset + 244); + int pos20 = offset + 260 + fieldOffset20; int dictLen = VarInt.peek(buf, pos20); pos20 += VarInt.length(buf, pos20); @@ -1034,8 +1034,8 @@ public class BlockType { } if ((nullBits[3] & 16) != 0) { - int fieldOffset21 = buf.getIntLE(offset + 247); - int pos21 = offset + 259 + fieldOffset21; + int fieldOffset21 = buf.getIntLE(offset + 248); + int pos21 = offset + 260 + fieldOffset21; int arrLen = VarInt.peek(buf, pos21); pos21 += VarInt.length(buf, pos21) + arrLen * 4; if (pos21 - offset > maxEnd) { @@ -1044,8 +1044,8 @@ public class BlockType { } if ((nullBits[3] & 32) != 0) { - int fieldOffset22 = buf.getIntLE(offset + 251); - int pos22 = offset + 259 + fieldOffset22; + int fieldOffset22 = buf.getIntLE(offset + 252); + int pos22 = offset + 260 + fieldOffset22; pos22 += Bench.computeBytesConsumed(buf, pos22); if (pos22 - offset > maxEnd) { maxEnd = pos22 - offset; @@ -1053,8 +1053,8 @@ public class BlockType { } if ((nullBits[3] & 64) != 0) { - int fieldOffset23 = buf.getIntLE(offset + 255); - int pos23 = offset + 259 + fieldOffset23; + int fieldOffset23 = buf.getIntLE(offset + 256); + int pos23 = offset + 260 + fieldOffset23; pos23 += ConnectedBlockRuleSet.computeBytesConsumed(buf, pos23); if (pos23 - offset > maxEnd) { maxEnd = pos23 - offset; @@ -1249,7 +1249,7 @@ public class BlockType { if (this.placementSettings != null) { this.placementSettings.serialize(buf); } else { - buf.writeZero(16); + buf.writeZero(17); } buf.writeByte(this.ignoreSupportWhenPlaced ? 1 : 0); @@ -1565,7 +1565,7 @@ public class BlockType { } public int computeSize() { - int size = 259; + int size = 260; if (this.item != null) { size += PacketIO.stringSize(this.item); } @@ -1702,17 +1702,17 @@ public class BlockType { } public static ValidationResult validateStructure(@Nonnull ByteBuf buffer, int offset) { - if (buffer.readableBytes() - offset < 259) { - return ValidationResult.error("Buffer too small: expected at least 259 bytes"); + if (buffer.readableBytes() - offset < 260) { + return ValidationResult.error("Buffer too small: expected at least 260 bytes"); } else { byte[] nullBits = PacketIO.readBytes(buffer, offset, 4); if ((nullBits[0] & 128) != 0) { - int itemOffset = buffer.getIntLE(offset + 163); + int itemOffset = buffer.getIntLE(offset + 164); if (itemOffset < 0) { return ValidationResult.error("Invalid offset for Item"); } - int pos = offset + 259 + itemOffset; + int pos = offset + 260 + itemOffset; if (pos >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Item"); } @@ -1734,12 +1734,12 @@ public class BlockType { } if ((nullBits[1] & 1) != 0) { - int nameOffset = buffer.getIntLE(offset + 167); + int nameOffset = buffer.getIntLE(offset + 168); if (nameOffset < 0) { return ValidationResult.error("Invalid offset for Name"); } - int posx = offset + 259 + nameOffset; + int posx = offset + 260 + nameOffset; if (posx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Name"); } @@ -1761,12 +1761,12 @@ public class BlockType { } if ((nullBits[1] & 2) != 0) { - int shaderEffectOffset = buffer.getIntLE(offset + 171); + int shaderEffectOffset = buffer.getIntLE(offset + 172); if (shaderEffectOffset < 0) { return ValidationResult.error("Invalid offset for ShaderEffect"); } - int posxx = offset + 259 + shaderEffectOffset; + int posxx = offset + 260 + shaderEffectOffset; if (posxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for ShaderEffect"); } @@ -1788,12 +1788,12 @@ public class BlockType { } if ((nullBits[1] & 4) != 0) { - int modelOffset = buffer.getIntLE(offset + 175); + int modelOffset = buffer.getIntLE(offset + 176); if (modelOffset < 0) { return ValidationResult.error("Invalid offset for Model"); } - int posxxx = offset + 259 + modelOffset; + int posxxx = offset + 260 + modelOffset; if (posxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Model"); } @@ -1815,12 +1815,12 @@ public class BlockType { } if ((nullBits[1] & 8) != 0) { - int modelTextureOffset = buffer.getIntLE(offset + 179); + int modelTextureOffset = buffer.getIntLE(offset + 180); if (modelTextureOffset < 0) { return ValidationResult.error("Invalid offset for ModelTexture"); } - int posxxxx = offset + 259 + modelTextureOffset; + int posxxxx = offset + 260 + modelTextureOffset; if (posxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for ModelTexture"); } @@ -1847,12 +1847,12 @@ public class BlockType { } if ((nullBits[1] & 16) != 0) { - int modelAnimationOffset = buffer.getIntLE(offset + 183); + int modelAnimationOffset = buffer.getIntLE(offset + 184); if (modelAnimationOffset < 0) { return ValidationResult.error("Invalid offset for ModelAnimation"); } - int posxxxxx = offset + 259 + modelAnimationOffset; + int posxxxxx = offset + 260 + modelAnimationOffset; if (posxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for ModelAnimation"); } @@ -1874,12 +1874,12 @@ public class BlockType { } if ((nullBits[1] & 32) != 0) { - int supportOffset = buffer.getIntLE(offset + 187); + int supportOffset = buffer.getIntLE(offset + 188); if (supportOffset < 0) { return ValidationResult.error("Invalid offset for Support"); } - int posxxxxxx = offset + 259 + supportOffset; + int posxxxxxx = offset + 260 + supportOffset; if (posxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Support"); } @@ -1910,12 +1910,12 @@ public class BlockType { } if ((nullBits[1] & 64) != 0) { - int supportingOffset = buffer.getIntLE(offset + 191); + int supportingOffset = buffer.getIntLE(offset + 192); if (supportingOffset < 0) { return ValidationResult.error("Invalid offset for Supporting"); } - int posxxxxxxx = offset + 259 + supportingOffset; + int posxxxxxxx = offset + 260 + supportingOffset; if (posxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Supporting"); } @@ -1946,12 +1946,12 @@ public class BlockType { } if ((nullBits[1] & 128) != 0) { - int cubeTexturesOffset = buffer.getIntLE(offset + 195); + int cubeTexturesOffset = buffer.getIntLE(offset + 196); if (cubeTexturesOffset < 0) { return ValidationResult.error("Invalid offset for CubeTextures"); } - int posxxxxxxxx = offset + 259 + cubeTexturesOffset; + int posxxxxxxxx = offset + 260 + cubeTexturesOffset; if (posxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for CubeTextures"); } @@ -1978,12 +1978,12 @@ public class BlockType { } if ((nullBits[2] & 1) != 0) { - int cubeSideMaskTextureOffset = buffer.getIntLE(offset + 199); + int cubeSideMaskTextureOffset = buffer.getIntLE(offset + 200); if (cubeSideMaskTextureOffset < 0) { return ValidationResult.error("Invalid offset for CubeSideMaskTexture"); } - int posxxxxxxxxx = offset + 259 + cubeSideMaskTextureOffset; + int posxxxxxxxxx = offset + 260 + cubeSideMaskTextureOffset; if (posxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for CubeSideMaskTexture"); } @@ -2005,12 +2005,12 @@ public class BlockType { } if ((nullBits[2] & 2) != 0) { - int particlesOffset = buffer.getIntLE(offset + 203); + int particlesOffset = buffer.getIntLE(offset + 204); if (particlesOffset < 0) { return ValidationResult.error("Invalid offset for Particles"); } - int posxxxxxxxxxx = offset + 259 + particlesOffset; + int posxxxxxxxxxx = offset + 260 + particlesOffset; if (posxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Particles"); } @@ -2037,12 +2037,12 @@ public class BlockType { } if ((nullBits[2] & 4) != 0) { - int blockParticleSetIdOffset = buffer.getIntLE(offset + 207); + int blockParticleSetIdOffset = buffer.getIntLE(offset + 208); if (blockParticleSetIdOffset < 0) { return ValidationResult.error("Invalid offset for BlockParticleSetId"); } - int posxxxxxxxxxxx = offset + 259 + blockParticleSetIdOffset; + int posxxxxxxxxxxx = offset + 260 + blockParticleSetIdOffset; if (posxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for BlockParticleSetId"); } @@ -2064,12 +2064,12 @@ public class BlockType { } if ((nullBits[2] & 8) != 0) { - int blockBreakingDecalIdOffset = buffer.getIntLE(offset + 211); + int blockBreakingDecalIdOffset = buffer.getIntLE(offset + 212); if (blockBreakingDecalIdOffset < 0) { return ValidationResult.error("Invalid offset for BlockBreakingDecalId"); } - int posxxxxxxxxxxxx = offset + 259 + blockBreakingDecalIdOffset; + int posxxxxxxxxxxxx = offset + 260 + blockBreakingDecalIdOffset; if (posxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for BlockBreakingDecalId"); } @@ -2091,12 +2091,12 @@ public class BlockType { } if ((nullBits[2] & 16) != 0) { - int transitionTextureOffset = buffer.getIntLE(offset + 215); + int transitionTextureOffset = buffer.getIntLE(offset + 216); if (transitionTextureOffset < 0) { return ValidationResult.error("Invalid offset for TransitionTexture"); } - int posxxxxxxxxxxxxx = offset + 259 + transitionTextureOffset; + int posxxxxxxxxxxxxx = offset + 260 + transitionTextureOffset; if (posxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for TransitionTexture"); } @@ -2118,12 +2118,12 @@ public class BlockType { } if ((nullBits[2] & 32) != 0) { - int transitionToGroupsOffset = buffer.getIntLE(offset + 219); + int transitionToGroupsOffset = buffer.getIntLE(offset + 220); if (transitionToGroupsOffset < 0) { return ValidationResult.error("Invalid offset for TransitionToGroups"); } - int posxxxxxxxxxxxxxx = offset + 259 + transitionToGroupsOffset; + int posxxxxxxxxxxxxxx = offset + 260 + transitionToGroupsOffset; if (posxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for TransitionToGroups"); } @@ -2145,12 +2145,12 @@ public class BlockType { } if ((nullBits[2] & 64) != 0) { - int interactionHintOffset = buffer.getIntLE(offset + 223); + int interactionHintOffset = buffer.getIntLE(offset + 224); if (interactionHintOffset < 0) { return ValidationResult.error("Invalid offset for InteractionHint"); } - int posxxxxxxxxxxxxxxx = offset + 259 + interactionHintOffset; + int posxxxxxxxxxxxxxxx = offset + 260 + interactionHintOffset; if (posxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for InteractionHint"); } @@ -2172,12 +2172,12 @@ public class BlockType { } if ((nullBits[2] & 128) != 0) { - int gatheringOffset = buffer.getIntLE(offset + 227); + int gatheringOffset = buffer.getIntLE(offset + 228); if (gatheringOffset < 0) { return ValidationResult.error("Invalid offset for Gathering"); } - int posxxxxxxxxxxxxxxxx = offset + 259 + gatheringOffset; + int posxxxxxxxxxxxxxxxx = offset + 260 + gatheringOffset; if (posxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Gathering"); } @@ -2191,12 +2191,12 @@ public class BlockType { } if ((nullBits[3] & 1) != 0) { - int displayOffset = buffer.getIntLE(offset + 231); + int displayOffset = buffer.getIntLE(offset + 232); if (displayOffset < 0) { return ValidationResult.error("Invalid offset for Display"); } - int posxxxxxxxxxxxxxxxxx = offset + 259 + displayOffset; + int posxxxxxxxxxxxxxxxxx = offset + 260 + displayOffset; if (posxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Display"); } @@ -2210,12 +2210,12 @@ public class BlockType { } if ((nullBits[3] & 2) != 0) { - int railOffset = buffer.getIntLE(offset + 235); + int railOffset = buffer.getIntLE(offset + 236); if (railOffset < 0) { return ValidationResult.error("Invalid offset for Rail"); } - int posxxxxxxxxxxxxxxxxxx = offset + 259 + railOffset; + int posxxxxxxxxxxxxxxxxxx = offset + 260 + railOffset; if (posxxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Rail"); } @@ -2229,12 +2229,12 @@ public class BlockType { } if ((nullBits[3] & 4) != 0) { - int interactionsOffset = buffer.getIntLE(offset + 239); + int interactionsOffset = buffer.getIntLE(offset + 240); if (interactionsOffset < 0) { return ValidationResult.error("Invalid offset for Interactions"); } - int posxxxxxxxxxxxxxxxxxxx = offset + 259 + interactionsOffset; + int posxxxxxxxxxxxxxxxxxxx = offset + 260 + interactionsOffset; if (posxxxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Interactions"); } @@ -2259,12 +2259,12 @@ public class BlockType { } if ((nullBits[3] & 8) != 0) { - int statesOffset = buffer.getIntLE(offset + 243); + int statesOffset = buffer.getIntLE(offset + 244); if (statesOffset < 0) { return ValidationResult.error("Invalid offset for States"); } - int posxxxxxxxxxxxxxxxxxxxx = offset + 259 + statesOffset; + int posxxxxxxxxxxxxxxxxxxxx = offset + 260 + statesOffset; if (posxxxxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for States"); } @@ -2304,12 +2304,12 @@ public class BlockType { } if ((nullBits[3] & 16) != 0) { - int tagIndexesOffset = buffer.getIntLE(offset + 247); + int tagIndexesOffset = buffer.getIntLE(offset + 248); if (tagIndexesOffset < 0) { return ValidationResult.error("Invalid offset for TagIndexes"); } - int posxxxxxxxxxxxxxxxxxxxxx = offset + 259 + tagIndexesOffset; + int posxxxxxxxxxxxxxxxxxxxxx = offset + 260 + tagIndexesOffset; if (posxxxxxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for TagIndexes"); } @@ -2331,12 +2331,12 @@ public class BlockType { } if ((nullBits[3] & 32) != 0) { - int benchOffset = buffer.getIntLE(offset + 251); + int benchOffset = buffer.getIntLE(offset + 252); if (benchOffset < 0) { return ValidationResult.error("Invalid offset for Bench"); } - int posxxxxxxxxxxxxxxxxxxxxxx = offset + 259 + benchOffset; + int posxxxxxxxxxxxxxxxxxxxxxx = offset + 260 + benchOffset; if (posxxxxxxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Bench"); } @@ -2350,12 +2350,12 @@ public class BlockType { } if ((nullBits[3] & 64) != 0) { - int connectedBlockRuleSetOffset = buffer.getIntLE(offset + 255); + int connectedBlockRuleSetOffset = buffer.getIntLE(offset + 256); if (connectedBlockRuleSetOffset < 0) { return ValidationResult.error("Invalid offset for ConnectedBlockRuleSet"); } - int posxxxxxxxxxxxxxxxxxxxxxxx = offset + 259 + connectedBlockRuleSetOffset; + int posxxxxxxxxxxxxxxxxxxxxxxx = offset + 260 + connectedBlockRuleSetOffset; if (posxxxxxxxxxxxxxxxxxxxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for ConnectedBlockRuleSet"); } diff --git a/src/com/hypixel/hytale/protocol/DebugShape.java b/src/com/hypixel/hytale/protocol/DebugShape.java index f2756293..1b77bdb5 100644 --- a/src/com/hypixel/hytale/protocol/DebugShape.java +++ b/src/com/hypixel/hytale/protocol/DebugShape.java @@ -7,7 +7,9 @@ public enum DebugShape { Cylinder(1), Cone(2), Cube(3), - Frustum(4); + Frustum(4), + Sector(5), + Disc(6); public static final DebugShape[] VALUES = values(); private final int value; diff --git a/src/com/hypixel/hytale/protocol/EntityStatType.java b/src/com/hypixel/hytale/protocol/EntityStatType.java index 5d72ac67..42e0b972 100644 --- a/src/com/hypixel/hytale/protocol/EntityStatType.java +++ b/src/com/hypixel/hytale/protocol/EntityStatType.java @@ -11,9 +11,9 @@ import javax.annotation.Nullable; public class EntityStatType { public static final int NULLABLE_BIT_FIELD_SIZE = 1; - public static final int FIXED_BLOCK_SIZE = 14; + public static final int FIXED_BLOCK_SIZE = 15; public static final int VARIABLE_FIELD_COUNT = 3; - public static final int VARIABLE_BLOCK_START = 26; + public static final int VARIABLE_BLOCK_START = 27; public static final int MAX_SIZE = 1677721600; @Nullable public String id; @@ -26,6 +26,7 @@ public class EntityStatType { public EntityStatEffects maxValueEffects; @Nonnull public EntityStatResetBehavior resetBehavior = EntityStatResetBehavior.InitialValue; + public boolean hideFromTooltip; public EntityStatType() { } @@ -37,7 +38,8 @@ public class EntityStatType { float max, @Nullable EntityStatEffects minValueEffects, @Nullable EntityStatEffects maxValueEffects, - @Nonnull EntityStatResetBehavior resetBehavior + @Nonnull EntityStatResetBehavior resetBehavior, + boolean hideFromTooltip ) { this.id = id; this.value = value; @@ -46,6 +48,7 @@ public class EntityStatType { this.minValueEffects = minValueEffects; this.maxValueEffects = maxValueEffects; this.resetBehavior = resetBehavior; + this.hideFromTooltip = hideFromTooltip; } public EntityStatType(@Nonnull EntityStatType other) { @@ -56,6 +59,7 @@ public class EntityStatType { this.minValueEffects = other.minValueEffects; this.maxValueEffects = other.maxValueEffects; this.resetBehavior = other.resetBehavior; + this.hideFromTooltip = other.hideFromTooltip; } @Nonnull @@ -66,8 +70,9 @@ public class EntityStatType { obj.min = buf.getFloatLE(offset + 5); obj.max = buf.getFloatLE(offset + 9); obj.resetBehavior = EntityStatResetBehavior.fromValue(buf.getByte(offset + 13)); + obj.hideFromTooltip = buf.getByte(offset + 14) != 0; if ((nullBits & 1) != 0) { - int varPos0 = offset + 26 + buf.getIntLE(offset + 14); + int varPos0 = offset + 27 + buf.getIntLE(offset + 15); int idLen = VarInt.peek(buf, varPos0); if (idLen < 0) { throw ProtocolException.negativeLength("Id", idLen); @@ -81,12 +86,12 @@ public class EntityStatType { } if ((nullBits & 2) != 0) { - int varPos1 = offset + 26 + buf.getIntLE(offset + 18); + int varPos1 = offset + 27 + buf.getIntLE(offset + 19); obj.minValueEffects = EntityStatEffects.deserialize(buf, varPos1); } if ((nullBits & 4) != 0) { - int varPos2 = offset + 26 + buf.getIntLE(offset + 22); + int varPos2 = offset + 27 + buf.getIntLE(offset + 23); obj.maxValueEffects = EntityStatEffects.deserialize(buf, varPos2); } @@ -95,10 +100,10 @@ public class EntityStatType { public static int computeBytesConsumed(@Nonnull ByteBuf buf, int offset) { byte nullBits = buf.getByte(offset); - int maxEnd = 26; + int maxEnd = 27; if ((nullBits & 1) != 0) { - int fieldOffset0 = buf.getIntLE(offset + 14); - int pos0 = offset + 26 + fieldOffset0; + int fieldOffset0 = buf.getIntLE(offset + 15); + int pos0 = offset + 27 + fieldOffset0; int sl = VarInt.peek(buf, pos0); pos0 += VarInt.length(buf, pos0) + sl; if (pos0 - offset > maxEnd) { @@ -107,8 +112,8 @@ public class EntityStatType { } if ((nullBits & 2) != 0) { - int fieldOffset1 = buf.getIntLE(offset + 18); - int pos1 = offset + 26 + fieldOffset1; + int fieldOffset1 = buf.getIntLE(offset + 19); + int pos1 = offset + 27 + fieldOffset1; pos1 += EntityStatEffects.computeBytesConsumed(buf, pos1); if (pos1 - offset > maxEnd) { maxEnd = pos1 - offset; @@ -116,8 +121,8 @@ public class EntityStatType { } if ((nullBits & 4) != 0) { - int fieldOffset2 = buf.getIntLE(offset + 22); - int pos2 = offset + 26 + fieldOffset2; + int fieldOffset2 = buf.getIntLE(offset + 23); + int pos2 = offset + 27 + fieldOffset2; pos2 += EntityStatEffects.computeBytesConsumed(buf, pos2); if (pos2 - offset > maxEnd) { maxEnd = pos2 - offset; @@ -147,6 +152,7 @@ public class EntityStatType { buf.writeFloatLE(this.min); buf.writeFloatLE(this.max); buf.writeByte(this.resetBehavior.getValue()); + buf.writeByte(this.hideFromTooltip ? 1 : 0); int idOffsetSlot = buf.writerIndex(); buf.writeIntLE(0); int minValueEffectsOffsetSlot = buf.writerIndex(); @@ -177,7 +183,7 @@ public class EntityStatType { } public int computeSize() { - int size = 26; + int size = 27; if (this.id != null) { size += PacketIO.stringSize(this.id); } @@ -194,17 +200,17 @@ public class EntityStatType { } public static ValidationResult validateStructure(@Nonnull ByteBuf buffer, int offset) { - if (buffer.readableBytes() - offset < 26) { - return ValidationResult.error("Buffer too small: expected at least 26 bytes"); + if (buffer.readableBytes() - offset < 27) { + return ValidationResult.error("Buffer too small: expected at least 27 bytes"); } else { byte nullBits = buffer.getByte(offset); if ((nullBits & 1) != 0) { - int idOffset = buffer.getIntLE(offset + 14); + int idOffset = buffer.getIntLE(offset + 15); if (idOffset < 0) { return ValidationResult.error("Invalid offset for Id"); } - int pos = offset + 26 + idOffset; + int pos = offset + 27 + idOffset; if (pos >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Id"); } @@ -226,12 +232,12 @@ public class EntityStatType { } if ((nullBits & 2) != 0) { - int minValueEffectsOffset = buffer.getIntLE(offset + 18); + int minValueEffectsOffset = buffer.getIntLE(offset + 19); if (minValueEffectsOffset < 0) { return ValidationResult.error("Invalid offset for MinValueEffects"); } - int posx = offset + 26 + minValueEffectsOffset; + int posx = offset + 27 + minValueEffectsOffset; if (posx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for MinValueEffects"); } @@ -245,12 +251,12 @@ public class EntityStatType { } if ((nullBits & 4) != 0) { - int maxValueEffectsOffset = buffer.getIntLE(offset + 22); + int maxValueEffectsOffset = buffer.getIntLE(offset + 23); if (maxValueEffectsOffset < 0) { return ValidationResult.error("Invalid offset for MaxValueEffects"); } - int posxx = offset + 26 + maxValueEffectsOffset; + int posxx = offset + 27 + maxValueEffectsOffset; if (posxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for MaxValueEffects"); } @@ -276,6 +282,7 @@ public class EntityStatType { copy.minValueEffects = this.minValueEffects != null ? this.minValueEffects.clone() : null; copy.maxValueEffects = this.maxValueEffects != null ? this.maxValueEffects.clone() : null; copy.resetBehavior = this.resetBehavior; + copy.hideFromTooltip = this.hideFromTooltip; return copy; } @@ -292,12 +299,13 @@ public class EntityStatType { && this.max == other.max && Objects.equals(this.minValueEffects, other.minValueEffects) && Objects.equals(this.maxValueEffects, other.maxValueEffects) - && Objects.equals(this.resetBehavior, other.resetBehavior); + && Objects.equals(this.resetBehavior, other.resetBehavior) + && this.hideFromTooltip == other.hideFromTooltip; } } @Override public int hashCode() { - return Objects.hash(this.id, this.value, this.min, this.max, this.minValueEffects, this.maxValueEffects, this.resetBehavior); + return Objects.hash(this.id, this.value, this.min, this.max, this.minValueEffects, this.maxValueEffects, this.resetBehavior, this.hideFromTooltip); } } diff --git a/src/com/hypixel/hytale/protocol/Fluid.java b/src/com/hypixel/hytale/protocol/Fluid.java index 4c36ee36..881fe2d0 100644 --- a/src/com/hypixel/hytale/protocol/Fluid.java +++ b/src/com/hypixel/hytale/protocol/Fluid.java @@ -12,9 +12,9 @@ import javax.annotation.Nullable; public class Fluid { public static final int NULLABLE_BIT_FIELD_SIZE = 1; - public static final int FIXED_BLOCK_SIZE = 22; - public static final int VARIABLE_FIELD_COUNT = 5; - public static final int VARIABLE_BLOCK_START = 42; + public static final int FIXED_BLOCK_SIZE = 23; + public static final int VARIABLE_FIELD_COUNT = 6; + public static final int VARIABLE_BLOCK_START = 47; public static final int MAX_SIZE = 1677721600; @Nullable public String id; @@ -28,6 +28,10 @@ public class Fluid { public ShaderType[] shaderEffect; @Nullable public ColorLight light; + @Nullable + public ModelParticle[] particles; + @Nonnull + public FluidDrawType drawType = FluidDrawType.None; public int fluidFXIndex; public int blockSoundSetIndex; @Nullable @@ -48,6 +52,8 @@ public class Fluid { @Nonnull Opacity opacity, @Nullable ShaderType[] shaderEffect, @Nullable ColorLight light, + @Nullable ModelParticle[] particles, + @Nonnull FluidDrawType drawType, int fluidFXIndex, int blockSoundSetIndex, @Nullable String blockParticleSetId, @@ -61,6 +67,8 @@ public class Fluid { this.opacity = opacity; this.shaderEffect = shaderEffect; this.light = light; + this.particles = particles; + this.drawType = drawType; this.fluidFXIndex = fluidFXIndex; this.blockSoundSetIndex = blockSoundSetIndex; this.blockParticleSetId = blockParticleSetId; @@ -76,6 +84,8 @@ public class Fluid { this.opacity = other.opacity; this.shaderEffect = other.shaderEffect; this.light = other.light; + this.particles = other.particles; + this.drawType = other.drawType; this.fluidFXIndex = other.fluidFXIndex; this.blockSoundSetIndex = other.blockSoundSetIndex; this.blockParticleSetId = other.blockParticleSetId; @@ -94,14 +104,15 @@ public class Fluid { obj.light = ColorLight.deserialize(buf, offset + 7); } - obj.fluidFXIndex = buf.getIntLE(offset + 11); - obj.blockSoundSetIndex = buf.getIntLE(offset + 15); + obj.drawType = FluidDrawType.fromValue(buf.getByte(offset + 11)); + obj.fluidFXIndex = buf.getIntLE(offset + 12); + obj.blockSoundSetIndex = buf.getIntLE(offset + 16); if ((nullBits & 2) != 0) { - obj.particleColor = Color.deserialize(buf, offset + 19); + obj.particleColor = Color.deserialize(buf, offset + 20); } if ((nullBits & 4) != 0) { - int varPos0 = offset + 42 + buf.getIntLE(offset + 22); + int varPos0 = offset + 47 + buf.getIntLE(offset + 23); int idLen = VarInt.peek(buf, varPos0); if (idLen < 0) { throw ProtocolException.negativeLength("Id", idLen); @@ -115,7 +126,7 @@ public class Fluid { } if ((nullBits & 8) != 0) { - int varPos1 = offset + 42 + buf.getIntLE(offset + 26); + int varPos1 = offset + 47 + buf.getIntLE(offset + 27); int cubeTexturesCount = VarInt.peek(buf, varPos1); if (cubeTexturesCount < 0) { throw ProtocolException.negativeLength("CubeTextures", cubeTexturesCount); @@ -140,7 +151,7 @@ public class Fluid { } if ((nullBits & 16) != 0) { - int varPos2 = offset + 42 + buf.getIntLE(offset + 30); + int varPos2 = offset + 47 + buf.getIntLE(offset + 31); int shaderEffectCount = VarInt.peek(buf, varPos2); if (shaderEffectCount < 0) { throw ProtocolException.negativeLength("ShaderEffect", shaderEffectCount); @@ -165,8 +176,33 @@ public class Fluid { } if ((nullBits & 32) != 0) { - int varPos3 = offset + 42 + buf.getIntLE(offset + 34); - int blockParticleSetIdLen = VarInt.peek(buf, varPos3); + int varPos3 = offset + 47 + buf.getIntLE(offset + 35); + int particlesCount = VarInt.peek(buf, varPos3); + if (particlesCount < 0) { + throw ProtocolException.negativeLength("Particles", particlesCount); + } + + if (particlesCount > 4096000) { + throw ProtocolException.arrayTooLong("Particles", particlesCount, 4096000); + } + + int varIntLen = VarInt.length(buf, varPos3); + if (varPos3 + varIntLen + particlesCount * 34L > buf.readableBytes()) { + throw ProtocolException.bufferTooSmall("Particles", varPos3 + varIntLen + particlesCount * 34, buf.readableBytes()); + } + + obj.particles = new ModelParticle[particlesCount]; + int elemPos = varPos3 + varIntLen; + + for (int i = 0; i < particlesCount; i++) { + obj.particles[i] = ModelParticle.deserialize(buf, elemPos); + elemPos += ModelParticle.computeBytesConsumed(buf, elemPos); + } + } + + if ((nullBits & 64) != 0) { + int varPos4 = offset + 47 + buf.getIntLE(offset + 39); + int blockParticleSetIdLen = VarInt.peek(buf, varPos4); if (blockParticleSetIdLen < 0) { throw ProtocolException.negativeLength("BlockParticleSetId", blockParticleSetIdLen); } @@ -175,12 +211,12 @@ public class Fluid { throw ProtocolException.stringTooLong("BlockParticleSetId", blockParticleSetIdLen, 4096000); } - obj.blockParticleSetId = PacketIO.readVarString(buf, varPos3, PacketIO.UTF8); + obj.blockParticleSetId = PacketIO.readVarString(buf, varPos4, PacketIO.UTF8); } - if ((nullBits & 64) != 0) { - int varPos4 = offset + 42 + buf.getIntLE(offset + 38); - int tagIndexesCount = VarInt.peek(buf, varPos4); + if ((nullBits & 128) != 0) { + int varPos5 = offset + 47 + buf.getIntLE(offset + 43); + int tagIndexesCount = VarInt.peek(buf, varPos5); if (tagIndexesCount < 0) { throw ProtocolException.negativeLength("TagIndexes", tagIndexesCount); } @@ -189,15 +225,15 @@ public class Fluid { throw ProtocolException.arrayTooLong("TagIndexes", tagIndexesCount, 4096000); } - int varIntLen = VarInt.length(buf, varPos4); - if (varPos4 + varIntLen + tagIndexesCount * 4L > buf.readableBytes()) { - throw ProtocolException.bufferTooSmall("TagIndexes", varPos4 + varIntLen + tagIndexesCount * 4, buf.readableBytes()); + int varIntLen = VarInt.length(buf, varPos5); + if (varPos5 + varIntLen + tagIndexesCount * 4L > buf.readableBytes()) { + throw ProtocolException.bufferTooSmall("TagIndexes", varPos5 + varIntLen + tagIndexesCount * 4, buf.readableBytes()); } obj.tagIndexes = new int[tagIndexesCount]; for (int i = 0; i < tagIndexesCount; i++) { - obj.tagIndexes[i] = buf.getIntLE(varPos4 + varIntLen + i * 4); + obj.tagIndexes[i] = buf.getIntLE(varPos5 + varIntLen + i * 4); } } @@ -206,10 +242,10 @@ public class Fluid { public static int computeBytesConsumed(@Nonnull ByteBuf buf, int offset) { byte nullBits = buf.getByte(offset); - int maxEnd = 42; + int maxEnd = 47; if ((nullBits & 4) != 0) { - int fieldOffset0 = buf.getIntLE(offset + 22); - int pos0 = offset + 42 + fieldOffset0; + int fieldOffset0 = buf.getIntLE(offset + 23); + int pos0 = offset + 47 + fieldOffset0; int sl = VarInt.peek(buf, pos0); pos0 += VarInt.length(buf, pos0) + sl; if (pos0 - offset > maxEnd) { @@ -218,8 +254,8 @@ public class Fluid { } if ((nullBits & 8) != 0) { - int fieldOffset1 = buf.getIntLE(offset + 26); - int pos1 = offset + 42 + fieldOffset1; + int fieldOffset1 = buf.getIntLE(offset + 27); + int pos1 = offset + 47 + fieldOffset1; int arrLen = VarInt.peek(buf, pos1); pos1 += VarInt.length(buf, pos1); @@ -233,8 +269,8 @@ public class Fluid { } if ((nullBits & 16) != 0) { - int fieldOffset2 = buf.getIntLE(offset + 30); - int pos2 = offset + 42 + fieldOffset2; + int fieldOffset2 = buf.getIntLE(offset + 31); + int pos2 = offset + 47 + fieldOffset2; int arrLen = VarInt.peek(buf, pos2); pos2 += VarInt.length(buf, pos2) + arrLen * 1; if (pos2 - offset > maxEnd) { @@ -243,25 +279,40 @@ public class Fluid { } if ((nullBits & 32) != 0) { - int fieldOffset3 = buf.getIntLE(offset + 34); - int pos3 = offset + 42 + fieldOffset3; - int sl = VarInt.peek(buf, pos3); - pos3 += VarInt.length(buf, pos3) + sl; + int fieldOffset3 = buf.getIntLE(offset + 35); + int pos3 = offset + 47 + fieldOffset3; + int arrLen = VarInt.peek(buf, pos3); + pos3 += VarInt.length(buf, pos3); + + for (int i = 0; i < arrLen; i++) { + pos3 += ModelParticle.computeBytesConsumed(buf, pos3); + } + if (pos3 - offset > maxEnd) { maxEnd = pos3 - offset; } } if ((nullBits & 64) != 0) { - int fieldOffset4 = buf.getIntLE(offset + 38); - int pos4 = offset + 42 + fieldOffset4; - int arrLen = VarInt.peek(buf, pos4); - pos4 += VarInt.length(buf, pos4) + arrLen * 4; + int fieldOffset4 = buf.getIntLE(offset + 39); + int pos4 = offset + 47 + fieldOffset4; + int sl = VarInt.peek(buf, pos4); + pos4 += VarInt.length(buf, pos4) + sl; if (pos4 - offset > maxEnd) { maxEnd = pos4 - offset; } } + if ((nullBits & 128) != 0) { + int fieldOffset5 = buf.getIntLE(offset + 43); + int pos5 = offset + 47 + fieldOffset5; + int arrLen = VarInt.peek(buf, pos5); + pos5 += VarInt.length(buf, pos5) + arrLen * 4; + if (pos5 - offset > maxEnd) { + maxEnd = pos5 - offset; + } + } + return maxEnd; } @@ -288,14 +339,18 @@ public class Fluid { nullBits = (byte)(nullBits | 16); } - if (this.blockParticleSetId != null) { + if (this.particles != null) { nullBits = (byte)(nullBits | 32); } - if (this.tagIndexes != null) { + if (this.blockParticleSetId != null) { nullBits = (byte)(nullBits | 64); } + if (this.tagIndexes != null) { + nullBits = (byte)(nullBits | 128); + } + buf.writeByte(nullBits); buf.writeIntLE(this.maxFluidLevel); buf.writeByte(this.requiresAlphaBlending ? 1 : 0); @@ -306,6 +361,7 @@ public class Fluid { buf.writeZero(4); } + buf.writeByte(this.drawType.getValue()); buf.writeIntLE(this.fluidFXIndex); buf.writeIntLE(this.blockSoundSetIndex); if (this.particleColor != null) { @@ -320,6 +376,8 @@ public class Fluid { buf.writeIntLE(0); int shaderEffectOffsetSlot = buf.writerIndex(); buf.writeIntLE(0); + int particlesOffsetSlot = buf.writerIndex(); + buf.writeIntLE(0); int blockParticleSetIdOffsetSlot = buf.writerIndex(); buf.writeIntLE(0); int tagIndexesOffsetSlot = buf.writerIndex(); @@ -362,6 +420,21 @@ public class Fluid { buf.setIntLE(shaderEffectOffsetSlot, -1); } + if (this.particles != null) { + buf.setIntLE(particlesOffsetSlot, buf.writerIndex() - varBlockStart); + if (this.particles.length > 4096000) { + throw ProtocolException.arrayTooLong("Particles", this.particles.length, 4096000); + } + + VarInt.write(buf, this.particles.length); + + for (ModelParticle item : this.particles) { + item.serialize(buf); + } + } else { + buf.setIntLE(particlesOffsetSlot, -1); + } + if (this.blockParticleSetId != null) { buf.setIntLE(blockParticleSetIdOffsetSlot, buf.writerIndex() - varBlockStart); PacketIO.writeVarString(buf, this.blockParticleSetId, 4096000); @@ -386,7 +459,7 @@ public class Fluid { } public int computeSize() { - int size = 42; + int size = 47; if (this.id != null) { size += PacketIO.stringSize(this.id); } @@ -405,6 +478,16 @@ public class Fluid { size += VarInt.size(this.shaderEffect.length) + this.shaderEffect.length * 1; } + if (this.particles != null) { + int particlesSize = 0; + + for (ModelParticle elem : this.particles) { + particlesSize += elem.computeSize(); + } + + size += VarInt.size(this.particles.length) + particlesSize; + } + if (this.blockParticleSetId != null) { size += PacketIO.stringSize(this.blockParticleSetId); } @@ -417,17 +500,17 @@ public class Fluid { } public static ValidationResult validateStructure(@Nonnull ByteBuf buffer, int offset) { - if (buffer.readableBytes() - offset < 42) { - return ValidationResult.error("Buffer too small: expected at least 42 bytes"); + if (buffer.readableBytes() - offset < 47) { + return ValidationResult.error("Buffer too small: expected at least 47 bytes"); } else { byte nullBits = buffer.getByte(offset); if ((nullBits & 4) != 0) { - int idOffset = buffer.getIntLE(offset + 22); + int idOffset = buffer.getIntLE(offset + 23); if (idOffset < 0) { return ValidationResult.error("Invalid offset for Id"); } - int pos = offset + 42 + idOffset; + int pos = offset + 47 + idOffset; if (pos >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Id"); } @@ -449,12 +532,12 @@ public class Fluid { } if ((nullBits & 8) != 0) { - int cubeTexturesOffset = buffer.getIntLE(offset + 26); + int cubeTexturesOffset = buffer.getIntLE(offset + 27); if (cubeTexturesOffset < 0) { return ValidationResult.error("Invalid offset for CubeTextures"); } - int posx = offset + 42 + cubeTexturesOffset; + int posx = offset + 47 + cubeTexturesOffset; if (posx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for CubeTextures"); } @@ -481,12 +564,12 @@ public class Fluid { } if ((nullBits & 16) != 0) { - int shaderEffectOffset = buffer.getIntLE(offset + 30); + int shaderEffectOffset = buffer.getIntLE(offset + 31); if (shaderEffectOffset < 0) { return ValidationResult.error("Invalid offset for ShaderEffect"); } - int posxx = offset + 42 + shaderEffectOffset; + int posxx = offset + 47 + shaderEffectOffset; if (posxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for ShaderEffect"); } @@ -508,17 +591,49 @@ public class Fluid { } if ((nullBits & 32) != 0) { - int blockParticleSetIdOffset = buffer.getIntLE(offset + 34); + int particlesOffset = buffer.getIntLE(offset + 35); + if (particlesOffset < 0) { + return ValidationResult.error("Invalid offset for Particles"); + } + + int posxxx = offset + 47 + particlesOffset; + if (posxxx >= buffer.writerIndex()) { + return ValidationResult.error("Offset out of bounds for Particles"); + } + + int particlesCount = VarInt.peek(buffer, posxxx); + if (particlesCount < 0) { + return ValidationResult.error("Invalid array count for Particles"); + } + + if (particlesCount > 4096000) { + return ValidationResult.error("Particles exceeds max length 4096000"); + } + + posxxx += VarInt.length(buffer, posxxx); + + for (int i = 0; i < particlesCount; i++) { + ValidationResult structResult = ModelParticle.validateStructure(buffer, posxxx); + if (!structResult.isValid()) { + return ValidationResult.error("Invalid ModelParticle in Particles[" + i + "]: " + structResult.error()); + } + + posxxx += ModelParticle.computeBytesConsumed(buffer, posxxx); + } + } + + if ((nullBits & 64) != 0) { + int blockParticleSetIdOffset = buffer.getIntLE(offset + 39); if (blockParticleSetIdOffset < 0) { return ValidationResult.error("Invalid offset for BlockParticleSetId"); } - int posxxx = offset + 42 + blockParticleSetIdOffset; - if (posxxx >= buffer.writerIndex()) { + int posxxxx = offset + 47 + blockParticleSetIdOffset; + if (posxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for BlockParticleSetId"); } - int blockParticleSetIdLen = VarInt.peek(buffer, posxxx); + int blockParticleSetIdLen = VarInt.peek(buffer, posxxxx); if (blockParticleSetIdLen < 0) { return ValidationResult.error("Invalid string length for BlockParticleSetId"); } @@ -527,25 +642,25 @@ public class Fluid { return ValidationResult.error("BlockParticleSetId exceeds max length 4096000"); } - posxxx += VarInt.length(buffer, posxxx); - posxxx += blockParticleSetIdLen; - if (posxxx > buffer.writerIndex()) { + posxxxx += VarInt.length(buffer, posxxxx); + posxxxx += blockParticleSetIdLen; + if (posxxxx > buffer.writerIndex()) { return ValidationResult.error("Buffer overflow reading BlockParticleSetId"); } } - if ((nullBits & 64) != 0) { - int tagIndexesOffset = buffer.getIntLE(offset + 38); + if ((nullBits & 128) != 0) { + int tagIndexesOffset = buffer.getIntLE(offset + 43); if (tagIndexesOffset < 0) { return ValidationResult.error("Invalid offset for TagIndexes"); } - int posxxxx = offset + 42 + tagIndexesOffset; - if (posxxxx >= buffer.writerIndex()) { + int posxxxxx = offset + 47 + tagIndexesOffset; + if (posxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for TagIndexes"); } - int tagIndexesCount = VarInt.peek(buffer, posxxxx); + int tagIndexesCount = VarInt.peek(buffer, posxxxxx); if (tagIndexesCount < 0) { return ValidationResult.error("Invalid array count for TagIndexes"); } @@ -554,9 +669,9 @@ public class Fluid { return ValidationResult.error("TagIndexes exceeds max length 4096000"); } - posxxxx += VarInt.length(buffer, posxxxx); - posxxxx += tagIndexesCount * 4; - if (posxxxx > buffer.writerIndex()) { + posxxxxx += VarInt.length(buffer, posxxxxx); + posxxxxx += tagIndexesCount * 4; + if (posxxxxx > buffer.writerIndex()) { return ValidationResult.error("Buffer overflow reading TagIndexes"); } } @@ -574,6 +689,8 @@ public class Fluid { copy.opacity = this.opacity; copy.shaderEffect = this.shaderEffect != null ? Arrays.copyOf(this.shaderEffect, this.shaderEffect.length) : null; copy.light = this.light != null ? this.light.clone() : null; + copy.particles = this.particles != null ? Arrays.stream(this.particles).map(e -> e.clone()).toArray(ModelParticle[]::new) : null; + copy.drawType = this.drawType; copy.fluidFXIndex = this.fluidFXIndex; copy.blockSoundSetIndex = this.blockSoundSetIndex; copy.blockParticleSetId = this.blockParticleSetId; @@ -596,6 +713,8 @@ public class Fluid { && Objects.equals(this.opacity, other.opacity) && Arrays.equals((Object[])this.shaderEffect, (Object[])other.shaderEffect) && Objects.equals(this.light, other.light) + && Arrays.equals((Object[])this.particles, (Object[])other.particles) + && Objects.equals(this.drawType, other.drawType) && this.fluidFXIndex == other.fluidFXIndex && this.blockSoundSetIndex == other.blockSoundSetIndex && Objects.equals(this.blockParticleSetId, other.blockParticleSetId) @@ -614,6 +733,8 @@ public class Fluid { result = 31 * result + Objects.hashCode(this.opacity); result = 31 * result + Arrays.hashCode((Object[])this.shaderEffect); result = 31 * result + Objects.hashCode(this.light); + result = 31 * result + Arrays.hashCode((Object[])this.particles); + result = 31 * result + Objects.hashCode(this.drawType); result = 31 * result + Integer.hashCode(this.fluidFXIndex); result = 31 * result + Integer.hashCode(this.blockSoundSetIndex); result = 31 * result + Objects.hashCode(this.blockParticleSetId); diff --git a/src/com/hypixel/hytale/protocol/FluidDrawType.java b/src/com/hypixel/hytale/protocol/FluidDrawType.java new file mode 100644 index 00000000..dea9bbdf --- /dev/null +++ b/src/com/hypixel/hytale/protocol/FluidDrawType.java @@ -0,0 +1,27 @@ +package com.hypixel.hytale.protocol; + +import com.hypixel.hytale.protocol.io.ProtocolException; + +public enum FluidDrawType { + None(0), + Liquid(1); + + public static final FluidDrawType[] VALUES = values(); + private final int value; + + private FluidDrawType(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } + + public static FluidDrawType fromValue(int value) { + if (value >= 0 && value < VALUES.length) { + return VALUES[value]; + } else { + throw ProtocolException.invalidEnumValue("FluidDrawType", value); + } + } +} diff --git a/src/com/hypixel/hytale/protocol/PacketRegistry.java b/src/com/hypixel/hytale/protocol/PacketRegistry.java index 50b807a8..b3a7379e 100644 --- a/src/com/hypixel/hytale/protocol/PacketRegistry.java +++ b/src/com/hypixel/hytale/protocol/PacketRegistry.java @@ -614,7 +614,7 @@ public final class PacketRegistry { register(111, "MouseInteraction", MouseInteraction.class, 44, 20480071, false, MouseInteraction::validateStructure, MouseInteraction::deserialize); register(112, "DamageInfo", DamageInfo.class, 29, 32768048, false, DamageInfo::validateStructure, DamageInfo::deserialize); register(113, "ReticleEvent", ReticleEvent.class, 4, 4, false, ReticleEvent::validateStructure, ReticleEvent::deserialize); - register(114, "DisplayDebug", DisplayDebug.class, 19, 32768037, false, DisplayDebug::validateStructure, DisplayDebug::deserialize); + register(114, "DisplayDebug", DisplayDebug.class, 23, 32768041, false, DisplayDebug::validateStructure, DisplayDebug::deserialize); register(115, "ClearDebugShapes", ClearDebugShapes.class, 0, 0, false, ClearDebugShapes::validateStructure, ClearDebugShapes::deserialize); register( 116, "SyncPlayerPreferences", SyncPlayerPreferences.class, 12, 12, false, SyncPlayerPreferences::validateStructure, SyncPlayerPreferences::deserialize diff --git a/src/com/hypixel/hytale/protocol/PickupLocation.java b/src/com/hypixel/hytale/protocol/PickupLocation.java index 14a5f75e..f78b70a8 100644 --- a/src/com/hypixel/hytale/protocol/PickupLocation.java +++ b/src/com/hypixel/hytale/protocol/PickupLocation.java @@ -4,7 +4,8 @@ import com.hypixel.hytale.protocol.io.ProtocolException; public enum PickupLocation { Hotbar(0), - Storage(1); + Storage(1), + Backpack(2); public static final PickupLocation[] VALUES = values(); private final int value; diff --git a/src/com/hypixel/hytale/protocol/ProtocolSettings.java b/src/com/hypixel/hytale/protocol/ProtocolSettings.java index d89c6f61..fa698d15 100644 --- a/src/com/hypixel/hytale/protocol/ProtocolSettings.java +++ b/src/com/hypixel/hytale/protocol/ProtocolSettings.java @@ -1,18 +1,18 @@ package com.hypixel.hytale.protocol; public final class ProtocolSettings { - public static final int PROTOCOL_CRC = 701662755; + public static final int PROTOCOL_CRC = 672031543; public static final int PROTOCOL_VERSION = 2; - public static final int PROTOCOL_BUILD_NUMBER = 5; + public static final int PROTOCOL_BUILD_NUMBER = 12; public static final int PACKET_COUNT = 270; public static final int STRUCT_COUNT = 318; - public static final int ENUM_COUNT = 136; + public static final int ENUM_COUNT = 137; public static final int MAX_PACKET_SIZE = 1677721600; private ProtocolSettings() { } public static boolean validateCrc(int crc) { - return 701662755 == crc; + return 672031543 == crc; } } diff --git a/src/com/hypixel/hytale/protocol/packets/asseteditor/AssetPackManifest.java b/src/com/hypixel/hytale/protocol/packets/asseteditor/AssetPackManifest.java index 11172d6b..b507b2dd 100644 --- a/src/com/hypixel/hytale/protocol/packets/asseteditor/AssetPackManifest.java +++ b/src/com/hypixel/hytale/protocol/packets/asseteditor/AssetPackManifest.java @@ -13,8 +13,8 @@ import javax.annotation.Nullable; public class AssetPackManifest { public static final int NULLABLE_BIT_FIELD_SIZE = 1; public static final int FIXED_BLOCK_SIZE = 1; - public static final int VARIABLE_FIELD_COUNT = 6; - public static final int VARIABLE_BLOCK_START = 25; + public static final int VARIABLE_FIELD_COUNT = 7; + public static final int VARIABLE_BLOCK_START = 29; public static final int MAX_SIZE = 1677721600; @Nullable public String name; @@ -28,6 +28,8 @@ public class AssetPackManifest { public String version; @Nullable public AuthorInfo[] authors; + @Nullable + public String serverVersion; public AssetPackManifest() { } @@ -38,7 +40,8 @@ public class AssetPackManifest { @Nullable String website, @Nullable String description, @Nullable String version, - @Nullable AuthorInfo[] authors + @Nullable AuthorInfo[] authors, + @Nullable String serverVersion ) { this.name = name; this.group = group; @@ -46,6 +49,7 @@ public class AssetPackManifest { this.description = description; this.version = version; this.authors = authors; + this.serverVersion = serverVersion; } public AssetPackManifest(@Nonnull AssetPackManifest other) { @@ -55,6 +59,7 @@ public class AssetPackManifest { this.description = other.description; this.version = other.version; this.authors = other.authors; + this.serverVersion = other.serverVersion; } @Nonnull @@ -62,7 +67,7 @@ public class AssetPackManifest { AssetPackManifest obj = new AssetPackManifest(); byte nullBits = buf.getByte(offset); if ((nullBits & 1) != 0) { - int varPos0 = offset + 25 + buf.getIntLE(offset + 1); + int varPos0 = offset + 29 + buf.getIntLE(offset + 1); int nameLen = VarInt.peek(buf, varPos0); if (nameLen < 0) { throw ProtocolException.negativeLength("Name", nameLen); @@ -76,7 +81,7 @@ public class AssetPackManifest { } if ((nullBits & 2) != 0) { - int varPos1 = offset + 25 + buf.getIntLE(offset + 5); + int varPos1 = offset + 29 + buf.getIntLE(offset + 5); int groupLen = VarInt.peek(buf, varPos1); if (groupLen < 0) { throw ProtocolException.negativeLength("Group", groupLen); @@ -90,7 +95,7 @@ public class AssetPackManifest { } if ((nullBits & 4) != 0) { - int varPos2 = offset + 25 + buf.getIntLE(offset + 9); + int varPos2 = offset + 29 + buf.getIntLE(offset + 9); int websiteLen = VarInt.peek(buf, varPos2); if (websiteLen < 0) { throw ProtocolException.negativeLength("Website", websiteLen); @@ -104,7 +109,7 @@ public class AssetPackManifest { } if ((nullBits & 8) != 0) { - int varPos3 = offset + 25 + buf.getIntLE(offset + 13); + int varPos3 = offset + 29 + buf.getIntLE(offset + 13); int descriptionLen = VarInt.peek(buf, varPos3); if (descriptionLen < 0) { throw ProtocolException.negativeLength("Description", descriptionLen); @@ -118,7 +123,7 @@ public class AssetPackManifest { } if ((nullBits & 16) != 0) { - int varPos4 = offset + 25 + buf.getIntLE(offset + 17); + int varPos4 = offset + 29 + buf.getIntLE(offset + 17); int versionLen = VarInt.peek(buf, varPos4); if (versionLen < 0) { throw ProtocolException.negativeLength("Version", versionLen); @@ -132,7 +137,7 @@ public class AssetPackManifest { } if ((nullBits & 32) != 0) { - int varPos5 = offset + 25 + buf.getIntLE(offset + 21); + int varPos5 = offset + 29 + buf.getIntLE(offset + 21); int authorsCount = VarInt.peek(buf, varPos5); if (authorsCount < 0) { throw ProtocolException.negativeLength("Authors", authorsCount); @@ -156,15 +161,29 @@ public class AssetPackManifest { } } + if ((nullBits & 64) != 0) { + int varPos6 = offset + 29 + buf.getIntLE(offset + 25); + int serverVersionLen = VarInt.peek(buf, varPos6); + if (serverVersionLen < 0) { + throw ProtocolException.negativeLength("ServerVersion", serverVersionLen); + } + + if (serverVersionLen > 4096000) { + throw ProtocolException.stringTooLong("ServerVersion", serverVersionLen, 4096000); + } + + obj.serverVersion = PacketIO.readVarString(buf, varPos6, PacketIO.UTF8); + } + return obj; } public static int computeBytesConsumed(@Nonnull ByteBuf buf, int offset) { byte nullBits = buf.getByte(offset); - int maxEnd = 25; + int maxEnd = 29; if ((nullBits & 1) != 0) { int fieldOffset0 = buf.getIntLE(offset + 1); - int pos0 = offset + 25 + fieldOffset0; + int pos0 = offset + 29 + fieldOffset0; int sl = VarInt.peek(buf, pos0); pos0 += VarInt.length(buf, pos0) + sl; if (pos0 - offset > maxEnd) { @@ -174,7 +193,7 @@ public class AssetPackManifest { if ((nullBits & 2) != 0) { int fieldOffset1 = buf.getIntLE(offset + 5); - int pos1 = offset + 25 + fieldOffset1; + int pos1 = offset + 29 + fieldOffset1; int sl = VarInt.peek(buf, pos1); pos1 += VarInt.length(buf, pos1) + sl; if (pos1 - offset > maxEnd) { @@ -184,7 +203,7 @@ public class AssetPackManifest { if ((nullBits & 4) != 0) { int fieldOffset2 = buf.getIntLE(offset + 9); - int pos2 = offset + 25 + fieldOffset2; + int pos2 = offset + 29 + fieldOffset2; int sl = VarInt.peek(buf, pos2); pos2 += VarInt.length(buf, pos2) + sl; if (pos2 - offset > maxEnd) { @@ -194,7 +213,7 @@ public class AssetPackManifest { if ((nullBits & 8) != 0) { int fieldOffset3 = buf.getIntLE(offset + 13); - int pos3 = offset + 25 + fieldOffset3; + int pos3 = offset + 29 + fieldOffset3; int sl = VarInt.peek(buf, pos3); pos3 += VarInt.length(buf, pos3) + sl; if (pos3 - offset > maxEnd) { @@ -204,7 +223,7 @@ public class AssetPackManifest { if ((nullBits & 16) != 0) { int fieldOffset4 = buf.getIntLE(offset + 17); - int pos4 = offset + 25 + fieldOffset4; + int pos4 = offset + 29 + fieldOffset4; int sl = VarInt.peek(buf, pos4); pos4 += VarInt.length(buf, pos4) + sl; if (pos4 - offset > maxEnd) { @@ -214,7 +233,7 @@ public class AssetPackManifest { if ((nullBits & 32) != 0) { int fieldOffset5 = buf.getIntLE(offset + 21); - int pos5 = offset + 25 + fieldOffset5; + int pos5 = offset + 29 + fieldOffset5; int arrLen = VarInt.peek(buf, pos5); pos5 += VarInt.length(buf, pos5); @@ -227,6 +246,16 @@ public class AssetPackManifest { } } + if ((nullBits & 64) != 0) { + int fieldOffset6 = buf.getIntLE(offset + 25); + int pos6 = offset + 29 + fieldOffset6; + int sl = VarInt.peek(buf, pos6); + pos6 += VarInt.length(buf, pos6) + sl; + if (pos6 - offset > maxEnd) { + maxEnd = pos6 - offset; + } + } + return maxEnd; } @@ -257,6 +286,10 @@ public class AssetPackManifest { nullBits = (byte)(nullBits | 32); } + if (this.serverVersion != null) { + nullBits = (byte)(nullBits | 64); + } + buf.writeByte(nullBits); int nameOffsetSlot = buf.writerIndex(); buf.writeIntLE(0); @@ -270,6 +303,8 @@ public class AssetPackManifest { buf.writeIntLE(0); int authorsOffsetSlot = buf.writerIndex(); buf.writeIntLE(0); + int serverVersionOffsetSlot = buf.writerIndex(); + buf.writeIntLE(0); int varBlockStart = buf.writerIndex(); if (this.name != null) { buf.setIntLE(nameOffsetSlot, buf.writerIndex() - varBlockStart); @@ -320,10 +355,17 @@ public class AssetPackManifest { } else { buf.setIntLE(authorsOffsetSlot, -1); } + + if (this.serverVersion != null) { + buf.setIntLE(serverVersionOffsetSlot, buf.writerIndex() - varBlockStart); + PacketIO.writeVarString(buf, this.serverVersion, 4096000); + } else { + buf.setIntLE(serverVersionOffsetSlot, -1); + } } public int computeSize() { - int size = 25; + int size = 29; if (this.name != null) { size += PacketIO.stringSize(this.name); } @@ -354,12 +396,16 @@ public class AssetPackManifest { size += VarInt.size(this.authors.length) + authorsSize; } + if (this.serverVersion != null) { + size += PacketIO.stringSize(this.serverVersion); + } + return size; } public static ValidationResult validateStructure(@Nonnull ByteBuf buffer, int offset) { - if (buffer.readableBytes() - offset < 25) { - return ValidationResult.error("Buffer too small: expected at least 25 bytes"); + if (buffer.readableBytes() - offset < 29) { + return ValidationResult.error("Buffer too small: expected at least 29 bytes"); } else { byte nullBits = buffer.getByte(offset); if ((nullBits & 1) != 0) { @@ -368,7 +414,7 @@ public class AssetPackManifest { return ValidationResult.error("Invalid offset for Name"); } - int pos = offset + 25 + nameOffset; + int pos = offset + 29 + nameOffset; if (pos >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Name"); } @@ -395,7 +441,7 @@ public class AssetPackManifest { return ValidationResult.error("Invalid offset for Group"); } - int posx = offset + 25 + groupOffset; + int posx = offset + 29 + groupOffset; if (posx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Group"); } @@ -422,7 +468,7 @@ public class AssetPackManifest { return ValidationResult.error("Invalid offset for Website"); } - int posxx = offset + 25 + websiteOffset; + int posxx = offset + 29 + websiteOffset; if (posxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Website"); } @@ -449,7 +495,7 @@ public class AssetPackManifest { return ValidationResult.error("Invalid offset for Description"); } - int posxxx = offset + 25 + descriptionOffset; + int posxxx = offset + 29 + descriptionOffset; if (posxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Description"); } @@ -476,7 +522,7 @@ public class AssetPackManifest { return ValidationResult.error("Invalid offset for Version"); } - int posxxxx = offset + 25 + versionOffset; + int posxxxx = offset + 29 + versionOffset; if (posxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Version"); } @@ -503,7 +549,7 @@ public class AssetPackManifest { return ValidationResult.error("Invalid offset for Authors"); } - int posxxxxx = offset + 25 + authorsOffset; + int posxxxxx = offset + 29 + authorsOffset; if (posxxxxx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Authors"); } @@ -529,6 +575,33 @@ public class AssetPackManifest { } } + if ((nullBits & 64) != 0) { + int serverVersionOffset = buffer.getIntLE(offset + 25); + if (serverVersionOffset < 0) { + return ValidationResult.error("Invalid offset for ServerVersion"); + } + + int posxxxxxx = offset + 29 + serverVersionOffset; + if (posxxxxxx >= buffer.writerIndex()) { + return ValidationResult.error("Offset out of bounds for ServerVersion"); + } + + int serverVersionLen = VarInt.peek(buffer, posxxxxxx); + if (serverVersionLen < 0) { + return ValidationResult.error("Invalid string length for ServerVersion"); + } + + if (serverVersionLen > 4096000) { + return ValidationResult.error("ServerVersion exceeds max length 4096000"); + } + + posxxxxxx += VarInt.length(buffer, posxxxxxx); + posxxxxxx += serverVersionLen; + if (posxxxxxx > buffer.writerIndex()) { + return ValidationResult.error("Buffer overflow reading ServerVersion"); + } + } + return ValidationResult.OK; } } @@ -541,6 +614,7 @@ public class AssetPackManifest { copy.description = this.description; copy.version = this.version; copy.authors = this.authors != null ? Arrays.stream(this.authors).map(e -> e.clone()).toArray(AuthorInfo[]::new) : null; + copy.serverVersion = this.serverVersion; return copy; } @@ -556,7 +630,8 @@ public class AssetPackManifest { && Objects.equals(this.website, other.website) && Objects.equals(this.description, other.description) && Objects.equals(this.version, other.version) - && Arrays.equals((Object[])this.authors, (Object[])other.authors); + && Arrays.equals((Object[])this.authors, (Object[])other.authors) + && Objects.equals(this.serverVersion, other.serverVersion); } } @@ -568,6 +643,7 @@ public class AssetPackManifest { result = 31 * result + Objects.hashCode(this.website); result = 31 * result + Objects.hashCode(this.description); result = 31 * result + Objects.hashCode(this.version); - return 31 * result + Arrays.hashCode((Object[])this.authors); + result = 31 * result + Arrays.hashCode((Object[])this.authors); + return 31 * result + Objects.hashCode(this.serverVersion); } } diff --git a/src/com/hypixel/hytale/protocol/packets/player/DisplayDebug.java b/src/com/hypixel/hytale/protocol/packets/player/DisplayDebug.java index d9a943a0..e589a2eb 100644 --- a/src/com/hypixel/hytale/protocol/packets/player/DisplayDebug.java +++ b/src/com/hypixel/hytale/protocol/packets/player/DisplayDebug.java @@ -16,10 +16,10 @@ public class DisplayDebug implements Packet { public static final int PACKET_ID = 114; public static final boolean IS_COMPRESSED = false; public static final int NULLABLE_BIT_FIELD_SIZE = 1; - public static final int FIXED_BLOCK_SIZE = 19; + public static final int FIXED_BLOCK_SIZE = 23; public static final int VARIABLE_FIELD_COUNT = 2; - public static final int VARIABLE_BLOCK_START = 27; - public static final int MAX_SIZE = 32768037; + public static final int VARIABLE_BLOCK_START = 31; + public static final int MAX_SIZE = 32768041; @Nonnull public DebugShape shape = DebugShape.Sphere; @Nullable @@ -30,6 +30,7 @@ public class DisplayDebug implements Packet { public boolean fade; @Nullable public float[] frustumProjection; + public float opacity; @Override public int getId() { @@ -40,7 +41,13 @@ public class DisplayDebug implements Packet { } public DisplayDebug( - @Nonnull DebugShape shape, @Nullable float[] matrix, @Nullable Vector3f color, float time, boolean fade, @Nullable float[] frustumProjection + @Nonnull DebugShape shape, + @Nullable float[] matrix, + @Nullable Vector3f color, + float time, + boolean fade, + @Nullable float[] frustumProjection, + float opacity ) { this.shape = shape; this.matrix = matrix; @@ -48,6 +55,7 @@ public class DisplayDebug implements Packet { this.time = time; this.fade = fade; this.frustumProjection = frustumProjection; + this.opacity = opacity; } public DisplayDebug(@Nonnull DisplayDebug other) { @@ -57,6 +65,7 @@ public class DisplayDebug implements Packet { this.time = other.time; this.fade = other.fade; this.frustumProjection = other.frustumProjection; + this.opacity = other.opacity; } @Nonnull @@ -70,8 +79,9 @@ public class DisplayDebug implements Packet { obj.time = buf.getFloatLE(offset + 14); obj.fade = buf.getByte(offset + 18) != 0; + obj.opacity = buf.getFloatLE(offset + 19); if ((nullBits & 2) != 0) { - int varPos0 = offset + 27 + buf.getIntLE(offset + 19); + int varPos0 = offset + 31 + buf.getIntLE(offset + 23); int matrixCount = VarInt.peek(buf, varPos0); if (matrixCount < 0) { throw ProtocolException.negativeLength("Matrix", matrixCount); @@ -94,7 +104,7 @@ public class DisplayDebug implements Packet { } if ((nullBits & 4) != 0) { - int varPos1 = offset + 27 + buf.getIntLE(offset + 23); + int varPos1 = offset + 31 + buf.getIntLE(offset + 27); int frustumProjectionCount = VarInt.peek(buf, varPos1); if (frustumProjectionCount < 0) { throw ProtocolException.negativeLength("FrustumProjection", frustumProjectionCount); @@ -121,10 +131,10 @@ public class DisplayDebug implements Packet { public static int computeBytesConsumed(@Nonnull ByteBuf buf, int offset) { byte nullBits = buf.getByte(offset); - int maxEnd = 27; + int maxEnd = 31; if ((nullBits & 2) != 0) { - int fieldOffset0 = buf.getIntLE(offset + 19); - int pos0 = offset + 27 + fieldOffset0; + int fieldOffset0 = buf.getIntLE(offset + 23); + int pos0 = offset + 31 + fieldOffset0; int arrLen = VarInt.peek(buf, pos0); pos0 += VarInt.length(buf, pos0) + arrLen * 4; if (pos0 - offset > maxEnd) { @@ -133,8 +143,8 @@ public class DisplayDebug implements Packet { } if ((nullBits & 4) != 0) { - int fieldOffset1 = buf.getIntLE(offset + 23); - int pos1 = offset + 27 + fieldOffset1; + int fieldOffset1 = buf.getIntLE(offset + 27); + int pos1 = offset + 31 + fieldOffset1; int arrLen = VarInt.peek(buf, pos1); pos1 += VarInt.length(buf, pos1) + arrLen * 4; if (pos1 - offset > maxEnd) { @@ -171,6 +181,7 @@ public class DisplayDebug implements Packet { buf.writeFloatLE(this.time); buf.writeByte(this.fade ? 1 : 0); + buf.writeFloatLE(this.opacity); int matrixOffsetSlot = buf.writerIndex(); buf.writeIntLE(0); int frustumProjectionOffsetSlot = buf.writerIndex(); @@ -209,7 +220,7 @@ public class DisplayDebug implements Packet { @Override public int computeSize() { - int size = 27; + int size = 31; if (this.matrix != null) { size += VarInt.size(this.matrix.length) + this.matrix.length * 4; } @@ -222,17 +233,17 @@ public class DisplayDebug implements Packet { } public static ValidationResult validateStructure(@Nonnull ByteBuf buffer, int offset) { - if (buffer.readableBytes() - offset < 27) { - return ValidationResult.error("Buffer too small: expected at least 27 bytes"); + if (buffer.readableBytes() - offset < 31) { + return ValidationResult.error("Buffer too small: expected at least 31 bytes"); } else { byte nullBits = buffer.getByte(offset); if ((nullBits & 2) != 0) { - int matrixOffset = buffer.getIntLE(offset + 19); + int matrixOffset = buffer.getIntLE(offset + 23); if (matrixOffset < 0) { return ValidationResult.error("Invalid offset for Matrix"); } - int pos = offset + 27 + matrixOffset; + int pos = offset + 31 + matrixOffset; if (pos >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for Matrix"); } @@ -254,12 +265,12 @@ public class DisplayDebug implements Packet { } if ((nullBits & 4) != 0) { - int frustumProjectionOffset = buffer.getIntLE(offset + 23); + int frustumProjectionOffset = buffer.getIntLE(offset + 27); if (frustumProjectionOffset < 0) { return ValidationResult.error("Invalid offset for FrustumProjection"); } - int posx = offset + 27 + frustumProjectionOffset; + int posx = offset + 31 + frustumProjectionOffset; if (posx >= buffer.writerIndex()) { return ValidationResult.error("Offset out of bounds for FrustumProjection"); } @@ -292,6 +303,7 @@ public class DisplayDebug implements Packet { copy.time = this.time; copy.fade = this.fade; copy.frustumProjection = this.frustumProjection != null ? Arrays.copyOf(this.frustumProjection, this.frustumProjection.length) : null; + copy.opacity = this.opacity; return copy; } @@ -307,7 +319,8 @@ public class DisplayDebug implements Packet { && Objects.equals(this.color, other.color) && this.time == other.time && this.fade == other.fade - && Arrays.equals(this.frustumProjection, other.frustumProjection); + && Arrays.equals(this.frustumProjection, other.frustumProjection) + && this.opacity == other.opacity; } } @@ -319,6 +332,7 @@ public class DisplayDebug implements Packet { result = 31 * result + Objects.hashCode(this.color); result = 31 * result + Float.hashCode(this.time); result = 31 * result + Boolean.hashCode(this.fade); - return 31 * result + Arrays.hashCode(this.frustumProjection); + result = 31 * result + Arrays.hashCode(this.frustumProjection); + return 31 * result + Float.hashCode(this.opacity); } } diff --git a/src/com/hypixel/hytale/server/core/Constants.java b/src/com/hypixel/hytale/server/core/Constants.java index e47428d7..ebfaaf66 100644 --- a/src/com/hypixel/hytale/server/core/Constants.java +++ b/src/com/hypixel/hytale/server/core/Constants.java @@ -104,4 +104,8 @@ public final class Constants { private static Path getUniversePath() { return OPTION_SET.has(Options.UNIVERSE) ? OPTION_SET.valueOf(Options.UNIVERSE) : Path.of("universe"); } + + public static boolean shouldSkipModValidation() { + return OPTION_SET.has(Options.SKIP_MOD_VALIDATION) || HytaleServer.get().getConfig().shouldSkipModValidation(); + } } diff --git a/src/com/hypixel/hytale/server/core/HytaleServer.java b/src/com/hypixel/hytale/server/core/HytaleServer.java index 95018b52..8693171e 100644 --- a/src/com/hypixel/hytale/server/core/HytaleServer.java +++ b/src/com/hypixel/hytale/server/core/HytaleServer.java @@ -129,6 +129,11 @@ public class HytaleServer { options.setEnvironment("release"); options.setTag("patchline", ManifestUtil.getPatchline()); options.setServerName(NetworkUtil.getHostName()); + UUID distinctId = HardwareUtil.getUUID(); + if (distinctId != null) { + options.setDistinctId(distinctId.toString()); + } + options.setBeforeSend((event, hint) -> { Throwable throwable = event.getThrowable(); if (PluginClassLoader.isFromThirdPartyPlugin(throwable)) { @@ -214,6 +219,7 @@ public class HytaleServer { } }); Sentry.init(options); + Sentry.startSession(); Sentry.configureScope( scope -> { UUID hardwareUUID = HardwareUtil.getUUID(); @@ -327,8 +333,8 @@ public class HytaleServer { if (loadAssetEvent.isShouldShutdown()) { List reasons = loadAssetEvent.getReasons(); - String join = String.join(", ", reasons); - LOGGER.at(Level.SEVERE).log("Asset validation FAILED with %d reason(s): %s", reasons.size(), join); + String join = String.join("\n", reasons); + LOGGER.at(Level.SEVERE).log("Asset validation FAILED with %d reason(s):\n%s", reasons.size(), join); this.shutdownServer(ShutdownReason.VALIDATE_ERROR.withMessage(join)); return; } @@ -431,7 +437,7 @@ public class HytaleServer { Objects.requireNonNull(reason, "Server shutdown reason can't be null!"); if (this.shutdown.getAndSet(reason) == null) { if (reason.getMessage() != null) { - this.sendSingleplayerSignal("-=|Shutdown|" + reason.getMessage()); + this.sendSingleplayerSignal("-=|Shutdown|" + reason.getMessage().replace("\n", "\\n")); } Thread shutdownThread = new Thread(() -> this.shutdown0(reason), "ShutdownThread"); @@ -462,6 +468,7 @@ public class HytaleServer { this.aliveLock.release(); HytaleLogManager.resetFinally(); + Sentry.endSession(); SCHEDULED_EXECUTOR.schedule(() -> { LOGGER.at(Level.SEVERE).log("Forcing shutdown!"); Runtime.getRuntime().halt(reason.getExitCode()); diff --git a/src/com/hypixel/hytale/server/core/HytaleServerConfig.java b/src/com/hypixel/hytale/server/core/HytaleServerConfig.java index e3947a99..eff958e9 100644 --- a/src/com/hypixel/hytale/server/core/HytaleServerConfig.java +++ b/src/com/hypixel/hytale/server/core/HytaleServerConfig.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.codec.lookup.Priority; import com.hypixel.hytale.codec.util.RawJsonReader; import com.hypixel.hytale.common.plugin.PluginIdentifier; import com.hypixel.hytale.common.semver.SemverRange; +import com.hypixel.hytale.common.util.java.ManifestUtil; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.protocol.GameMode; import com.hypixel.hytale.server.core.auth.AuthCredentialStoreProvider; @@ -107,6 +108,8 @@ public class HytaleServerConfig { .add() .append(new KeyedCodec<>("Update", HytaleServerConfig.UpdateConfig.CODEC), (o, value) -> o.updateConfig = value, o -> o.updateConfig) .add() + .append(new KeyedCodec<>("SkipModValidationForVersion", Codec.STRING), (o, v) -> o.skipModValidationForVersion = v, o -> o.skipModValidationForVersion) + .add() .afterDecode((config, extraInfo) -> { config.defaults.hytaleServerConfig = config; config.connectionTimeouts.setHytaleServerConfig(config); @@ -124,6 +127,9 @@ public class HytaleServerConfig { if (config.defaultModsEnabled == null && extraInfo.getVersion() < 4) { config.defaultModsEnabled = true; + } + + if (extraInfo.getVersion() != 4) { config.markChanged(); } }) @@ -164,6 +170,8 @@ public class HytaleServerConfig { private boolean displayTmpTagsInStrings; @Nonnull private HytaleServerConfig.UpdateConfig updateConfig = new HytaleServerConfig.UpdateConfig(this); + @Nullable + private String skipModValidationForVersion; public String getServerName() { return this.serverName; @@ -328,6 +336,10 @@ public class HytaleServerConfig { this.markChanged(); } + public boolean shouldSkipModValidation() { + return this.skipModValidationForVersion != null && this.skipModValidationForVersion.equals(ManifestUtil.getImplementationRevisionId()); + } + public void removeModule(@Nonnull String module) { this.modules.remove(module); this.markChanged(); diff --git a/src/com/hypixel/hytale/server/core/Options.java b/src/com/hypixel/hytale/server/core/Options.java index af3601f1..f1d59262 100644 --- a/src/com/hypixel/hytale/server/core/Options.java +++ b/src/com/hypixel/hytale/server/core/Options.java @@ -122,6 +122,9 @@ public class Options { ) .withRequiredArg() .withValuesSeparatedBy(','); + public static final OptionSpec SKIP_MOD_VALIDATION = PARSER.accepts( + "skip-mod-validation", "Skips mod validation, attempting to allow the server to boot even if one fails to load" + ); public static final String ALLOW_SELF_OP_COMMAND_STRING = "allow-op"; public static final OptionSpec ALLOW_SELF_OP_COMMAND = PARSER.accepts("allow-op"); public static final OptionSpec AUTH_MODE = PARSER.accepts("auth-mode", "Authentication mode") @@ -171,6 +174,30 @@ public class Options { HytaleLoggerBackend.loadLevels(List.of(Map.entry("", Level.WARNING))); } + for (Path path : optionSet.valuesOf(ASSET_DIRECTORY)) { + PathUtil.addTrustedRoot(path); + } + + for (Path path : optionSet.valuesOf(MODS_DIRECTORIES)) { + PathUtil.addTrustedRoot(path); + } + + for (Path path : optionSet.valuesOf(EARLY_PLUGIN_DIRECTORIES)) { + PathUtil.addTrustedRoot(path); + } + + if (optionSet.has(WORLD_GEN_DIRECTORY)) { + PathUtil.addTrustedRoot(optionSet.valueOf(WORLD_GEN_DIRECTORY)); + } + + if (optionSet.has(BACKUP_DIRECTORY)) { + PathUtil.addTrustedRoot(optionSet.valueOf(BACKUP_DIRECTORY)); + } + + if (optionSet.has(UNIVERSE)) { + PathUtil.addTrustedRoot(optionSet.valueOf(UNIVERSE)); + } + return false; } } diff --git a/src/com/hypixel/hytale/server/core/ShutdownReason.java b/src/com/hypixel/hytale/server/core/ShutdownReason.java index c63b32aa..218c518a 100644 --- a/src/com/hypixel/hytale/server/core/ShutdownReason.java +++ b/src/com/hypixel/hytale/server/core/ShutdownReason.java @@ -13,6 +13,7 @@ public class ShutdownReason { public static final ShutdownReason VALIDATE_ERROR = new ShutdownReason(6); public static final ShutdownReason MISSING_ASSETS = new ShutdownReason(7); public static final ShutdownReason UPDATE = new ShutdownReason(8); + public static final ShutdownReason MOD_ERROR = new ShutdownReason(9); private final int exitCode; private final String message; diff --git a/src/com/hypixel/hytale/server/core/asset/AssetModule.java b/src/com/hypixel/hytale/server/core/asset/AssetModule.java index 0c03200f..4ea7e851 100644 --- a/src/com/hypixel/hytale/server/core/asset/AssetModule.java +++ b/src/com/hypixel/hytale/server/core/asset/AssetModule.java @@ -13,10 +13,14 @@ import com.hypixel.hytale.codec.util.RawJsonReader; import com.hypixel.hytale.common.plugin.PluginIdentifier; import com.hypixel.hytale.common.plugin.PluginManifest; import com.hypixel.hytale.common.util.FormatUtil; +import com.hypixel.hytale.common.util.PathUtil; +import com.hypixel.hytale.common.util.java.ManifestUtil; import com.hypixel.hytale.event.EventPriority; import com.hypixel.hytale.logger.HytaleLogger; +import com.hypixel.hytale.server.core.Constants; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.HytaleServerConfig; +import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.Options; import com.hypixel.hytale.server.core.ShutdownReason; import com.hypixel.hytale.server.core.asset.monitor.AssetMonitor; @@ -24,10 +28,13 @@ import com.hypixel.hytale.server.core.asset.type.gameplay.respawn.HomeOrSpawnPoi import com.hypixel.hytale.server.core.asset.type.gameplay.respawn.RespawnController; import com.hypixel.hytale.server.core.asset.type.gameplay.respawn.WorldSpawnPoint; import com.hypixel.hytale.server.core.asset.type.item.DroplistCommand; +import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.event.events.BootEvent; +import com.hypixel.hytale.server.core.event.events.player.AddPlayerToWorldEvent; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.PluginManager; +import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.worldgen.IWorldGen; import com.hypixel.hytale.server.core.universe.world.worldgen.ValidatableWorldGen; import com.hypixel.hytale.server.core.universe.world.worldgen.WorldGenLoadException; @@ -35,6 +42,7 @@ import com.hypixel.hytale.server.core.universe.world.worldgen.provider.IWorldGen import com.hypixel.hytale.server.core.universe.world.worldmap.IWorldMap; import com.hypixel.hytale.server.core.universe.world.worldmap.provider.IWorldMapProvider; import com.hypixel.hytale.sneakythrow.SneakyThrow; +import java.awt.Color; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -44,6 +52,8 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; @@ -59,6 +69,8 @@ public class AssetModule extends JavaPlugin { private AssetMonitor assetMonitor; @Nonnull private final List assetPacks = new CopyOnWriteArrayList<>(); + private final List pendingAssetPacks = new ArrayList<>(); + private boolean hasSetup = false; private boolean hasLoaded = false; private final List> pendingAssetStores = new CopyOnWriteArrayList<>(); @@ -79,8 +91,8 @@ public class AssetModule extends JavaPlugin { try { this.assetMonitor = new AssetMonitor(); this.getLogger().at(Level.INFO).log("Asset monitor enabled!"); - } catch (IOException var4) { - this.getLogger().at(Level.SEVERE).withCause(var4).log("Failed to create asset monitor!"); + } catch (IOException var8) { + this.getLogger().at(Level.SEVERE).withCause(var8).log("Failed to create asset monitor!"); } } @@ -88,6 +100,9 @@ public class AssetModule extends JavaPlugin { this.loadAndRegisterPack(path, false); } + this.hasSetup = true; + this.assetPacks.addAll(this.pendingAssetPacks); + this.pendingAssetPacks.clear(); this.loadPacksFromDirectory(PluginManager.MODS_PATH); for (Path modsPath : Options.getOptionSet().valuesOf(Options.MODS_DIRECTORIES)) { @@ -97,6 +112,59 @@ public class AssetModule extends JavaPlugin { if (this.assetPacks.isEmpty()) { HytaleServer.get().shutdownServer(ShutdownReason.MISSING_ASSETS.withMessage("Failed to load any asset packs")); } else { + boolean hasOutdatedPacks = false; + String serverVersion = ManifestUtil.getVersion(); + + for (AssetPack pack : this.assetPacks) { + if (!pack.getName().equals("Hytale:Hytale")) { + PluginManifest manifest = pack.getManifest(); + String targetServerVersion = manifest.getServerVersion(); + if (targetServerVersion == null || !targetServerVersion.equals(serverVersion)) { + hasOutdatedPacks = true; + if (targetServerVersion != null && !"*".equals(targetServerVersion)) { + this.getLogger() + .at(Level.WARNING) + .log( + "Plugin '%s' targets a different server version %s. You may encounter issues, please check for plugin updates.", + pack.getName(), + serverVersion + ); + } else { + this.getLogger() + .at(Level.WARNING) + .log( + "Plugin '%s' does not specify a target server version. You may encounter issues, please check for plugin updates. This will be a hard error in the future", + pack.getName() + ); + } + } + } + } + + if (hasOutdatedPacks && System.getProperty("hytale.allow_outdated_mods") == null) { + this.getLogger() + .at(Level.SEVERE) + .log("One or more asset packs are targeting an older server version. It is recommended to update these plugins to ensure compatibility."); + + try { + if (!Constants.SINGLEPLAYER) { + Thread.sleep(Duration.ofSeconds(2L)); + } + } catch (InterruptedException var9) { + throw new RuntimeException(var9); + } + + HytaleServer.get().getEventBus().registerGlobal(AddPlayerToWorldEvent.class, event -> { + PlayerRef playerRef = event.getHolder().getComponent(PlayerRef.getComponentType()); + Player player = event.getHolder().getComponent(Player.getComponentType()); + if (playerRef != null && player != null) { + if (player.hasPermission("hytale.mods.outdated.notify")) { + playerRef.sendMessage(Message.translation("server.assetModule.outOfDatePacks").color(Color.RED)); + } + } + }); + } + this.getEventRegistry().register((short)-16, LoadAssetEvent.class, event -> { if (this.hasLoaded) { throw new IllegalStateException("LoadAssetEvent has already been dispatched"); @@ -107,8 +175,8 @@ public class AssetModule extends JavaPlugin { this.hasLoaded = true; AssetRegistryLoader.preLoadAssets(event); - for (AssetPack pack : this.assetPacks) { - AssetRegistryLoader.loadAssets(event, pack); + for (AssetPack packx : this.assetPacks) { + AssetRegistryLoader.loadAssets(event, packx); } } finally { AssetRegistry.ASSET_LOCK.writeLock().unlock(); @@ -194,6 +262,17 @@ public class AssetModule extends JavaPlugin { return null; } + public boolean isWithinPackSubDir(@Nonnull Path path, @Nonnull String subDir) { + for (AssetPack pack : this.assetPacks) { + Path packSubDir = pack.getRoot().resolve(subDir); + if (PathUtil.isChildOf(packSubDir, path)) { + return true; + } + } + + return false; + } + public boolean isAssetPathImmutable(@Nonnull Path path) { AssetPack pack = this.findAssetPackForPath(path); return pack != null && pack.isImmutable(); @@ -304,16 +383,23 @@ public class AssetModule extends JavaPlugin { } AssetPack pack = new AssetPack(packLocation, name, absolutePath, fileSystem, isImmutable, manifest); - this.assetPacks.add(pack); - AssetRegistry.ASSET_LOCK.writeLock().lock(); + if (!this.hasSetup) { + this.pendingAssetPacks.add(pack); + } else { + this.assetPacks.add(pack); + AssetRegistry.ASSET_LOCK.writeLock().lock(); - try { - if (this.hasLoaded) { - HytaleServer.get().getEventBus().dispatchFor(AssetPackRegisterEvent.class).dispatch(new AssetPackRegisterEvent(pack)); - return; + try { + if (this.hasLoaded) { + HytaleServer.get() + .getEventBus() + .dispatchFor(AssetPackRegisterEvent.class) + .dispatch(new AssetPackRegisterEvent(pack)); + return; + } + } finally { + AssetRegistry.ASSET_LOCK.writeLock().unlock(); } - } finally { - AssetRegistry.ASSET_LOCK.writeLock().unlock(); } } diff --git a/src/com/hypixel/hytale/server/core/asset/AssetRegistryLoader.java b/src/com/hypixel/hytale/server/core/asset/AssetRegistryLoader.java index 5b4c0b63..eacff09a 100644 --- a/src/com/hypixel/hytale/server/core/asset/AssetRegistryLoader.java +++ b/src/com/hypixel/hytale/server/core/asset/AssetRegistryLoader.java @@ -20,6 +20,7 @@ import com.hypixel.hytale.codec.schema.config.Schema; import com.hypixel.hytale.common.util.FormatUtil; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.protocol.Packet; +import com.hypixel.hytale.server.core.Constants; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.Options; import com.hypixel.hytale.server.core.ShutdownReason; @@ -247,6 +248,7 @@ public class AssetRegistryLoader { Path serverAssetDirectory = assetPack.getRoot().resolve("Server"); HytaleLogger.getLogger().at(Level.INFO).log("Loading assets from: %s", serverAssetDirectory); long startAll = System.nanoTime(); + boolean shouldFail = Options.getOptionSet().has(Options.VALIDATE_ASSETS) || !Constants.shouldSkipModValidation(); boolean failedToLoadAsset = false; LOGGER.at(Level.INFO).log("Loading assets from %s", serverAssetDirectory); Collection> values = AssetRegistry.getStoreMap().values(); @@ -277,19 +279,23 @@ public class AssetRegistryLoader { failedToLoadAsset |= loadResult.hasFailed(); } } - } catch (Exception var18) { + } catch (Exception var19) { failedToLoadAsset = true; + if (event != null) { + event.failed(shouldFail, "Asset pack " + assetPack.getName() + " failed to load " + assetClass.getSimpleName() + " - " + var19.getMessage()); + } + long end = System.nanoTime(); long diff = end - start; if (iterator.isBeingWaitedFor(assetStore)) { throw new RuntimeException( String.format("Failed to load %s from path '%s' took %s", assetClass.getSimpleName(), assetStore.getPath(), FormatUtil.nanosToString(diff)), - var18 + var19 ); } LOGGER.at(Level.SEVERE) - .withCause(var18) + .withCause(var19) .log("Failed to load %s from path '%s' took %s", assetClass.getSimpleName(), assetStore.getPath(), FormatUtil.nanosToString(diff)); } } @@ -313,33 +319,25 @@ public class AssetRegistryLoader { long diffAll = endAll - startAll; LOGGER.at(Level.INFO).log("Took %s to load all assets", FormatUtil.nanosToString(diffAll)); if (failedToLoadAsset && event != null) { - event.failed(Options.getOptionSet().has(Options.VALIDATE_ASSETS), "failed to validate assets"); + if ("Hytale:Hytale".equals(assetPack.getName())) { + event.failed(shouldFail, "Assets " + assetPack.getName() + " failed to load."); + } else { + event.failed(shouldFail, "Mod " + assetPack.getName() + " failed to load. Check for mod updates or contact the mod author."); + } } } public static void sendAssets(@Nonnull PacketHandler packetHandler) { Consumer packetConsumer = packetHandler::write; Consumer singlePacketConsumer = packetHandler::write; - AssetRegistry.ASSET_LOCK.writeLock().lock(); - - try { - HytaleAssetStore.SETUP_PACKET_CONSUMERS.add(singlePacketConsumer); - } finally { - AssetRegistry.ASSET_LOCK.writeLock().unlock(); - } + HytaleAssetStore.SETUP_PACKET_CONSUMERS.add(singlePacketConsumer); try { for (AssetStore assetStore : AssetRegistry.getStoreMap().values()) { ((HytaleAssetStore)assetStore).sendAssets(packetConsumer); } } finally { - AssetRegistry.ASSET_LOCK.writeLock().lock(); - - try { - HytaleAssetStore.SETUP_PACKET_CONSUMERS.remove(singlePacketConsumer); - } finally { - AssetRegistry.ASSET_LOCK.writeLock().unlock(); - } + HytaleAssetStore.SETUP_PACKET_CONSUMERS.remove(singlePacketConsumer); } } diff --git a/src/com/hypixel/hytale/server/core/asset/HytaleAssetStore.java b/src/com/hypixel/hytale/server/core/asset/HytaleAssetStore.java index 31dc4a27..189f11c6 100644 --- a/src/com/hypixel/hytale/server/core/asset/HytaleAssetStore.java +++ b/src/com/hypixel/hytale/server/core/asset/HytaleAssetStore.java @@ -24,15 +24,16 @@ import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.util.NotificationUtil; import com.hypixel.hytale.server.core.util.io.FileUtil; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectList; import java.io.IOException; import java.lang.ref.SoftReference; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.Objects; +import java.util.Queue; import java.util.Set; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Consumer; import java.util.function.Function; import java.util.logging.Level; @@ -41,7 +42,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class HytaleAssetStore, M extends AssetMap> extends AssetStore { - public static final ObjectList> SETUP_PACKET_CONSUMERS = new ObjectArrayList<>(); + public static final Queue> SETUP_PACKET_CONSUMERS = new ConcurrentLinkedQueue<>(); protected final AssetPacketGenerator packetGenerator; protected final Function notificationItemFunction; @Nullable @@ -92,8 +93,7 @@ public class HytaleAssetStore, M extends Ass Packet packet = this.packetGenerator.generateRemovePacket(this.assetMap, toBeRemoved, query); universe.broadcastPacketNoCache(packet); - for (int i = 0; i < SETUP_PACKET_CONSUMERS.size(); i++) { - Consumer c = SETUP_PACKET_CONSUMERS.get(i); + for (Consumer c : SETUP_PACKET_CONSUMERS) { c.accept(packet); } } @@ -102,8 +102,7 @@ public class HytaleAssetStore, M extends Ass Packet packet = this.packetGenerator.generateUpdatePacket(this.assetMap, toBeUpdated, query); universe.broadcastPacketNoCache(packet); - for (int i = 0; i < SETUP_PACKET_CONSUMERS.size(); i++) { - Consumer c = SETUP_PACKET_CONSUMERS.get(i); + for (Consumer c : SETUP_PACKET_CONSUMERS) { c.accept(packet); } } diff --git a/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.java b/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.java index 212f540c..a0f8522f 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.java +++ b/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.java @@ -54,6 +54,8 @@ public class BlockPlacementSettings implements NetworkSerializable placementSettings.ceilingPlacementOverrideBlockId ) .add() + .append(new KeyedCodec<>("AllowBreakReplace", Codec.BOOLEAN), (o, v) -> o.allowBreakReplace = v, o -> o.allowBreakReplace) + .add() .build(); protected String wallPlacementOverrideBlockId; protected String floorPlacementOverrideBlockId; @@ -62,6 +64,7 @@ public class BlockPlacementSettings implements NetworkSerializable (Ljava/lang/String;Ljava/lang/Throwable;)V - // 04d: athrow - // 04e: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.Default Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; - // 051: goto 063 - // 054: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.Default Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; - // 057: goto 063 - // 05a: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.AlwaysHidden Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; - // 05d: goto 063 - // 060: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.AlwaysVisible Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; - // 063: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.previewVisibility Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; - // 066: aload 1 - // 067: aload 0 - // 068: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.rotationMode Lcom/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings$RotationMode; - // 06b: astore 2 - // 06c: bipush 0 - // 06d: istore 3 - // 06e: aload 2 - // 06f: iload 3 - // 070: invokedynamic typeSwitch (Ljava/lang/Object;I)I bsm=java/lang/runtime/SwitchBootstraps.typeSwitch (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc; ] - // 075: tableswitch 35 -1 3 45 51 57 63 69 - // 098: new java/lang/MatchException - // 09b: dup - // 09c: aconst_null - // 09d: aconst_null - // 09e: invokespecial java/lang/MatchException. (Ljava/lang/String;Ljava/lang/Throwable;)V - // 0a1: athrow - // 0a2: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.Default Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; - // 0a5: goto 0bd - // 0a8: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.Default Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; - // 0ab: goto 0bd - // 0ae: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.FacingPlayer Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; - // 0b1: goto 0bd - // 0b4: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.StairFacingPlayer Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; - // 0b7: goto 0bd - // 0ba: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.BlockNormal Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; - // 0bd: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.rotationMode Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; - // 0c0: aload 1 - // 0c1: aload 0 - // 0c2: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.wallPlacementOverrideBlockId Ljava/lang/String; - // 0c5: ifnonnull 0cc - // 0c8: bipush -1 - // 0c9: goto 0d6 - // 0cc: invokestatic com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockType.getAssetMap ()Lcom/hypixel/hytale/assetstore/map/BlockTypeAssetMap; - // 0cf: aload 0 - // 0d0: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.wallPlacementOverrideBlockId Ljava/lang/String; - // 0d3: invokevirtual com/hypixel/hytale/assetstore/map/BlockTypeAssetMap.getIndex (Ljava/lang/Object;)I - // 0d6: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.wallPlacementOverrideBlockId I - // 0d9: aload 1 - // 0da: getfield com/hypixel/hytale/protocol/BlockPlacementSettings.wallPlacementOverrideBlockId I - // 0dd: ldc -2147483648 - // 0df: if_icmpne 0f3 - // 0e2: new java/lang/IllegalArgumentException - // 0e5: dup - // 0e6: aload 0 - // 0e7: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.wallPlacementOverrideBlockId Ljava/lang/String; - // 0ea: invokedynamic makeConcatWithConstants (Ljava/lang/String;)Ljava/lang/String; bsm=java/lang/invoke/StringConcatFactory.makeConcatWithConstants (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ "Unknown key! \u0001" ] - // 0ef: invokespecial java/lang/IllegalArgumentException. (Ljava/lang/String;)V - // 0f2: athrow - // 0f3: aload 1 - // 0f4: aload 0 - // 0f5: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.floorPlacementOverrideBlockId Ljava/lang/String; - // 0f8: ifnonnull 0ff - // 0fb: bipush -1 - // 0fc: goto 109 - // 0ff: invokestatic com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockType.getAssetMap ()Lcom/hypixel/hytale/assetstore/map/BlockTypeAssetMap; - // 102: aload 0 - // 103: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.floorPlacementOverrideBlockId Ljava/lang/String; - // 106: invokevirtual com/hypixel/hytale/assetstore/map/BlockTypeAssetMap.getIndex (Ljava/lang/Object;)I - // 109: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.floorPlacementOverrideBlockId I - // 10c: aload 1 - // 10d: getfield com/hypixel/hytale/protocol/BlockPlacementSettings.floorPlacementOverrideBlockId I - // 110: ldc -2147483648 - // 112: if_icmpne 126 - // 115: new java/lang/IllegalArgumentException - // 118: dup - // 119: aload 0 - // 11a: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.floorPlacementOverrideBlockId Ljava/lang/String; - // 11d: invokedynamic makeConcatWithConstants (Ljava/lang/String;)Ljava/lang/String; bsm=java/lang/invoke/StringConcatFactory.makeConcatWithConstants (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ "Unknown key! \u0001" ] - // 122: invokespecial java/lang/IllegalArgumentException. (Ljava/lang/String;)V - // 125: athrow - // 126: aload 1 - // 127: aload 0 - // 128: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.ceilingPlacementOverrideBlockId Ljava/lang/String; - // 12b: ifnonnull 132 - // 12e: bipush -1 - // 12f: goto 13c - // 132: invokestatic com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockType.getAssetMap ()Lcom/hypixel/hytale/assetstore/map/BlockTypeAssetMap; - // 135: aload 0 - // 136: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.ceilingPlacementOverrideBlockId Ljava/lang/String; - // 139: invokevirtual com/hypixel/hytale/assetstore/map/BlockTypeAssetMap.getIndex (Ljava/lang/Object;)I - // 13c: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.ceilingPlacementOverrideBlockId I - // 13f: aload 1 - // 140: getfield com/hypixel/hytale/protocol/BlockPlacementSettings.ceilingPlacementOverrideBlockId I - // 143: ldc -2147483648 - // 145: if_icmpne 159 - // 148: new java/lang/IllegalArgumentException - // 14b: dup - // 14c: aload 0 - // 14d: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.ceilingPlacementOverrideBlockId Ljava/lang/String; - // 150: invokedynamic makeConcatWithConstants (Ljava/lang/String;)Ljava/lang/String; bsm=java/lang/invoke/StringConcatFactory.makeConcatWithConstants (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ "Unknown key! \u0001" ] - // 155: invokespecial java/lang/IllegalArgumentException. (Ljava/lang/String;)V - // 158: athrow - // 159: aload 1 - // 15a: areturn + // 01a: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.allowBreakReplace Z + // 01d: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.allowBreakReplace Z + // 020: aload 1 + // 021: aload 0 + // 022: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.previewVisibility Lcom/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings$BlockPreviewVisibility; + // 025: astore 2 + // 026: bipush 0 + // 027: istore 3 + // 028: aload 2 + // 029: iload 3 + // 02a: invokedynamic typeSwitch (Ljava/lang/Object;I)I bsm=java/lang/runtime/SwitchBootstraps.typeSwitch (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc; ] + // 02f: tableswitch 29 -1 2 39 45 51 57 + // 04c: new java/lang/MatchException + // 04f: dup + // 050: aconst_null + // 051: aconst_null + // 052: invokespecial java/lang/MatchException. (Ljava/lang/String;Ljava/lang/Throwable;)V + // 055: athrow + // 056: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.Default Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; + // 059: goto 06b + // 05c: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.Default Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; + // 05f: goto 06b + // 062: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.AlwaysHidden Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; + // 065: goto 06b + // 068: getstatic com/hypixel/hytale/protocol/BlockPreviewVisibility.AlwaysVisible Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; + // 06b: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.previewVisibility Lcom/hypixel/hytale/protocol/BlockPreviewVisibility; + // 06e: aload 1 + // 06f: aload 0 + // 070: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.rotationMode Lcom/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings$RotationMode; + // 073: astore 2 + // 074: bipush 0 + // 075: istore 3 + // 076: aload 2 + // 077: iload 3 + // 078: invokedynamic typeSwitch (Ljava/lang/Object;I)I bsm=java/lang/runtime/SwitchBootstraps.typeSwitch (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc;, null.invoke Ljava/lang/Enum$EnumDesc; ] + // 07d: tableswitch 35 -1 3 45 51 57 63 69 + // 0a0: new java/lang/MatchException + // 0a3: dup + // 0a4: aconst_null + // 0a5: aconst_null + // 0a6: invokespecial java/lang/MatchException. (Ljava/lang/String;Ljava/lang/Throwable;)V + // 0a9: athrow + // 0aa: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.Default Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; + // 0ad: goto 0c5 + // 0b0: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.Default Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; + // 0b3: goto 0c5 + // 0b6: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.FacingPlayer Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; + // 0b9: goto 0c5 + // 0bc: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.StairFacingPlayer Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; + // 0bf: goto 0c5 + // 0c2: getstatic com/hypixel/hytale/protocol/BlockPlacementRotationMode.BlockNormal Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; + // 0c5: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.rotationMode Lcom/hypixel/hytale/protocol/BlockPlacementRotationMode; + // 0c8: aload 1 + // 0c9: aload 0 + // 0ca: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.wallPlacementOverrideBlockId Ljava/lang/String; + // 0cd: ifnonnull 0d4 + // 0d0: bipush -1 + // 0d1: goto 0de + // 0d4: invokestatic com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockType.getAssetMap ()Lcom/hypixel/hytale/assetstore/map/BlockTypeAssetMap; + // 0d7: aload 0 + // 0d8: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.wallPlacementOverrideBlockId Ljava/lang/String; + // 0db: invokevirtual com/hypixel/hytale/assetstore/map/BlockTypeAssetMap.getIndex (Ljava/lang/Object;)I + // 0de: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.wallPlacementOverrideBlockId I + // 0e1: aload 1 + // 0e2: getfield com/hypixel/hytale/protocol/BlockPlacementSettings.wallPlacementOverrideBlockId I + // 0e5: ldc -2147483648 + // 0e7: if_icmpne 0fb + // 0ea: new java/lang/IllegalArgumentException + // 0ed: dup + // 0ee: aload 0 + // 0ef: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.wallPlacementOverrideBlockId Ljava/lang/String; + // 0f2: invokedynamic makeConcatWithConstants (Ljava/lang/String;)Ljava/lang/String; bsm=java/lang/invoke/StringConcatFactory.makeConcatWithConstants (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ "Unknown key! \u0001" ] + // 0f7: invokespecial java/lang/IllegalArgumentException. (Ljava/lang/String;)V + // 0fa: athrow + // 0fb: aload 1 + // 0fc: aload 0 + // 0fd: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.floorPlacementOverrideBlockId Ljava/lang/String; + // 100: ifnonnull 107 + // 103: bipush -1 + // 104: goto 111 + // 107: invokestatic com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockType.getAssetMap ()Lcom/hypixel/hytale/assetstore/map/BlockTypeAssetMap; + // 10a: aload 0 + // 10b: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.floorPlacementOverrideBlockId Ljava/lang/String; + // 10e: invokevirtual com/hypixel/hytale/assetstore/map/BlockTypeAssetMap.getIndex (Ljava/lang/Object;)I + // 111: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.floorPlacementOverrideBlockId I + // 114: aload 1 + // 115: getfield com/hypixel/hytale/protocol/BlockPlacementSettings.floorPlacementOverrideBlockId I + // 118: ldc -2147483648 + // 11a: if_icmpne 12e + // 11d: new java/lang/IllegalArgumentException + // 120: dup + // 121: aload 0 + // 122: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.floorPlacementOverrideBlockId Ljava/lang/String; + // 125: invokedynamic makeConcatWithConstants (Ljava/lang/String;)Ljava/lang/String; bsm=java/lang/invoke/StringConcatFactory.makeConcatWithConstants (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ "Unknown key! \u0001" ] + // 12a: invokespecial java/lang/IllegalArgumentException. (Ljava/lang/String;)V + // 12d: athrow + // 12e: aload 1 + // 12f: aload 0 + // 130: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.ceilingPlacementOverrideBlockId Ljava/lang/String; + // 133: ifnonnull 13a + // 136: bipush -1 + // 137: goto 144 + // 13a: invokestatic com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockType.getAssetMap ()Lcom/hypixel/hytale/assetstore/map/BlockTypeAssetMap; + // 13d: aload 0 + // 13e: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.ceilingPlacementOverrideBlockId Ljava/lang/String; + // 141: invokevirtual com/hypixel/hytale/assetstore/map/BlockTypeAssetMap.getIndex (Ljava/lang/Object;)I + // 144: putfield com/hypixel/hytale/protocol/BlockPlacementSettings.ceilingPlacementOverrideBlockId I + // 147: aload 1 + // 148: getfield com/hypixel/hytale/protocol/BlockPlacementSettings.ceilingPlacementOverrideBlockId I + // 14b: ldc -2147483648 + // 14d: if_icmpne 161 + // 150: new java/lang/IllegalArgumentException + // 153: dup + // 154: aload 0 + // 155: getfield com/hypixel/hytale/server/core/asset/type/blocktype/config/BlockPlacementSettings.ceilingPlacementOverrideBlockId Ljava/lang/String; + // 158: invokedynamic makeConcatWithConstants (Ljava/lang/String;)Ljava/lang/String; bsm=java/lang/invoke/StringConcatFactory.makeConcatWithConstants (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; args=[ "Unknown key! \u0001" ] + // 15d: invokespecial java/lang/IllegalArgumentException. (Ljava/lang/String;)V + // 160: athrow + // 161: aload 1 + // 162: areturn } public String getWallPlacementOverrideBlockId() { diff --git a/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/CustomModelTexture.java b/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/CustomModelTexture.java index 537c83b6..2e7c7793 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/CustomModelTexture.java +++ b/src/com/hypixel/hytale/server/core/asset/type/blocktype/config/CustomModelTexture.java @@ -15,9 +15,10 @@ public class CustomModelTexture { ) .addValidator(CommonAssetValidator.TEXTURE_ITEM) .add() - .addField( + .append( new KeyedCodec<>("Weight", Codec.INTEGER), (customModelTexture, i) -> customModelTexture.weight = i, customModelTexture -> customModelTexture.weight ) + .add() .build(); private String texture; private int weight; diff --git a/src/com/hypixel/hytale/server/core/asset/type/buildertool/config/PrefabListAsset.java b/src/com/hypixel/hytale/server/core/asset/type/buildertool/config/PrefabListAsset.java index f38af830..cb693f85 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/buildertool/config/PrefabListAsset.java +++ b/src/com/hypixel/hytale/server/core/asset/type/buildertool/config/PrefabListAsset.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.EnumCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.codec.validation.ValidatorCache; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.server.core.prefab.PrefabStore; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.io.IOException; @@ -126,22 +127,33 @@ public class PrefabListAsset implements JsonAssetWithMap walk = Files.walk(this.rootDirectory.getPrefabPath().resolve(this.unprocessedPrefabPath), this.recursive ? 5 : 1)) { - walk.filter(x$0 -> Files.isRegularFile(x$0)).filter(path -> path.toString().endsWith(".prefab.json")).forEach(this.prefabPaths::add); - } catch (IOException var6) { - PrefabListAsset.getAssetStore() - .getLogger() - .at(Level.SEVERE) - .withCause(var6) - .log("Failed to process prefab path: %s", this.unprocessedPrefabPath); - } - } else { + Path prefabRoot = this.rootDirectory.getPrefabPath(); + if (!this.unprocessedPrefabPath.endsWith("/")) { if (!this.unprocessedPrefabPath.endsWith(".prefab.json")) { this.unprocessedPrefabPath = this.unprocessedPrefabPath + ".prefab.json"; } - this.prefabPaths.add(this.rootDirectory.getPrefabPath().resolve(this.unprocessedPrefabPath)); + Path resolved = PathUtil.resolvePathWithinDir(prefabRoot, this.unprocessedPrefabPath); + if (resolved == null) { + PrefabListAsset.getAssetStore().getLogger().at(Level.SEVERE).log("Invalid prefab path: %s", this.unprocessedPrefabPath); + } else { + this.prefabPaths.add(resolved); + } + } else { + Path resolved = PathUtil.resolvePathWithinDir(prefabRoot, this.unprocessedPrefabPath); + if (resolved == null) { + PrefabListAsset.getAssetStore().getLogger().at(Level.SEVERE).log("Invalid prefab path: %s", this.unprocessedPrefabPath); + } else { + try (Stream walk = Files.walk(resolved, this.recursive ? 5 : 1)) { + walk.filter(x$0 -> Files.isRegularFile(x$0)).filter(path -> path.toString().endsWith(".prefab.json")).forEach(this.prefabPaths::add); + } catch (IOException var8) { + PrefabListAsset.getAssetStore() + .getLogger() + .at(Level.SEVERE) + .withCause(var8) + .log("Failed to process prefab path: %s", this.unprocessedPrefabPath); + } + } } } } diff --git a/src/com/hypixel/hytale/server/core/asset/type/entityeffect/config/EntityEffect.java b/src/com/hypixel/hytale/server/core/asset/type/entityeffect/config/EntityEffect.java index 8caca2d7..6442253d 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/entityeffect/config/EntityEffect.java +++ b/src/com/hypixel/hytale/server/core/asset/type/entityeffect/config/EntityEffect.java @@ -192,7 +192,7 @@ public class EntityEffect entityEffect -> entityEffect.locale, (entityEffect, parent) -> entityEffect.locale = parent.locale ) - .documentation("An optional translation key, used to display the damage cause upon death.") + .documentation("[Deprecated - DeathMessageKey instead] Use An optional translation key, used to display the damage cause upon death.") .add() .appendInherited( new KeyedCodec<>("StatusEffectIcon", Codec.STRING), @@ -226,6 +226,14 @@ public class EntityEffect ) .addValidator(DamageCause.VALIDATOR_CACHE.getMapKeyValidator()) .add() + .appendInherited( + new KeyedCodec<>("DeathMessageKey", Codec.STRING), + (entityEffect, s) -> entityEffect.deathMessageKey = s, + entityEffect -> entityEffect.deathMessageKey, + (entityEffect, parent) -> entityEffect.deathMessageKey = parent.deathMessageKey + ) + .documentation("Localization key used on the death screen when this EntityEffect kills a player.") + .add() .afterDecode(entityEffect -> { entityEffect.entityStats = EntityStatsModule.resolveEntityStats(entityEffect.unknownEntityStats); entityEffect.statModifiers = EntityStatsModule.resolveEntityStats(entityEffect.rawStatModifiers); @@ -287,6 +295,7 @@ public class EntityEffect @Nullable protected String locale; protected boolean invulnerable = false; + protected String deathMessageKey; @Nullable protected Map rawStatModifiers; @Nullable @@ -418,6 +427,10 @@ public class EntityEffect return this.damageResistanceValues; } + public String getDeathMessageKey() { + return this.deathMessageKey; + } + @Nonnull public com.hypixel.hytale.protocol.EntityEffect toPacket() { com.hypixel.hytale.protocol.EntityEffect cached = this.cachedPacket == null ? null : this.cachedPacket.get(); diff --git a/src/com/hypixel/hytale/server/core/asset/type/fluid/DefaultFluidTicker.java b/src/com/hypixel/hytale/server/core/asset/type/fluid/DefaultFluidTicker.java index 4ec56458..299155bf 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/fluid/DefaultFluidTicker.java +++ b/src/com/hypixel/hytale/server/core/asset/type/fluid/DefaultFluidTicker.java @@ -110,7 +110,7 @@ public class DefaultFluidTicker extends FluidTicker { int z = offset.y; int blockX = worldX + x; int blockZ = worldZ + z; - if (!blocksFluidFrom(sourceBlock, sourceRotationIndex, -x, -z, sourceFiller)) { + if (!this.blocksFluidFrom(sourceBlock, sourceRotationIndex, -x, -z, sourceFiller)) { boolean isDifferentSection = !ChunkUtil.isSameChunkSection(worldX, worldY, worldZ, blockX, worldY, blockZ); FluidSection otherFluidSection = isDifferentSection ? accessor.getFluidSectionByBlock(blockX, worldY, blockZ) : fluidSection; BlockSection otherBlockSection = isDifferentSection ? accessor.getBlockSectionByBlock(blockX, worldY, blockZ) : blockSection; @@ -121,7 +121,7 @@ public class DefaultFluidTicker extends FluidTicker { BlockType block = blockMap.getAsset(otherBlockSection.get(blockX, worldY, blockZ)); int rotationIndex = otherBlockSection.getRotationIndex(blockX, worldY, blockZ); int destFiller = otherBlockSection.getFiller(blockX, worldY, blockZ); - if (!blocksFluidFrom(block, rotationIndex, x, z, destFiller)) { + if (!this.blocksFluidFrom(block, rotationIndex, x, z, destFiller)) { int otherFluidId = otherFluidSection.getFluidId(blockX, worldY, blockZ); if (otherFluidId != 0 && otherFluidId != spreadFluidId) { DefaultFluidTicker.FluidCollisionConfig config = this.getCollisionMap().get(otherFluidId); diff --git a/src/com/hypixel/hytale/server/core/asset/type/fluid/FireFluidTicker.java b/src/com/hypixel/hytale/server/core/asset/type/fluid/FireFluidTicker.java new file mode 100644 index 00000000..2346b328 --- /dev/null +++ b/src/com/hypixel/hytale/server/core/asset/type/fluid/FireFluidTicker.java @@ -0,0 +1,319 @@ +package com.hypixel.hytale.server.core.asset.type.fluid; + +import com.hypixel.hytale.assetstore.AssetExtraInfo; +import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap; +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.codec.codecs.array.ArrayCodec; +import com.hypixel.hytale.math.util.ChunkUtil; +import com.hypixel.hytale.math.vector.Vector3i; +import com.hypixel.hytale.protocol.SoundCategory; +import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; +import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent; +import com.hypixel.hytale.server.core.asset.type.tagpattern.config.TagPattern; +import com.hypixel.hytale.server.core.universe.world.SoundUtil; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection; +import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.IntSet; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class FireFluidTicker extends FluidTicker { + public static final BuilderCodec CODEC = BuilderCodec.builder(FireFluidTicker.class, FireFluidTicker::new, BASE_CODEC) + .appendInherited( + new KeyedCodec<>("SpreadFluid", Codec.STRING), + (ticker, o) -> ticker.spreadFluid = o, + ticker -> ticker.spreadFluid, + (ticker, parent) -> ticker.spreadFluid = parent.spreadFluid + ) + .addValidator(Fluid.VALIDATOR_CACHE.getValidator().late()) + .add() + .appendInherited( + new KeyedCodec<>("Flammability", new ArrayCodec<>(FireFluidTicker.FlammabilityConfig.CODEC, FireFluidTicker.FlammabilityConfig[]::new)), + (ticker, o) -> { + List combined = new ArrayList<>(); + if (ticker.rawFlammabilityConfigs != null) { + Collections.addAll(combined, ticker.rawFlammabilityConfigs); + } + + Collections.addAll(combined, o); + ticker.rawFlammabilityConfigs = combined.toArray(new FireFluidTicker.FlammabilityConfig[0]); + }, + ticker -> ticker.rawFlammabilityConfigs, + (ticker, parent) -> ticker.rawFlammabilityConfigs = parent.rawFlammabilityConfigs + ) + .documentation("Defines flammability configs per tag pattern") + .add() + .build(); + public static final FireFluidTicker INSTANCE = new FireFluidTicker(); + private static final Vector3i[] OFFSETS = new Vector3i[]{ + new Vector3i(0, -1, 0), new Vector3i(0, 1, 0), new Vector3i(0, 0, -1), new Vector3i(0, 0, 1), new Vector3i(-1, 0, 0), new Vector3i(1, 0, 0) + }; + private String spreadFluid; + private int spreadFluidId; + private FireFluidTicker.FlammabilityConfig[] rawFlammabilityConfigs = new FireFluidTicker.FlammabilityConfig[0]; + @Nullable + private transient List sortedFlammabilityConfigs = null; + + @Nonnull + @Override + protected FluidTicker.AliveStatus isAlive( + @Nonnull FluidTicker.Accessor accessor, + @Nonnull FluidSection fluidSection, + @Nonnull BlockSection blockSection, + Fluid fluid, + int fluidId, + byte fluidLevel, + int worldX, + int worldY, + int worldZ + ) { + return FluidTicker.AliveStatus.ALIVE; + } + + @Nonnull + @Override + protected BlockTickStrategy spread( + @Nonnull World world, + long tick, + @Nonnull FluidTicker.Accessor accessor, + @Nonnull FluidSection fluidSection, + BlockSection blockSection, + @Nonnull Fluid fluid, + int fluidId, + byte fluidLevel, + int worldX, + int worldY, + int worldZ + ) { + BlockTypeAssetMap blockMap = BlockType.getAssetMap(); + int spreadFluidId = this.getSpreadFluidId(fluidId); + BlockType currentBlock = blockMap.getAsset(blockSection.get(worldX, worldY, worldZ)); + int maxLevel = fluid.getMaxFluidLevel(); + if (fluidLevel < maxLevel) { + fluidSection.setFluid(worldX, worldY, worldZ, fluidId, ++fluidLevel); + } + + for (Vector3i offset : OFFSETS) { + int x = offset.x; + int y = offset.y; + int z = offset.z; + int blockX = worldX + x; + int blockY = worldY + y; + int blockZ = worldZ + z; + if (blockY >= 0 && blockY < 256) { + boolean isDifferentSection = !ChunkUtil.isSameChunkSection(worldX, worldY, worldZ, blockX, blockY, blockZ); + FluidSection otherFluidSection = isDifferentSection ? accessor.getFluidSectionByBlock(blockX, blockY, blockZ) : fluidSection; + BlockSection otherBlockSection = isDifferentSection ? accessor.getBlockSectionByBlock(blockX, blockY, blockZ) : blockSection; + if (otherFluidSection == null || otherBlockSection == null) { + return BlockTickStrategy.WAIT_FOR_ADJACENT_CHUNK_LOAD; + } + + int otherBlockId = otherBlockSection.get(blockX, blockY, blockZ); + BlockType otherBlock = blockMap.getAsset(otherBlockId); + int otherFluidId = otherFluidSection.getFluidId(blockX, blockY, blockZ); + if (otherFluidId == 0) { + boolean isFlammable = this.getFlammabilityForBlock(otherBlock) != null; + if (isFlammable) { + otherFluidSection.setFluid(blockX, blockY, blockZ, spreadFluidId, (byte)1); + otherBlockSection.setTicking(blockX, blockY, blockZ, true); + } + } + } + } + + FireFluidTicker.FlammabilityConfig currentFlammability = this.getFlammabilityForBlock(currentBlock); + if (currentFlammability == null) { + fluidSection.setFluid(worldX, worldY, worldZ, 0, (byte)0); + return BlockTickStrategy.SLEEP; + } else { + ThreadLocalRandom random = ThreadLocalRandom.current(); + if (fluidLevel >= currentFlammability.getBurnLevel() && random.nextFloat() < currentFlammability.getBurnChance()) { + this.tryBurn(world, accessor, fluidSection, blockSection, currentFlammability, worldX, worldY, worldZ); + return BlockTickStrategy.SLEEP; + } else { + return BlockTickStrategy.CONTINUE; + } + } + } + + @Nullable + private FireFluidTicker.FlammabilityConfig getFlammabilityForBlock(@Nonnull BlockType block) { + List configs = this.getSortedFlammabilityConfigs(); + AssetExtraInfo.Data data = block.getData(); + if (data == null) { + return null; + } else { + Int2ObjectMap blockTags = data.getTags(); + + for (FireFluidTicker.FlammabilityConfig config : configs) { + TagPattern tagPattern = config.getTagPattern(); + if (tagPattern != null && tagPattern.test(blockTags)) { + return config; + } + } + + return null; + } + } + + @Override + public boolean canOccupySolidBlocks() { + return true; + } + + private boolean tryBurn( + @Nonnull World world, + @Nonnull FluidTicker.Accessor accessor, + @Nonnull FluidSection fluidSection, + BlockSection blockSection, + @Nonnull FireFluidTicker.FlammabilityConfig config, + int blockX, + int blockY, + int blockZ + ) { + int resultingBlockIndex = config.getResultingBlockIndex(); + if (resultingBlockIndex != Integer.MIN_VALUE) { + int originalRotation = blockSection.getRotationIndex(blockX, blockY, blockZ); + int originalFiller = blockSection.getFiller(blockX, blockY, blockZ); + blockSection.set(blockX, blockY, blockZ, resultingBlockIndex, originalRotation, originalFiller); + setTickingSurrounding(accessor, blockSection, blockX, blockY, blockZ); + } + + int soundEvent = config.getSoundEventIndex(); + if (soundEvent != Integer.MIN_VALUE) { + world.execute(() -> SoundUtil.playSoundEvent3d(soundEvent, SoundCategory.SFX, blockX, blockY, blockZ, world.getEntityStore().getStore())); + } + + fluidSection.setFluid(blockX, blockY, blockZ, 0, (byte)0); + return true; + } + + @Override + public boolean isSelfFluid(int selfFluidId, int otherFluidId) { + return super.isSelfFluid(selfFluidId, otherFluidId) || otherFluidId == this.getSpreadFluidId(selfFluidId); + } + + private int getSpreadFluidId(int fluidId) { + if (this.spreadFluidId == 0) { + if (this.spreadFluid != null) { + this.spreadFluidId = Fluid.getAssetMap().getIndex(this.spreadFluid); + } else { + this.spreadFluidId = Integer.MIN_VALUE; + } + } + + return this.spreadFluidId == Integer.MIN_VALUE ? fluidId : this.spreadFluidId; + } + + @Nonnull + public List getSortedFlammabilityConfigs() { + if (this.sortedFlammabilityConfigs == null) { + List configs = new ArrayList<>(); + if (this.rawFlammabilityConfigs != null) { + Collections.addAll(configs, this.rawFlammabilityConfigs); + } + + configs.sort(Comparator.comparingInt(FireFluidTicker.FlammabilityConfig::getPriority).reversed()); + this.sortedFlammabilityConfigs = configs; + } + + return this.sortedFlammabilityConfigs; + } + + public static class FlammabilityConfig { + public static final BuilderCodec CODEC = BuilderCodec.builder( + FireFluidTicker.FlammabilityConfig.class, FireFluidTicker.FlammabilityConfig::new + ) + .appendInherited( + new KeyedCodec<>("TagPattern", TagPattern.CHILD_ASSET_CODEC), + (o, v) -> o.tagPatternId = v, + o -> o.tagPatternId, + (o, p) -> o.tagPatternId = p.tagPatternId + ) + .addValidator(TagPattern.VALIDATOR_CACHE.getValidator()) + .documentation("TagPattern to match blocks that this config applies to") + .add() + .appendInherited(new KeyedCodec<>("Priority", Codec.INTEGER), (o, v) -> o.priority = v, o -> o.priority, (o, p) -> o.priority = p.priority) + .documentation("Priority for pattern matching - higher values are checked first") + .add() + .appendInherited(new KeyedCodec<>("BurnLevel", Codec.BYTE), (o, v) -> o.burnLevel = v, o -> o.burnLevel, (o, p) -> o.burnLevel = p.burnLevel) + .documentation("The fluid level the fluid has to be greater than or equal to to burn this block") + .add() + .appendInherited( + new KeyedCodec<>("BurnChance", Codec.FLOAT), (o, v) -> o.burnChance = v, o -> o.burnChance, (o, p) -> o.burnChance = p.burnChance + ) + .documentation("Probability (0.0 to 1.0) that the block will burn each tick when above the burn level") + .add() + .appendInherited( + new KeyedCodec<>("ResultingBlock", Codec.STRING), + (o, v) -> o.resultingBlock = v, + o -> o.resultingBlock, + (o, p) -> o.resultingBlock = p.resultingBlock + ) + .documentation("The block to place after burning, if any") + .add() + .appendInherited( + new KeyedCodec<>("SoundEvent", Codec.STRING), (o, v) -> o.soundEvent = v, o -> o.soundEvent, (o, p) -> o.soundEvent = p.soundEvent + ) + .addValidator(SoundEvent.VALIDATOR_CACHE.getValidator()) + .add() + .build(); + private String tagPatternId; + @Nullable + private transient TagPattern tagPattern = null; + private int priority; + private byte burnLevel = 1; + private float burnChance = 0.1F; + private String resultingBlock = "Empty"; + private int resultingBlockIndex = Integer.MIN_VALUE; + private String soundEvent; + private int soundEventIndex = Integer.MIN_VALUE; + + @Nullable + public TagPattern getTagPattern() { + if (this.tagPattern == null && this.tagPatternId != null) { + this.tagPattern = TagPattern.getAssetMap().getAsset(this.tagPatternId); + } + + return this.tagPattern; + } + + public int getPriority() { + return this.priority; + } + + public byte getBurnLevel() { + return this.burnLevel; + } + + public float getBurnChance() { + return this.burnChance; + } + + public int getResultingBlockIndex() { + if (this.resultingBlockIndex == Integer.MIN_VALUE && this.resultingBlock != null) { + this.resultingBlockIndex = BlockType.getBlockIdOrUnknown(this.resultingBlock, "Unknown block type %s", this.resultingBlock); + } + + return this.resultingBlockIndex; + } + + public int getSoundEventIndex() { + if (this.soundEventIndex == Integer.MIN_VALUE && this.soundEvent != null) { + this.soundEventIndex = SoundEvent.getAssetMap().getIndex(this.soundEvent); + } + + return this.soundEventIndex; + } + } +} diff --git a/src/com/hypixel/hytale/server/core/asset/type/fluid/Fluid.java b/src/com/hypixel/hytale/server/core/asset/type/fluid/Fluid.java index 03047785..70dc07ad 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/fluid/Fluid.java +++ b/src/com/hypixel/hytale/server/core/asset/type/fluid/Fluid.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.codecs.EnumCodec; import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.codec.codecs.map.EnumMapCodec; +import com.hypixel.hytale.codec.schema.metadata.ui.UIDefaultCollapsedState; import com.hypixel.hytale.codec.schema.metadata.ui.UIEditorSectionStart; import com.hypixel.hytale.codec.schema.metadata.ui.UIPropertyTitle; import com.hypixel.hytale.codec.schema.metadata.ui.UIRebuildCaches; @@ -21,6 +22,7 @@ import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.protocol.BlockTextures; import com.hypixel.hytale.protocol.Color; import com.hypixel.hytale.protocol.ColorLight; +import com.hypixel.hytale.protocol.FluidDrawType; import com.hypixel.hytale.protocol.InteractionType; import com.hypixel.hytale.protocol.Opacity; import com.hypixel.hytale.protocol.ShaderType; @@ -28,6 +30,7 @@ import com.hypixel.hytale.server.core.asset.type.blockparticle.config.BlockParti import com.hypixel.hytale.server.core.asset.type.blocksound.config.BlockSoundSet; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockTypeTextures; import com.hypixel.hytale.server.core.asset.type.fluidfx.config.FluidFX; +import com.hypixel.hytale.server.core.asset.type.model.config.ModelParticle; import com.hypixel.hytale.server.core.codec.ProtocolCodecs; import com.hypixel.hytale.server.core.io.NetworkSerializable; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.InteractionTypeUtils; @@ -61,7 +64,7 @@ public class Fluid implements JsonAssetWithMap fluid.textures, (fluid, parent) -> fluid.textures = parent.textures ) - .metadata(new UIPropertyTitle("Block Textures")) + .metadata(new UIPropertyTitle("Fluid Textures")) .metadata(new UIRebuildCaches(UIRebuildCaches.ClientCache.MODELS, UIRebuildCaches.ClientCache.BLOCK_TEXTURES)) .add() .appendInherited( @@ -72,6 +75,16 @@ public class Fluid implements JsonAssetWithMapappendInherited( + new KeyedCodec<>("DrawType", new EnumCodec<>(FluidDrawType.class)), + (fluid, o) -> fluid.drawType = o, + fluid -> fluid.drawType, + (fluid, parent) -> fluid.drawType = parent.drawType + ) + .addValidator(Validators.nonNull()) + .metadata(new UIRebuildCaches(UIRebuildCaches.ClientCache.MODELS, UIRebuildCaches.ClientCache.BLOCK_TEXTURES, UIRebuildCaches.ClientCache.MODEL_TEXTURES)) + .metadata(new UIEditorSectionStart("Rendering")) + .add() .appendInherited( new KeyedCodec<>("Opacity", new EnumCodec<>(Opacity.class)), (fluid, o) -> fluid.opacity = o, @@ -96,6 +109,18 @@ public class Fluid implements JsonAssetWithMapappendInherited( + new KeyedCodec<>("Particles", ModelParticle.ARRAY_CODEC), + (fluid, s) -> fluid.particles = s, + fluid -> fluid.particles, + (fluid, parent) -> fluid.particles = parent.particles + ) + .documentation("The particles defined here will be spawned on top of fluids of this type placed in the world.") + .metadata(new UIPropertyTitle("Fluid Particles")) + .metadata(new UIRebuildCaches(UIRebuildCaches.ClientCache.MODELS)) + .metadata(UIDefaultCollapsedState.UNCOLLAPSED) + .addValidator(Validators.nonNullArrayElements()) + .add() .appendInherited( new KeyedCodec<>("Ticker", FluidTicker.CODEC), (fluid, o) -> fluid.ticker = o, fluid -> fluid.ticker, (fluid, parent) -> fluid.ticker = parent.ticker ) @@ -195,6 +220,8 @@ public class Fluid implements JsonAssetWithMap 0) { + packet.particles = new com.hypixel.hytale.protocol.ModelParticle[this.particles.length]; + + for (int i = 0; i < this.particles.length; i++) { + packet.particles[i] = this.particles[i].toPacket(); + } + } + + packet.drawType = this.drawType; packet.requiresAlphaBlending = this.requiresAlphaBlending; packet.blockSoundSetIndex = this.blockSoundSetIndex; packet.blockParticleSetId = this.blockParticleSetId; diff --git a/src/com/hypixel/hytale/server/core/asset/type/fluid/FluidTicker.java b/src/com/hypixel/hytale/server/core/asset/type/fluid/FluidTicker.java index 34080fe7..4f7280b5 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/fluid/FluidTicker.java +++ b/src/com/hypixel/hytale/server/core/asset/type/fluid/FluidTicker.java @@ -92,7 +92,7 @@ public abstract class FluidTicker { int worldZ ) { int block = blockSection.get(worldX, worldY, worldZ); - if (isFullySolid(BlockType.getAssetMap().getAsset(block))) { + if (!this.canOccupySolidBlocks() && isFullySolid(BlockType.getAssetMap().getAsset(block))) { fluidSection.setFluid(worldX, worldY, worldZ, 0, (byte)0); setTickingSurrounding(cachedAccessor, blockSection, worldX, worldY, worldZ); return BlockTickStrategy.SLEEP; @@ -107,6 +107,10 @@ public abstract class FluidTicker { } } + public boolean canOccupySolidBlocks() { + return false; + } + public BlockTickStrategy process( World world, long tick, @@ -185,8 +189,8 @@ public abstract class FluidTicker { if (sourceBlock != null) { int sourceRotation = otherBlockSection.getRotationIndex(blockX, worldY, blockZ); int sourceFiller = otherBlockSection.getFiller(blockX, worldY, blockZ); - if (!blocksFluidFrom(sourceBlock, sourceRotation, x, z, sourceFiller) - && !blocksFluidFrom(thisBlock, thisRotation, -x, -z, thisFiller)) { + if (!this.blocksFluidFrom(sourceBlock, sourceRotation, x, z, sourceFiller) + && !this.blocksFluidFrom(thisBlock, thisRotation, -x, -z, thisFiller)) { return FluidTicker.AliveStatus.ALIVE; } } @@ -197,8 +201,8 @@ public abstract class FluidTicker { if (sourceBlock != null) { int sourceRotation = otherBlockSection.getRotationIndex(blockX, worldY, blockZ); int sourceFiller = otherBlockSection.getFiller(blockX, worldY, blockZ); - if (!blocksFluidFrom(sourceBlock, sourceRotation, x, z, sourceFiller) - && !blocksFluidFrom(thisBlock, thisRotation, -x, -z, thisFiller)) { + if (!this.blocksFluidFrom(sourceBlock, sourceRotation, x, z, sourceFiller) + && !this.blocksFluidFrom(thisBlock, thisRotation, -x, -z, thisFiller)) { return FluidTicker.AliveStatus.ALIVE; } } @@ -351,11 +355,11 @@ public abstract class FluidTicker { return drawType == DrawType.Cube || drawType == DrawType.CubeWithModel; } - public static boolean blocksFluidFrom(@Nonnull BlockType blockType, int rotationIndex, int offsetX, int offsetZ) { - return blocksFluidFrom(blockType, rotationIndex, offsetX, offsetZ, 0); + public boolean blocksFluidFrom(@Nonnull BlockType blockType, int rotationIndex, int offsetX, int offsetZ) { + return this.blocksFluidFrom(blockType, rotationIndex, offsetX, offsetZ, 0); } - public static boolean blocksFluidFrom(@Nonnull BlockType blockType, int rotationIndex, int offsetX, int offsetZ, int filler) { + public boolean blocksFluidFrom(@Nonnull BlockType blockType, int rotationIndex, int offsetX, int offsetZ, int filler) { if (blockType.getMaterial() != BlockMaterial.Solid) { return false; } else if (isFullySolid(blockType)) { @@ -503,7 +507,7 @@ public abstract class FluidTicker { void setBlock(int var1, int var2, int var3, int var4); } - protected static enum AliveStatus { + public static enum AliveStatus { ALIVE, DEMOTE, WAIT_FOR_ADJACENT_CHUNK; diff --git a/src/com/hypixel/hytale/server/core/asset/type/gameplay/WorldConfig.java b/src/com/hypixel/hytale/server/core/asset/type/gameplay/WorldConfig.java index 457f3cb2..803f64dc 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/gameplay/WorldConfig.java +++ b/src/com/hypixel/hytale/server/core/asset/type/gameplay/WorldConfig.java @@ -3,6 +3,7 @@ package com.hypixel.hytale.server.core.asset.type.gameplay; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.server.core.asset.type.gameplay.sleep.SleepConfig; import javax.annotation.Nonnull; public class WorldConfig { diff --git a/src/com/hypixel/hytale/server/core/asset/type/gameplay/SleepConfig.java b/src/com/hypixel/hytale/server/core/asset/type/gameplay/sleep/SleepConfig.java similarity index 88% rename from src/com/hypixel/hytale/server/core/asset/type/gameplay/SleepConfig.java rename to src/com/hypixel/hytale/server/core/asset/type/gameplay/sleep/SleepConfig.java index 71aec8c8..e927d33d 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/gameplay/SleepConfig.java +++ b/src/com/hypixel/hytale/server/core/asset/type/gameplay/sleep/SleepConfig.java @@ -1,4 +1,4 @@ -package com.hypixel.hytale.server.core.asset.type.gameplay; +package com.hypixel.hytale.server.core.asset.type.gameplay.sleep; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; @@ -22,10 +22,13 @@ public class SleepConfig { .addValidator(Validators.doubleArraySize(2)) .documentation("The in-game hours during which players can sleep to skip to the WakeUpHour. If missing, there is no restriction.") .add() + .append(new KeyedCodec<>("Sounds", SleepSoundsConfig.CODEC), (sleepConfig, i) -> sleepConfig.sounds = i, sleepConfig -> sleepConfig.sounds) + .add() .build(); public static final SleepConfig DEFAULT = new SleepConfig(); private float wakeUpHour = 5.5F; private double[] allowedSleepHoursRange; + private SleepSoundsConfig sounds = new SleepSoundsConfig(); public float getWakeUpHour() { return this.wakeUpHour; @@ -36,6 +39,10 @@ public class SleepConfig { return this.allowedSleepHoursRange; } + public SleepSoundsConfig getSounds() { + return this.sounds; + } + @Nullable public LocalTime getSleepStartTime() { if (this.allowedSleepHoursRange == null) { diff --git a/src/com/hypixel/hytale/server/core/asset/type/gameplay/sleep/SleepSoundsConfig.java b/src/com/hypixel/hytale/server/core/asset/type/gameplay/sleep/SleepSoundsConfig.java new file mode 100644 index 00000000..67b7440f --- /dev/null +++ b/src/com/hypixel/hytale/server/core/asset/type/gameplay/sleep/SleepSoundsConfig.java @@ -0,0 +1,90 @@ +package com.hypixel.hytale.server.core.asset.type.gameplay.sleep; + +import com.hypixel.hytale.codec.Codec; +import com.hypixel.hytale.codec.KeyedCodec; +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent; +import javax.annotation.Nullable; + +public class SleepSoundsConfig { + public static final BuilderCodec CODEC = BuilderCodec.builder(SleepSoundsConfig.class, SleepSoundsConfig::new) + .append(new KeyedCodec<>("Success", Codec.STRING), (config, o) -> config.success = o, config -> config.success) + .addValidator(SoundEvent.VALIDATOR_CACHE.getValidator()) + .add() + .append(new KeyedCodec<>("Fail", Codec.STRING), (config, o) -> config.fail = o, config -> config.fail) + .addValidator(SoundEvent.VALIDATOR_CACHE.getValidator()) + .add() + .append(new KeyedCodec<>("Notification", Codec.STRING), (config, o) -> config.notification = o, config -> config.notification) + .addValidator(SoundEvent.VALIDATOR_CACHE.getValidator()) + .add() + .append(new KeyedCodec<>("NotificationLoop", Codec.STRING), (config, o) -> config.notificationLoop = o, config -> config.notificationLoop) + .addValidator(SoundEvent.VALIDATOR_CACHE.getValidator()) + .add() + .append( + new KeyedCodec<>("NotificationCooldownSeconds", Codec.INTEGER), + (config, o) -> config.notificationCooldownSeconds = o, + config -> config.notificationCooldownSeconds + ) + .add() + .append( + new KeyedCodec<>("NotificationLoopEnabled", Codec.BOOLEAN), + (config, o) -> config.notificationLoopEnabled = o, + config -> config.notificationLoopEnabled + ) + .add() + .build(); + private String success = "SFX_Sleep_Success"; + private String fail = "SFX_Sleep_Fail"; + private String notification = "SFX_Sleep_Notification"; + private String notificationLoop = "SFX_Sleep_Notification_Loop"; + private int notificationCooldownSeconds = 30; + private boolean notificationLoopEnabled = true; + + @Nullable + public String getSuccess() { + return this.success; + } + + public int getSuccessIndex() { + return SoundEvent.getAssetMap().getIndex(this.success); + } + + @Nullable + public String getFail() { + return this.fail; + } + + public int getFailIndex() { + return SoundEvent.getAssetMap().getIndex(this.fail); + } + + @Nullable + public String getNotification() { + return this.notification; + } + + public int getNotificationIndex() { + return SoundEvent.getAssetMap().getIndex(this.notification); + } + + @Nullable + public String getNotificationLoop() { + return this.notificationLoop; + } + + public int getNotificationLoopIndex() { + return SoundEvent.getAssetMap().getIndex(this.notificationLoop); + } + + public long getNotificationCooldownSeconds() { + return this.notificationCooldownSeconds; + } + + public long getNotificationLoopCooldownMs() { + return this.notificationCooldownSeconds * 1000; + } + + public boolean isNotificationLoopEnabled() { + return this.notificationLoopEnabled; + } +} diff --git a/src/com/hypixel/hytale/server/core/asset/type/projectile/config/Projectile.java b/src/com/hypixel/hytale/server/core/asset/type/projectile/config/Projectile.java index 0657ef43..483c5262 100644 --- a/src/com/hypixel/hytale/server/core/asset/type/projectile/config/Projectile.java +++ b/src/com/hypixel/hytale/server/core/asset/type/projectile/config/Projectile.java @@ -389,6 +389,7 @@ public class Projectile implements JsonAssetWithMap> ASSET_STORE; + @Nonnull public static final ValidatorCache VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(WordList::getAssetStore)); private static final WordList EMPTY = new WordList(); protected AssetExtraInfo.Data data; protected String id; protected String[] translationKeys; + @Nonnull public static AssetStore> getAssetStore() { if (ASSET_STORE == null) { ASSET_STORE = AssetRegistry.getAssetStore(WordList.class); diff --git a/src/com/hypixel/hytale/server/core/auth/EncryptedAuthCredentialStoreProvider.java b/src/com/hypixel/hytale/server/core/auth/EncryptedAuthCredentialStoreProvider.java index 4d6f7f1c..afbf8526 100644 --- a/src/com/hypixel/hytale/server/core/auth/EncryptedAuthCredentialStoreProvider.java +++ b/src/com/hypixel/hytale/server/core/auth/EncryptedAuthCredentialStoreProvider.java @@ -3,6 +3,7 @@ package com.hypixel.hytale.server.core.auth; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.common.util.PathUtil; import java.nio.file.Path; import javax.annotation.Nonnull; @@ -20,7 +21,12 @@ public class EncryptedAuthCredentialStoreProvider implements AuthCredentialStore @Nonnull @Override public IAuthCredentialStore createStore() { - return new EncryptedAuthCredentialStore(Path.of(this.path)); + Path resolved = Path.of(this.path); + if (!PathUtil.isInTrustedRoot(resolved)) { + throw new IllegalStateException("Auth credential store path must be within a trusted directory: " + this.path); + } else { + return new EncryptedAuthCredentialStore(resolved); + } } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/command/commands/debug/AssetsCommand.java b/src/com/hypixel/hytale/server/core/command/commands/debug/AssetsCommand.java index 09d1e29f..a233c18f 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/debug/AssetsCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/debug/AssetsCommand.java @@ -21,7 +21,7 @@ public class AssetsCommand extends AbstractCommandCollection { public static class AssetLongestAssetNameCommand extends AbstractAsyncCommand { public AssetLongestAssetNameCommand() { - super("longest", ""); + super("longest", "server.commands.assets.longest.desc"); } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionAddCommand.java b/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionAddCommand.java index 86f4595c..a179f86b 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionAddCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionAddCommand.java @@ -38,7 +38,7 @@ public class HitboxCollisionAddCommand extends AbstractCommandCollection { "hitboxCollisionConfig", "server.commands.hitboxcollision.add.hitboxCollisionConfig.desc", ArgTypes.HITBOX_COLLISION_CONFIG ); @Nonnull - private final EntityWrappedArg entityArg = this.withOptionalArg("entity", "server.commands.hitboxcollision.add.entity.desc", ArgTypes.ENTITY_ID); + private final EntityWrappedArg entityArg = this.withOptionalArg("entity", "server.commands.hitboxcollision.add.entityArg.desc", ArgTypes.ENTITY_ID); public HitboxCollisionAddEntityCommand() { super("entity", "server.commands.hitboxcollision.add.entity.desc"); diff --git a/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionRemoveCommand.java b/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionRemoveCommand.java index 88fe8433..f01eca40 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionRemoveCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/debug/component/hitboxcollision/HitboxCollisionRemoveCommand.java @@ -26,7 +26,7 @@ public class HitboxCollisionRemoveCommand extends AbstractCommandCollection { public static class HitboxCollisionRemoveEntityCommand extends AbstractWorldCommand { @Nonnull - private final EntityWrappedArg entityArg = this.withRequiredArg("entity", "server.commands.hitboxcollision.remove.entity.desc", ArgTypes.ENTITY_ID); + private final EntityWrappedArg entityArg = this.withRequiredArg("entity", "server.commands.hitboxcollision.remove.entityArg.desc", ArgTypes.ENTITY_ID); public HitboxCollisionRemoveEntityCommand() { super("entity", "server.commands.hitboxcollision.remove.entity.desc"); diff --git a/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionAddCommand.java b/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionAddCommand.java index fcfde07d..e09c8d2b 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionAddCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionAddCommand.java @@ -37,7 +37,7 @@ public class RepulsionAddCommand extends AbstractCommandCollection { "repulsionConfig", "server.commands.repulsion.add.repulsionConfig.desc", ArgTypes.REPULSION_CONFIG ); @Nonnull - private final EntityWrappedArg entityArg = this.withRequiredArg("entity", "server.commands.repulsion.add.entity.desc", ArgTypes.ENTITY_ID); + private final EntityWrappedArg entityArg = this.withRequiredArg("entity", "server.commands.repulsion.add.entityArg.desc", ArgTypes.ENTITY_ID); public RepulsionAddEntityCommand() { super("entity", "server.commands.repulsion.add.entity.desc"); diff --git a/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionRemoveCommand.java b/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionRemoveCommand.java index e207b8ad..60b39486 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionRemoveCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/debug/component/repulsion/RepulsionRemoveCommand.java @@ -30,7 +30,7 @@ public class RepulsionRemoveCommand extends AbstractCommandCollection { @Nonnull private static final Message MESSAGE_COMMANDS_REPULSION_REMOVE_SUCCESS = Message.translation("server.commands.repulsion.remove.success"); @Nonnull - private final EntityWrappedArg entityArg = this.withRequiredArg("entity", "server.commands.repulsion.remove.entity.desc", ArgTypes.ENTITY_ID); + private final EntityWrappedArg entityArg = this.withRequiredArg("entity", "server.commands.repulsion.remove.entityArg.desc", ArgTypes.ENTITY_ID); public RepulsionRemoveEntityCommand() { super("entity", "server.commands.repulsion.remove.entity.desc"); diff --git a/src/com/hypixel/hytale/server/core/command/commands/debug/stresstest/Bot.java b/src/com/hypixel/hytale/server/core/command/commands/debug/stresstest/Bot.java index bd9a4814..c30cd1ff 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/debug/stresstest/Bot.java +++ b/src/com/hypixel/hytale/server/core/command/commands/debug/stresstest/Bot.java @@ -170,7 +170,7 @@ public class Bot extends SimpleChannelInboundHandler { @Override public void channelActive(@Nonnull ChannelHandlerContext ctx) { UUID uuid = UUID.nameUUIDFromBytes(("BOT|" + this.name).getBytes(StandardCharsets.UTF_8)); - ctx.writeAndFlush(new Connect(701662755, 5, "bot", ClientType.Game, uuid, this.name, null, "en", null, null)); + ctx.writeAndFlush(new Connect(672031543, 12, "bot", ClientType.Game, uuid, this.name, null, "en", null, null)); this.logger.at(Level.INFO).log("Connected!"); } diff --git a/src/com/hypixel/hytale/server/core/command/commands/player/inventory/GiveCommand.java b/src/com/hypixel/hytale/server/core/command/commands/player/inventory/GiveCommand.java index b0eee4e0..d46d3462 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/player/inventory/GiveCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/player/inventory/GiveCommand.java @@ -66,7 +66,7 @@ public class GiveCommand extends AbstractPlayerCommand { } ItemStack stack = new ItemStack(item.getId(), quantity, metadata).withDurability(durability); - ItemStackTransaction transaction = playerComponent.getInventory().getCombinedHotbarFirst().addItemStack(stack); + ItemStackTransaction transaction = playerComponent.giveItem(stack, ref, store); ItemStack remainder = transaction.getRemainder(); Message itemNameMessage = Message.translation(item.getTranslationKey()); if (remainder != null && !remainder.isEmpty()) { @@ -132,7 +132,7 @@ public class GiveCommand extends AbstractPlayerCommand { } ItemStack stack = new ItemStack(item.getId(), quantity, metadata).withDurability(durability); - ItemStackTransaction transaction = playerComponent.getInventory().getCombinedHotbarFirst().addItemStack(stack); + ItemStackTransaction transaction = playerComponent.giveItem(stack, ref, store); ItemStack remainder = transaction.getRemainder(); Message itemNameMessage = Message.translation(item.getTranslationKey()); if (remainder != null && !remainder.isEmpty()) { diff --git a/src/com/hypixel/hytale/server/core/command/commands/utility/ConvertPrefabsCommand.java b/src/com/hypixel/hytale/server/core/command/commands/utility/ConvertPrefabsCommand.java index 32693d02..2c93c756 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/utility/ConvertPrefabsCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/utility/ConvertPrefabsCommand.java @@ -1,5 +1,6 @@ package com.hypixel.hytale.server.core.command.commands.utility; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.command.system.CommandContext; @@ -84,10 +85,15 @@ public class ConvertPrefabsCommand extends AbstractAsyncCommand { String storeOption = this.storeArg.get(context); if (this.pathArg.provided(context)) { Path assetPath = Paths.get(this.pathArg.get(context)); - return this.convertPath(assetPath, blocks, filler, relative, entities, destructive, failed, skipped).thenApply(_v -> { - this.sendCompletionMessages(context, assetPath, failed, skipped); - return null; - }); + if (!PathUtil.isInTrustedRoot(assetPath)) { + context.sendMessage(Message.translation("server.commands.convertprefabs.invalidPath")); + return CompletableFuture.completedFuture(null); + } else { + return this.convertPath(assetPath, blocks, filler, relative, entities, destructive, failed, skipped).thenApply(_v -> { + this.sendCompletionMessages(context, assetPath, failed, skipped); + return null; + }); + } } else { return switch (storeOption) { case "server" -> { diff --git a/src/com/hypixel/hytale/server/core/command/commands/utility/ValidateCPBCommand.java b/src/com/hypixel/hytale/server/core/command/commands/utility/ValidateCPBCommand.java index ca7656a0..85c09d4e 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/utility/ValidateCPBCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/utility/ValidateCPBCommand.java @@ -35,8 +35,13 @@ public class ValidateCPBCommand extends AbstractAsyncCommand { @Override protected CompletableFuture executeAsync(@Nonnull CommandContext context) { if (this.pathArg.provided(context)) { - String path = this.pathArg.get(context); - return CompletableFuture.runAsync(() -> convertPrefabs(context, PathUtil.get(path))); + Path assetPath = Path.of(this.pathArg.get(context)); + if (!PathUtil.isInTrustedRoot(assetPath)) { + context.sendMessage(Message.translation("server.commands.validatecpb.invalidPath")); + return CompletableFuture.completedFuture(null); + } else { + return CompletableFuture.runAsync(() -> convertPrefabs(context, assetPath)); + } } else { return CompletableFuture.runAsync(() -> { for (AssetPack pack : AssetModule.get().getAssetPacks()) { diff --git a/src/com/hypixel/hytale/server/core/command/commands/utility/lighting/LightingSendToggleCommand.java b/src/com/hypixel/hytale/server/core/command/commands/utility/lighting/LightingSendToggleCommand.java index c667c5eb..e4aac3d7 100644 --- a/src/com/hypixel/hytale/server/core/command/commands/utility/lighting/LightingSendToggleCommand.java +++ b/src/com/hypixel/hytale/server/core/command/commands/utility/lighting/LightingSendToggleCommand.java @@ -8,7 +8,6 @@ import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; import com.hypixel.hytale.server.core.command.system.basecommands.AbstractWorldCommand; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; -import com.hypixel.hytale.server.core.util.message.MessageFormat; import java.util.Objects; import java.util.function.BooleanSupplier; import java.util.function.Consumer; @@ -44,6 +43,6 @@ abstract class LightingSendToggleCommand extends AbstractWorldCommand { Boolean enabled = this.enabledArg.provided(context) ? this.enabledArg.get(context) : null; Boolean newValue = Objects.requireNonNullElseGet(enabled, () -> !this.getter.getAsBoolean()); this.setter.accept(newValue); - context.sendMessage(Message.translation(this.statusTranslationKey).param("status", MessageFormat.enabled(newValue))); + context.sendMessage(Message.translation(this.statusTranslationKey).param("enabled", newValue.toString())); } } diff --git a/src/com/hypixel/hytale/server/core/command/system/arguments/types/ArgTypes.java b/src/com/hypixel/hytale/server/core/command/system/arguments/types/ArgTypes.java index 31ad56e5..3f447fcf 100644 --- a/src/com/hypixel/hytale/server/core/command/system/arguments/types/ArgTypes.java +++ b/src/com/hypixel/hytale/server/core/command/system/arguments/types/ArgTypes.java @@ -654,6 +654,19 @@ public final class ArgTypes { } } }; + public static final ArgumentType> LAYER_ENTRY_TYPE = new MultiArgumentType>( + "Layer Entry Type", "A thickness for a corresponding block pattern", "1 Rock_Stone", "3 50%Rock_Basalt;50%Rock_Stone" + ) { + private final WrappedArgumentType thickness = this.withParameter("thickness", "How thick the layer should be", ArgTypes.INTEGER); + private final WrappedArgumentType blockPattern = this.withParameter( + "blockPattern", "The block pattern to use for the layer. If using with percentages, separate values with a ';'", ArgTypes.STRING + ); + + @Nonnull + public Pair parse(@Nonnull MultiArgumentContext context, ParseResult parseResult) { + return Pair.of(context.get(this.thickness), context.get(this.blockPattern)); + } + }; public static final ArgumentType> WEIGHTED_BLOCK_TYPE = new MultiArgumentType>( "Weighted Block Type", "A weight corresponding to a blocktype", "5 Empty", "20 Rock_Stone", "2 Rock_Shale" ) { diff --git a/src/com/hypixel/hytale/server/core/console/ConsoleModule.java b/src/com/hypixel/hytale/server/core/console/ConsoleModule.java index b127708f..06e008ce 100644 --- a/src/com/hypixel/hytale/server/core/console/ConsoleModule.java +++ b/src/com/hypixel/hytale/server/core/console/ConsoleModule.java @@ -22,9 +22,10 @@ import org.jline.terminal.Terminal; import org.jline.terminal.TerminalBuilder; public class ConsoleModule extends JavaPlugin { + private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); public static final PluginManifest MANIFEST = PluginManifest.corePlugin(ConsoleModule.class).build(); private static ConsoleModule instance; - private Terminal terminal; + private static Terminal terminal; private ConsoleModule.ConsoleRunnable consoleRunnable; public static ConsoleModule get() { @@ -35,11 +36,7 @@ public class ConsoleModule extends JavaPlugin { super(init); } - @Override - protected void setup() { - instance = this; - this.getCommandRegistry().registerCommand(new SayCommand()); - + public static void initializeTerminal() { try { TerminalBuilder builder = TerminalBuilder.builder(); if (Constants.SINGLEPLAYER) { @@ -48,22 +45,28 @@ public class ConsoleModule extends JavaPlugin { builder.color(true); } - this.terminal = builder.build(); - HytaleConsole.INSTANCE.setTerminal(this.terminal.getType()); - LineReader lineReader = LineReaderBuilder.builder().terminal(this.terminal).build(); - this.consoleRunnable = new ConsoleModule.ConsoleRunnable(lineReader, ConsoleSender.INSTANCE); - this.getLogger().at(Level.INFO).log("Setup console with type: %s", this.terminal.getType()); - } catch (IOException var3) { - this.getLogger().at(Level.SEVERE).withCause(var3).log("Failed to start console reader"); + terminal = builder.build(); + HytaleConsole.INSTANCE.setTerminal(terminal.getType()); + } catch (IOException var1) { + LOGGER.at(Level.SEVERE).withCause(var1).log("Failed to start console reader"); } } + @Override + protected void setup() { + instance = this; + this.getCommandRegistry().registerCommand(new SayCommand()); + LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).build(); + this.consoleRunnable = new ConsoleModule.ConsoleRunnable(lineReader, ConsoleSender.INSTANCE); + this.getLogger().at(Level.INFO).log("Setup console with type: %s", terminal.getType()); + } + @Override protected void shutdown() { this.getLogger().at(Level.INFO).log("Restoring terminal..."); try { - this.terminal.close(); + terminal.close(); } catch (IOException var2) { HytaleLogger.getLogger().at(Level.SEVERE).withCause(var2).log("Failed to restore terminal!"); } @@ -72,7 +75,7 @@ public class ConsoleModule extends JavaPlugin { } public Terminal getTerminal() { - return this.terminal; + return terminal; } private static class ConsoleRunnable implements Runnable { diff --git a/src/com/hypixel/hytale/server/core/entity/InteractionManager.java b/src/com/hypixel/hytale/server/core/entity/InteractionManager.java index 772856d2..30f764fc 100644 --- a/src/com/hypixel/hytale/server/core/entity/InteractionManager.java +++ b/src/com/hypixel/hytale/server/core/entity/InteractionManager.java @@ -417,7 +417,8 @@ public class InteractionManager implements Component { long threshold = this.getOperationTimeoutThreshold(); if (waitMillisx > threshold) { - LOGGER.at(Level.SEVERE).log("Client finished chain earlier than server! %d, %s", chain.getChainId(), chain); + LOGGER.at(Level.FINE).log("Client finished chain earlier than server! %d, %s", chain.getChainId(), chain); + this.cancelChains(chain); } } @@ -674,10 +675,12 @@ public class InteractionManager implements Component { long threshold = this.getOperationTimeoutThreshold(); if (waitMillis > threshold) { - HytaleLogger.Api ctx = LOGGER.at(Level.SEVERE); + HytaleLogger.Api ctx = LOGGER.at(Level.FINE); if (ctx.isEnabled()) { ctx.log("Client finished interaction earlier than server! %d, %s", entry.getIndex(), entry); } + + this.cancelChains(chain); } } } diff --git a/src/com/hypixel/hytale/server/core/entity/ItemUtils.java b/src/com/hypixel/hytale/server/core/entity/ItemUtils.java index bec7db1f..8966ab2f 100644 --- a/src/com/hypixel/hytale/server/core/entity/ItemUtils.java +++ b/src/com/hypixel/hytale/server/core/entity/ItemUtils.java @@ -8,26 +8,25 @@ import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.math.vector.Transform; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; -import com.hypixel.hytale.server.core.asset.type.item.config.Item; -import com.hypixel.hytale.server.core.asset.type.model.config.Model; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.event.events.ecs.DropItemEvent; import com.hypixel.hytale.server.core.event.events.ecs.InteractivelyPickupItemEvent; import com.hypixel.hytale.server.core.inventory.ItemStack; -import com.hypixel.hytale.server.core.inventory.container.ItemContainer; import com.hypixel.hytale.server.core.inventory.container.SimpleItemContainer; import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction; import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent; -import com.hypixel.hytale.server.core.modules.entity.player.PlayerSettings; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.util.logging.Level; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ItemUtils { + @Nonnull + public static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + public static void interactivelyPickupItem( @Nonnull Ref ref, @Nonnull ItemStack itemStack, @Nullable Vector3d origin, @Nonnull ComponentAccessor componentAccessor ) { @@ -39,19 +38,8 @@ public class ItemUtils { } else { Player playerComponent = componentAccessor.getComponent(ref, Player.getComponentType()); if (playerComponent != null) { - TransformComponent transformComponent = componentAccessor.getComponent(ref, TransformComponent.getComponentType()); - - assert transformComponent != null; - - PlayerSettings playerSettingsComponent = componentAccessor.getComponent(ref, PlayerSettings.getComponentType()); - if (playerSettingsComponent == null) { - playerSettingsComponent = PlayerSettings.defaults(); - } - Holder pickupItemHolder = null; - Item item = itemStack.getItem(); - ItemContainer itemContainer = playerComponent.getInventory().getContainerForItemPickup(item, playerSettingsComponent); - ItemStackTransaction transaction = itemContainer.addItemStack(itemStack); + ItemStackTransaction transaction = playerComponent.giveItem(itemStack, ref, componentAccessor); ItemStack remainder = transaction.getRemainder(); if (remainder != null && !remainder.isEmpty()) { int quantity = itemStack.getQuantity() - remainder.getQuantity(); @@ -93,14 +81,11 @@ public class ItemUtils { itemStack = event.getItemStack(); if (!itemStack.isEmpty() && itemStack.isValid()) { HeadRotation headRotationComponent = componentAccessor.getComponent(ref, HeadRotation.getComponentType()); - - assert headRotationComponent != null; - - Vector3f rotation = headRotationComponent.getRotation(); + Vector3f rotation = headRotationComponent != null ? headRotationComponent.getRotation() : new Vector3f(0.0F, 0.0F, 0.0F); Vector3d direction = Transform.getDirection(rotation.getPitch(), rotation.getYaw()); return throwItem(ref, componentAccessor, itemStack, direction, throwSpeed); } else { - HytaleLogger.getLogger().at(Level.WARNING).log("Attempted to throw invalid item %s at %s by %s", itemStack, throwSpeed, ref.getIndex()); + LOGGER.at(Level.WARNING).log("Attempted to throw invalid item %s at %s by %s", itemStack, throwSpeed, ref.getIndex()); return null; } } @@ -114,35 +99,43 @@ public class ItemUtils { @Nonnull Vector3d throwDirection, float throwSpeed ) { - TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); - - assert transformComponent != null; - - ModelComponent modelComponent = store.getComponent(ref, ModelComponent.getComponentType()); - - assert modelComponent != null; - - Vector3d throwPosition = transformComponent.getPosition().clone(); - Model model = modelComponent.getModel(); - throwPosition.add(0.0, model.getEyeHeight(ref, store), 0.0).add(throwDirection); - Holder itemEntityHolder = ItemComponent.generateItemDrop( - store, - itemStack, - throwPosition, - Vector3f.ZERO, - (float)throwDirection.x * throwSpeed, - (float)throwDirection.y * throwSpeed, - (float)throwDirection.z * throwSpeed - ); - if (itemEntityHolder == null) { + if (!ref.isValid()) { + LOGGER.at(Level.WARNING).log("Attempted to throw item %s by invalid entity %s", itemStack, Integer.valueOf(ref.getIndex())); return null; } else { - ItemComponent itemComponent = itemEntityHolder.getComponent(ItemComponent.getComponentType()); - if (itemComponent != null) { - itemComponent.setPickupDelay(1.5F); - } + TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); + if (transformComponent == null) { + LOGGER.at(Level.WARNING).log("Attempted to throw item %s by entity %s without a TransformComponent", itemStack, Integer.valueOf(ref.getIndex())); + return null; + } else { + float eyeHeight = 0.0F; + ModelComponent modelComponent = store.getComponent(ref, ModelComponent.getComponentType()); + if (modelComponent != null) { + eyeHeight = modelComponent.getModel().getEyeHeight(ref, store); + } - return store.addEntity(itemEntityHolder, AddReason.SPAWN); + Vector3d throwPosition = transformComponent.getPosition().clone(); + throwPosition.add(0.0, eyeHeight, 0.0).add(throwDirection); + Holder itemEntityHolder = ItemComponent.generateItemDrop( + store, + itemStack, + throwPosition, + Vector3f.ZERO, + (float)throwDirection.x * throwSpeed, + (float)throwDirection.y * throwSpeed, + (float)throwDirection.z * throwSpeed + ); + if (itemEntityHolder == null) { + return null; + } else { + ItemComponent itemComponent = itemEntityHolder.getComponent(ItemComponent.getComponentType()); + if (itemComponent != null) { + itemComponent.setPickupDelay(1.5F); + } + + return store.addEntity(itemEntityHolder, AddReason.SPAWN); + } + } } } diff --git a/src/com/hypixel/hytale/server/core/entity/effect/ActiveEntityEffect.java b/src/com/hypixel/hytale/server/core/entity/effect/ActiveEntityEffect.java index e76bdfcf..897d183a 100644 --- a/src/com/hypixel/hytale/server/core/entity/effect/ActiveEntityEffect.java +++ b/src/com/hypixel/hytale/server/core/entity/effect/ActiveEntityEffect.java @@ -243,16 +243,19 @@ public class ActiveEntityEffect implements Damage.Source { @Override public Message getDeathMessage(@Nonnull Damage info, @Nonnull Ref targetRef, @Nonnull ComponentAccessor componentAccessor) { EntityEffect entityEffect = EntityEffect.getAssetMap().getAsset(this.entityEffectIndex); - Message damageCauseMessage; - if (entityEffect != null) { - String locale = entityEffect.getLocale(); - String reason = locale != null ? locale : entityEffect.getId().toLowerCase(Locale.ROOT); - damageCauseMessage = Message.translation("server.general.damageCauses." + reason); + if (entityEffect == null) { + return Message.translation("server.general.killedBy").param("damageSource", MESSAGE_GENERAL_DAMAGE_CAUSES_UNKNOWN); } else { - damageCauseMessage = MESSAGE_GENERAL_DAMAGE_CAUSES_UNKNOWN; + String deathMessageKey = entityEffect.getDeathMessageKey(); + if (deathMessageKey != null) { + return Message.translation(deathMessageKey); + } else { + String locale = entityEffect.getLocale(); + String reason = locale != null ? locale : entityEffect.getId().toLowerCase(Locale.ROOT); + Message damageCauseMessage = Message.translation("server.general.damageCauses." + reason); + return Message.translation("server.general.killedBy").param("damageSource", damageCauseMessage); + } } - - return Message.translation("server.general.killedBy").param("damageSource", damageCauseMessage); } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/entity/entities/Player.java b/src/com/hypixel/hytale/server/core/entity/entities/Player.java index 5a53419e..434fb8be 100644 --- a/src/com/hypixel/hytale/server/core/entity/entities/Player.java +++ b/src/com/hypixel/hytale/server/core/entity/entities/Player.java @@ -51,6 +51,7 @@ import com.hypixel.hytale.server.core.inventory.Inventory; import com.hypixel.hytale.server.core.inventory.ItemStack; import com.hypixel.hytale.server.core.inventory.container.ItemContainer; import com.hypixel.hytale.server.core.inventory.transaction.ItemStackSlotTransaction; +import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction; import com.hypixel.hytale.server.core.io.PacketHandler; import com.hypixel.hytale.server.core.modules.collision.CollisionModule; import com.hypixel.hytale.server.core.modules.collision.CollisionResult; @@ -897,6 +898,16 @@ public class Player extends LivingEntity implements CommandSender, PermissionHol } } + @Nonnull + public ItemStackTransaction giveItem(@Nonnull ItemStack stack, @Nonnull Ref ref, @Nonnull ComponentAccessor componentAccessor) { + PlayerSettings playerSettings = componentAccessor.getComponent(ref, PlayerSettings.getComponentType()); + if (playerSettings == null) { + playerSettings = PlayerSettings.defaults(); + } + + return this.getInventory().getContainerForItemPickup(stack.getItem(), playerSettings).addItemStack(stack); + } + @Override public int hashCode() { int result = super.hashCode(); diff --git a/src/com/hypixel/hytale/server/core/entity/entities/ProjectileComponent.java b/src/com/hypixel/hytale/server/core/entity/entities/ProjectileComponent.java index 4829d90d..ff953e27 100644 --- a/src/com/hypixel/hytale/server/core/entity/entities/ProjectileComponent.java +++ b/src/com/hypixel/hytale/server/core/entity/entities/ProjectileComponent.java @@ -306,8 +306,6 @@ public class ProjectileComponent implements Component { if (depthShot != 0.0) { PhysicsMath.vectorFromAngles(yaw, pitchAdjust ? pitch : 0.0F, offset); offset.setLength(depthShot); - } else { - offset.assign(0.0, 0.0, 0.0); } offset.add(horizontalCenterShot * -PhysicsMath.headingZ(yaw), -verticalCenterShot, horizontalCenterShot * PhysicsMath.headingX(yaw)); diff --git a/src/com/hypixel/hytale/server/core/event/events/player/DrainPlayerFromWorldEvent.java b/src/com/hypixel/hytale/server/core/event/events/player/DrainPlayerFromWorldEvent.java index f2c47c93..5b0f2a39 100644 --- a/src/com/hypixel/hytale/server/core/event/events/player/DrainPlayerFromWorldEvent.java +++ b/src/com/hypixel/hytale/server/core/event/events/player/DrainPlayerFromWorldEvent.java @@ -6,35 +6,42 @@ import com.hypixel.hytale.math.vector.Transform; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class DrainPlayerFromWorldEvent implements IEvent { + @Nonnull private final Holder holder; + @Nonnull private World world; + @Nullable private Transform transform; - public DrainPlayerFromWorldEvent(Holder holder, World world, Transform transform) { + public DrainPlayerFromWorldEvent(@Nonnull Holder holder, @Nonnull World world, @Nullable Transform transform) { this.holder = holder; this.world = world; this.transform = transform; } + @Nonnull public Holder getHolder() { return this.holder; } + @Nonnull public World getWorld() { return this.world; } - public void setWorld(World world) { + public void setWorld(@Nonnull World world) { this.world = world; } + @Nullable public Transform getTransform() { return this.transform; } - public void setTransform(Transform transform) { + public void setTransform(@Nullable Transform transform) { this.transform = transform; } diff --git a/src/com/hypixel/hytale/server/core/inventory/Inventory.java b/src/com/hypixel/hytale/server/core/inventory/Inventory.java index 2b7c5f9e..d53f9a22 100644 --- a/src/com/hypixel/hytale/server/core/inventory/Inventory.java +++ b/src/com/hypixel/hytale/server/core/inventory/Inventory.java @@ -111,9 +111,11 @@ public class Inventory implements NetworkSerializable { @Deprecated private ItemContainer tools = EmptyItemContainer.INSTANCE; private ItemContainer backpack = EmptyItemContainer.INSTANCE; + private CombinedItemContainer combinedHotbarStorageBackpack; private CombinedItemContainer combinedHotbarFirst; private CombinedItemContainer combinedStorageFirst; private CombinedItemContainer combinedBackpackStorageHotbar; + private CombinedItemContainer combinedBackpackHotbarStorage; private CombinedItemContainer combinedStorageHotbarBackpack; private CombinedItemContainer combinedArmorHotbarStorage; private CombinedItemContainer combinedArmorHotbarUtilityStorage; @@ -391,89 +393,110 @@ public class Inventory implements NetworkSerializable { } } - public void smartMoveItem(int fromSectionId, int fromSlotId, int quantity, @Nonnull SmartMoveType moveType) { + public void smartMoveItem(int fromSectionId, int fromSlotId, int quantity, @Nonnull SmartMoveType moveType, PlayerSettings settings) { ItemContainer targetContainer = this.getSectionById(fromSectionId); if (targetContainer != null) { - switch (moveType) { - case EquipOrMergeStack: - if (this.tryEquipArmorPart(fromSectionId, (short)fromSlotId, quantity, targetContainer, true)) { - return; - } - - if (this.entity instanceof Player) { - for (Window window : ((Player)this.entity).getWindowManager().getWindows()) { - if (window instanceof ItemContainerWindow) { - ((ItemContainerWindow)window).getItemContainer().combineItemStacksIntoSlot(targetContainer, (short)fromSlotId); - } + ItemStack itemStack = targetContainer.getItemStack((short)fromSlotId); + if (!ItemStack.isEmpty(itemStack)) { + switch (moveType) { + case EquipOrMergeStack: + if (this.tryEquipArmorPart(itemStack, fromSectionId, (short)fromSlotId, quantity, targetContainer, true)) { + return; } - } - this.combinedHotbarFirst.combineItemStacksIntoSlot(targetContainer, (short)fromSlotId); - break; - case PutInHotbarOrWindow: - if (fromSectionId >= 0) { - targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.combinedHotbarFirst); - return; - } - - if (this.entity instanceof Player) { - for (Window windowx : ((Player)this.entity).getWindowManager().getWindows()) { - if (windowx instanceof ItemContainerWindow) { - ItemContainer itemContainer = ((ItemContainerWindow)windowx).getItemContainer(); - MoveTransaction transaction = targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, itemContainer); - ItemStack remainder = transaction.getAddTransaction().getRemainder(); - if (ItemStack.isEmpty(remainder) || remainder.getQuantity() != quantity) { - return; + if (this.entity instanceof Player) { + for (Window window : ((Player)this.entity).getWindowManager().getWindows()) { + if (window instanceof ItemContainerWindow) { + ((ItemContainerWindow)window).getItemContainer().combineItemStacksIntoSlot(targetContainer, (short)fromSlotId); } } } - } - if (this.tryEquipArmorPart(fromSectionId, (short)fromSlotId, quantity, targetContainer, false)) { - return; - } + this.combinedEverything.combineItemStacksIntoSlot(targetContainer, (short)fromSlotId); + break; + case PutInHotbarOrWindow: + if (fromSectionId >= 0) { + this.moveItemFromCheckToInventory(itemStack, targetContainer, (short)fromSlotId, quantity, settings); + return; + } - switch (fromSectionId) { - case -2: - targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.hotbar); + if (this.entity instanceof Player) { + for (Window windowx : ((Player)this.entity).getWindowManager().getWindows()) { + if (windowx instanceof ItemContainerWindow) { + ItemContainer itemContainer = ((ItemContainerWindow)windowx).getItemContainer(); + MoveTransaction transaction = targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, itemContainer); + ItemStack remainder = transaction.getAddTransaction().getRemainder(); + if (ItemStack.isEmpty(remainder) || remainder.getQuantity() != quantity) { + return; + } + } + } + } + + if (this.tryEquipArmorPart(itemStack, fromSectionId, (short)fromSlotId, quantity, targetContainer, false)) { return; - case -1: - targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.storage); - return; - default: - targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.combinedHotbarFirst); - return; - } - case PutInHotbarOrBackpack: - if (fromSectionId == -9) { - targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.combinedHotbarFirst); - } else { - targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.combinedBackpackStorageHotbar); - } + } + + switch (fromSectionId) { + case -2: + targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.hotbar); + return; + case -1: + targetContainer.moveItemStackFromSlot((short)fromSlotId, quantity, this.storage); + return; + default: + this.moveItemFromCheckToInventory(itemStack, targetContainer, (short)fromSlotId, quantity, settings); + return; + } + case PutInHotbarOrBackpack: + if (fromSectionId == -9) { + this.moveItemFromCheckToInventory(itemStack, targetContainer, (short)fromSlotId, quantity, settings); + } else { + targetContainer.moveItemStackFromSlot( + (short)fromSlotId, quantity, this.getContainerForItemPickup(itemStack.getItem(), settings, PickupLocation.Backpack) + ); + } + } } } } - private boolean tryEquipArmorPart(int fromSectionId, short fromSlotId, int quantity, ItemContainer targetContainer, boolean forceEquip) { - ItemStack itemStack = targetContainer.getItemStack(fromSlotId); - if (ItemStack.isEmpty(itemStack)) { + private boolean tryEquipArmorPart( + @Nonnull ItemStack itemStack, int fromSectionId, short fromSlotId, int quantity, ItemContainer targetContainer, boolean forceEquip + ) { + Item item = itemStack.getItem(); + ItemArmor itemArmor = item.getArmor(); + if (itemArmor == null || fromSectionId == -3 || !forceEquip && this.armor.getItemStack((short)itemArmor.getArmorSlot().ordinal()) != null) { return false; } else { - Item item = itemStack.getItem(); - ItemArmor itemArmor = item.getArmor(); - if (itemArmor == null || fromSectionId == -3 || !forceEquip && this.armor.getItemStack((short)itemArmor.getArmorSlot().ordinal()) != null) { - return false; - } else { - targetContainer.moveItemStackFromSlotToSlot(fromSlotId, quantity, this.armor, (short)itemArmor.getArmorSlot().ordinal()); - return true; - } + targetContainer.moveItemStackFromSlotToSlot(fromSlotId, quantity, this.armor, (short)itemArmor.getArmorSlot().ordinal()); + return true; } } + private MoveTransaction moveItemFromCheckToInventory( + @Nonnull ItemStack itemStack, @Nonnull ItemContainer targetContainer, short fromSlotId, int quantity, PlayerSettings settings + ) { + return targetContainer.moveItemStackFromSlot(fromSlotId, quantity, this.getContainerForItemPickup(itemStack.getItem(), settings)); + } + @Nullable - public ListTransaction> takeAll(int inventorySectionId) { - ItemContainer sectionById = this.getSectionById(inventorySectionId); - return sectionById != null ? sectionById.moveAllItemStacksTo(this.combinedHotbarFirst) : null; + public ListTransaction> takeAll(int inventorySectionId, PlayerSettings settings) { + ItemContainer container = this.getSectionById(inventorySectionId); + return container == null ? null : this.takeAllWithPriority(container, settings); + } + + public ListTransaction> takeAllWithPriority(ItemContainer fromContainer, PlayerSettings settings) { + List> transactions = new ObjectArrayList<>(); + + for (int slot = 0; slot < fromContainer.getCapacity(); slot++) { + ItemStack stack = fromContainer.getItemStack((short)slot); + if (!ItemStack.isEmpty(stack)) { + transactions.add(this.moveItemFromCheckToInventory(stack, fromContainer, (short)slot, stack.getQuantity(), settings)); + } + } + + return new ListTransaction<>(true, transactions); } @Nullable @@ -558,10 +581,6 @@ public class Inventory implements NetworkSerializable { return this.combinedBackpackStorageHotbar; } - public CombinedItemContainer getCombinedArmorHotbarStorage() { - return this.combinedArmorHotbarStorage; - } - public CombinedItemContainer getCombinedArmorHotbarUtilityStorage() { return this.combinedArmorHotbarUtilityStorage; } @@ -574,31 +593,39 @@ public class Inventory implements NetworkSerializable { return this.combinedEverything; } + private ItemContainer getItemContainerForPickupLocation(@Nonnull PickupLocation pickupLocation) { + return switch (pickupLocation) { + case Hotbar -> this.combinedHotbarStorageBackpack; + case Storage -> this.combinedStorageHotbarBackpack; + case Backpack -> this.combinedBackpackStorageHotbar; + default -> this.combinedHotbarStorageBackpack; + }; + } + @Nonnull public ItemContainer getContainerForItemPickup(@Nonnull Item item, PlayerSettings playerSettings) { - if (item.getArmor() != null) { - return playerSettings.armorItemsPreferredPickupLocation() == PickupLocation.Hotbar ? this.getCombinedHotbarFirst() : this.getCombinedStorageFirst(); + return this.getContainerForItemPickup(item, playerSettings, null); + } + + @Nonnull + public ItemContainer getContainerForItemPickup(@Nonnull Item item, PlayerSettings playerSettings, @Nullable PickupLocation overridePickupLocation) { + if (overridePickupLocation != null) { + return this.getItemContainerForPickupLocation(overridePickupLocation); + } else if (item.getArmor() != null) { + return this.getItemContainerForPickupLocation(playerSettings.armorItemsPreferredPickupLocation()); } else if (item.getWeapon() != null || item.getTool() != null) { - return playerSettings.weaponAndToolItemsPreferredPickupLocation() == PickupLocation.Hotbar - ? this.getCombinedHotbarFirst() - : this.getCombinedStorageFirst(); + return this.getItemContainerForPickupLocation(playerSettings.weaponAndToolItemsPreferredPickupLocation()); } else if (item.getUtility().isUsable()) { - return playerSettings.usableItemsItemsPreferredPickupLocation() == PickupLocation.Hotbar - ? this.getCombinedHotbarFirst() - : this.getCombinedStorageFirst(); + return this.getItemContainerForPickupLocation(playerSettings.usableItemsItemsPreferredPickupLocation()); } else { BlockType blockType = item.hasBlockType() ? BlockType.getAssetMap().getAsset(item.getBlockId()) : BlockType.EMPTY; if (blockType == null) { blockType = BlockType.EMPTY; } - if (blockType.getMaterial() == BlockMaterial.Solid) { - return playerSettings.solidBlockItemsPreferredPickupLocation() == PickupLocation.Hotbar - ? this.getCombinedHotbarFirst() - : this.getCombinedStorageFirst(); - } else { - return playerSettings.miscItemsPreferredPickupLocation() == PickupLocation.Hotbar ? this.getCombinedHotbarFirst() : this.getCombinedStorageFirst(); - } + return blockType.getMaterial() == BlockMaterial.Solid + ? this.getItemContainerForPickupLocation(playerSettings.solidBlockItemsPreferredPickupLocation()) + : this.getItemContainerForPickupLocation(playerSettings.miscItemsPreferredPickupLocation()); } } @@ -797,7 +824,9 @@ public class Inventory implements NetworkSerializable { this.combinedHotbarFirst = new CombinedItemContainer(this.hotbar, this.storage); this.combinedStorageFirst = new CombinedItemContainer(this.storage, this.hotbar); this.combinedBackpackStorageHotbar = new CombinedItemContainer(this.backpack, this.storage, this.hotbar); + this.combinedBackpackHotbarStorage = new CombinedItemContainer(this.backpack, this.hotbar, this.storage); this.combinedStorageHotbarBackpack = new CombinedItemContainer(this.storage, this.hotbar, this.backpack); + this.combinedHotbarStorageBackpack = new CombinedItemContainer(this.hotbar, this.storage, this.backpack); this.combinedArmorHotbarStorage = new CombinedItemContainer(this.armor, this.hotbar, this.storage); this.combinedArmorHotbarUtilityStorage = new CombinedItemContainer(this.armor, this.hotbar, this.utility, this.storage); this.combinedHotbarUtilityConsumableStorage = new CombinedItemContainer(this.hotbar, this.utility, this.storage); diff --git a/src/com/hypixel/hytale/server/core/io/handlers/InitialPacketHandler.java b/src/com/hypixel/hytale/server/core/io/handlers/InitialPacketHandler.java index fca09f7c..94b1c492 100644 --- a/src/com/hypixel/hytale/server/core/io/handlers/InitialPacketHandler.java +++ b/src/com/hypixel/hytale/server/core/io/handlers/InitialPacketHandler.java @@ -75,9 +75,9 @@ public class InitialPacketHandler extends PacketHandler { this.receivedConnect = true; this.clearTimeout(); PacketHandler.logConnectionTimings(this.channel, "Connect", Level.FINE); - if (packet.protocolCrc != 701662755) { + if (packet.protocolCrc != 672031543) { int clientBuild = packet.protocolBuildNumber; - int serverBuild = 5; + int serverBuild = 12; int errorCode; if (clientBuild < serverBuild) { errorCode = 5; diff --git a/src/com/hypixel/hytale/server/core/io/handlers/game/GamePacketHandler.java b/src/com/hypixel/hytale/server/core/io/handlers/game/GamePacketHandler.java index c8eb4f7f..a4823354 100644 --- a/src/com/hypixel/hytale/server/core/io/handlers/game/GamePacketHandler.java +++ b/src/com/hypixel/hytale/server/core/io/handlers/game/GamePacketHandler.java @@ -13,6 +13,7 @@ import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.protocol.BlockRotation; import com.hypixel.hytale.protocol.GameMode; import com.hypixel.hytale.protocol.HostAddress; +import com.hypixel.hytale.protocol.Packet; import com.hypixel.hytale.protocol.io.netty.ProtocolUtil; import com.hypixel.hytale.protocol.packets.camera.RequestFlyCameraMode; import com.hypixel.hytale.protocol.packets.camera.SetFlyCameraMode; @@ -53,7 +54,6 @@ import com.hypixel.hytale.server.core.Constants; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.HytaleServerConfig; import com.hypixel.hytale.server.core.Message; -import com.hypixel.hytale.server.core.NameMatching; import com.hypixel.hytale.server.core.asset.common.CommonAssetModule; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.model.config.Model; @@ -109,7 +109,6 @@ import java.net.InetSocketAddress; import java.util.Collections; import java.util.Deque; import java.util.List; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedDeque; @@ -172,31 +171,46 @@ public class GamePacketHandler extends GenericPacketHandler implements IPacketHa this.registerHandler(211, p -> this.handle((ChatMessage)p)); this.registerHandler(23, p -> this.handle((RequestAssets)p)); this.registerHandler(219, p -> this.handle((CustomPageEvent)p)); - this.registerHandler(32, p -> this.handle((ViewRadius)p)); - this.registerHandler(232, p -> this.handle((UpdateLanguage)p)); - this.registerHandler(111, p -> this.handle((MouseInteraction)p)); + this.registerWorldHandler(32, this::handleViewRadius); + this.registerWorldHandler(232, this::handleUpdateLanguage); + this.registerWorldHandler(111, this::handleMouseInteraction); this.registerHandler(251, p -> this.handle((UpdateServerAccess)p)); this.registerHandler(252, p -> this.handle((SetServerAccess)p)); - this.registerHandler(204, p -> this.handle((ClientOpenWindow)p)); - this.registerHandler(203, p -> this.handle((SendWindowAction)p)); - this.registerHandler(202, p -> this.handle((CloseWindow)p)); + this.registerWorldHandler(204, this::handleClientOpenWindow); + this.registerWorldHandler(203, this::handleSendWindowAction); + this.registerWorldHandler(202, this::handleCloseWindow); this.registerHandler(260, p -> this.handle((RequestMachinimaActorModel)p)); - this.registerHandler(262, p -> this.handle((UpdateMachinimaScene)p)); + this.registerWorldHandler(262, this::handleUpdateMachinimaScene); this.registerHandler(105, p -> this.handle((ClientReady)p)); - this.registerHandler(166, p -> this.handle((MountMovement)p)); - this.registerHandler(116, p -> this.handle((SyncPlayerPreferences)p)); - this.registerHandler(117, p -> this.handle((ClientPlaceBlock)p)); - this.registerHandler(119, p -> this.handle((RemoveMapMarker)p)); - this.registerHandler(243, p -> this.handle((UpdateWorldMapVisible)p)); - this.registerHandler(244, p -> this.handle((TeleportToWorldMapMarker)p)); - this.registerHandler(245, p -> this.handle((TeleportToWorldMapPosition)p)); - this.registerHandler(246, p -> this.handle((CreateUserMarker)p)); + this.registerWorldHandler(166, this::handleMountMovement); + this.registerWorldHandler(116, this::handleSyncPlayerPreferences); + this.registerWorldHandler(117, this::handleClientPlaceBlock); + this.registerWorldHandler(119, this::handleRemoveMapMarker); + this.registerWorldHandler(243, this::handleUpdateWorldMapVisible); + this.registerWorldHandler(244, this::handleTeleportToWorldMapMarker); + this.registerWorldHandler(245, this::handleTeleportToWorldMapPosition); + this.registerWorldHandler(246, this::handleCreateUserMarker); this.registerHandler(290, p -> this.handle((SyncInteractionChains)p)); - this.registerHandler(158, p -> this.handle((SetPaused)p)); - this.registerHandler(282, p -> this.handle((RequestFlyCameraMode)p)); + this.registerWorldHandler(158, this::handleSetPaused); + this.registerWorldHandler(282, this::handleRequestFlyCameraMode); this.packetHandlers.forEach(SubPacketHandler::registerHandlers); } + private void registerWorldHandler(int packetId, @Nonnull GamePacketHandler.WorldPacketHandler handler) { + this.registerHandler(packetId, packet -> { + Ref ref = this.playerRef.getReference(); + if (ref != null) { + Store store = ref.getStore(); + World world = store.getExternalData().getWorld(); + world.execute(() -> { + if (ref.isValid()) { + handler.consumer((T)packet, ref, world, store); + } + }); + } + }); + } + @Override public void closed(ChannelHandlerContext ctx) { super.closed(ctx); @@ -238,19 +252,12 @@ public class GamePacketHandler extends GenericPacketHandler implements IPacketHa ProtocolUtil.closeApplicationConnection(this.channel); } - public void handle(@Nonnull MouseInteraction packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleMouseInteraction(@Nonnull MouseInteraction packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - InteractionModule.get().doMouseInteraction(ref, store, packet, playerComponent, this.playerRef); - }); - } + InteractionModule.get().doMouseInteraction(ref, store, packet, playerComponent, this.playerRef); } public void handle(@Nonnull ClientMovement packet) { @@ -420,206 +427,152 @@ public class GamePacketHandler extends GenericPacketHandler implements IPacketHa } } - public void handle(@Nonnull ViewRadius packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleViewRadius(@Nonnull ViewRadius packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - EntityTrackerSystems.EntityViewer entityViewerComponent = store.getComponent(ref, EntityTrackerSystems.EntityViewer.getComponentType()); + EntityTrackerSystems.EntityViewer entityViewerComponent = store.getComponent(ref, EntityTrackerSystems.EntityViewer.getComponentType()); - assert entityViewerComponent != null; + assert entityViewerComponent != null; - int viewRadiusChunks = MathUtil.ceil(packet.value / 32.0F); - playerComponent.setClientViewRadius(viewRadiusChunks); - entityViewerComponent.viewRadiusBlocks = playerComponent.getViewRadius() * 32; - }); - } + int viewRadiusChunks = MathUtil.ceil(packet.value / 32.0F); + playerComponent.setClientViewRadius(viewRadiusChunks); + entityViewerComponent.viewRadiusBlocks = playerComponent.getViewRadius() * 32; } - public void handle(@Nonnull UpdateLanguage packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - this.playerRef.setLanguage(packet.language); - I18nModule.get().sendTranslations(this, packet.language); - } + public void handleUpdateLanguage(@Nonnull UpdateLanguage packet, Ref ref, World world, Store store) { + this.playerRef.setLanguage(packet.language); + I18nModule.get().sendTranslations(this, packet.language); } - protected void handle(@Nonnull ClientOpenWindow packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Supplier supplier = Window.CLIENT_REQUESTABLE_WINDOW_TYPES.get(packet.type); - if (supplier == null) { - throw new RuntimeException("Unable to process ClientOpenWindow packet. Window type is not supported!"); - } else { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + protected void handleClientOpenWindow(@Nonnull ClientOpenWindow packet, Ref ref, World world, Store store) { + Supplier supplier = Window.CLIENT_REQUESTABLE_WINDOW_TYPES.get(packet.type); + if (supplier == null) { + throw new RuntimeException("Unable to process ClientOpenWindow packet. Window type is not supported!"); + } else { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - UpdateWindow updateWindowPacket = playerComponent.getWindowManager().clientOpenWindow(ref, supplier.get(), store); - if (updateWindowPacket != null) { - this.writeNoCache(updateWindowPacket); - } - }); + UpdateWindow updateWindowPacket = playerComponent.getWindowManager().clientOpenWindow(ref, supplier.get(), store); + if (updateWindowPacket != null) { + this.writeNoCache(updateWindowPacket); } } } - public void handle(@Nonnull SendWindowAction packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleSendWindowAction(@Nonnull SendWindowAction packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - Window window = playerComponent.getWindowManager().getWindow(packet.id); - if (window != null) { - if (window instanceof ValidatedWindow validatedWindow && !validatedWindow.validate(ref, store)) { - window.close(ref, store); - } else { - window.handleAction(this.playerRef.getReference(), store, packet.action); + Window window = playerComponent.getWindowManager().getWindow(packet.id); + if (window != null) { + if (window instanceof ValidatedWindow validatedWindow && !validatedWindow.validate(ref, store)) { + window.close(ref, store); + } else { + window.handleAction(ref, store, packet.action); + } + } + } + + public void handleSyncPlayerPreferences(@Nonnull SyncPlayerPreferences packet, Ref ref, World world, Store store) { + ComponentType componentType = EntityModule.get().getPlayerSettingsComponentType(); + store.putComponent( + ref, + componentType, + new PlayerSettings( + packet.showEntityMarkers, + packet.armorItemsPreferredPickupLocation, + packet.weaponAndToolItemsPreferredPickupLocation, + packet.usableItemsItemsPreferredPickupLocation, + packet.solidBlockItemsPreferredPickupLocation, + packet.miscItemsPreferredPickupLocation, + new PlayerCreativeSettings(packet.allowNPCDetection, packet.respondToHit), + packet.hideHelmet, + packet.hideCuirass, + packet.hideGauntlets, + packet.hidePants + ) + ); + store.getComponent(ref, Player.getComponentType()).invalidateEquipmentNetwork(); + } + + public void handleClientPlaceBlock(@Nonnull ClientPlaceBlock packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); + + assert playerComponent != null; + + Inventory inventory = playerComponent.getInventory(); + Vector3i targetBlock = new Vector3i(packet.position.x, packet.position.y, packet.position.z); + BlockRotation blockRotation = new BlockRotation(packet.rotation.rotationYaw, packet.rotation.rotationPitch, packet.rotation.rotationRoll); + TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); + Store chunkStore = world.getChunkStore().getStore(); + long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z); + Ref chunkReference = chunkStore.getExternalData().getChunkReference(chunkIndex); + if (chunkReference != null) { + BlockChunk blockChunk = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType()); + if (blockChunk != null) { + BlockSection section = blockChunk.getSectionAtBlockY(targetBlock.y); + if (section != null) { + if (transformComponent != null && playerComponent.getGameMode() != GameMode.Creative) { + Vector3d position = transformComponent.getPosition(); + Vector3d blockCenter = new Vector3d(targetBlock.x + 0.5, targetBlock.y + 0.5, targetBlock.z + 0.5); + if (position.distanceSquaredTo(blockCenter) > 49.0) { + section.invalidateBlock(targetBlock.x, targetBlock.y, targetBlock.z); + return; + } } - } - }); - } - } - public void handle(@Nonnull SyncPlayerPreferences packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute( - () -> { - ComponentType componentType = EntityModule.get().getPlayerSettingsComponentType(); - store.putComponent( - ref, - componentType, - new PlayerSettings( - packet.showEntityMarkers, - packet.armorItemsPreferredPickupLocation, - packet.weaponAndToolItemsPreferredPickupLocation, - packet.usableItemsItemsPreferredPickupLocation, - packet.solidBlockItemsPreferredPickupLocation, - packet.miscItemsPreferredPickupLocation, - new PlayerCreativeSettings(packet.allowNPCDetection, packet.respondToHit), - packet.hideHelmet, - packet.hideCuirass, - packet.hideGauntlets, - packet.hidePants - ) - ); - store.getComponent(ref, Player.getComponentType()).invalidateEquipmentNetwork(); - } - ); - } - } - - public void handle(@Nonnull ClientPlaceBlock packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute( - () -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); - - assert playerComponent != null; - - Inventory inventory = playerComponent.getInventory(); - Vector3i targetBlock = new Vector3i(packet.position.x, packet.position.y, packet.position.z); - BlockRotation blockRotation = new BlockRotation(packet.rotation.rotationYaw, packet.rotation.rotationPitch, packet.rotation.rotationRoll); - TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType()); - Store chunkStore = world.getChunkStore().getStore(); - long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z); - Ref chunkReference = chunkStore.getExternalData().getChunkReference(chunkIndex); - if (chunkReference != null) { - BlockChunk blockChunk = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType()); - if (blockChunk != null) { - BlockSection section = blockChunk.getSectionAtBlockY(targetBlock.y); - if (section != null) { - if (transformComponent != null && playerComponent.getGameMode() != GameMode.Creative) { - Vector3d position = transformComponent.getPosition(); - Vector3d blockCenter = new Vector3d(targetBlock.x + 0.5, targetBlock.y + 0.5, targetBlock.z + 0.5); - if (position.distanceSquaredTo(blockCenter) > 49.0) { - section.invalidateBlock(targetBlock.x, targetBlock.y, targetBlock.z); - return; - } - } - - ItemStack itemInHand = playerComponent.getInventory().getItemInHand(); - if (itemInHand == null) { - section.invalidateBlock(targetBlock.x, targetBlock.y, targetBlock.z); - } else { - String heldBlockKey = itemInHand.getBlockKey(); - if (heldBlockKey == null) { - section.invalidateBlock(targetBlock.x, targetBlock.y, targetBlock.z); - } else { - if (packet.placedBlockId != -1) { - String clientPlacedBlockTypeKey = BlockType.getAssetMap().getAsset(packet.placedBlockId).getId(); - BlockType heldBlockType = BlockType.getAssetMap().getAsset(heldBlockKey); - if (heldBlockType != null && BlockPlaceUtils.canPlaceBlock(heldBlockType, clientPlacedBlockTypeKey)) { - heldBlockKey = clientPlacedBlockTypeKey; - } - } - - BlockPlaceUtils.placeBlock( - ref, - itemInHand, - heldBlockKey, - inventory.getHotbar(), - Vector3i.ZERO, - targetBlock, - blockRotation, - inventory, - inventory.getActiveHotbarSlot(), - playerComponent.getGameMode() != GameMode.Creative, - chunkReference, - chunkStore, - store - ); - } + ItemStack itemInHand = playerComponent.getInventory().getItemInHand(); + if (itemInHand == null) { + section.invalidateBlock(targetBlock.x, targetBlock.y, targetBlock.z); + } else { + String heldBlockKey = itemInHand.getBlockKey(); + if (heldBlockKey == null) { + section.invalidateBlock(targetBlock.x, targetBlock.y, targetBlock.z); + } else { + if (packet.placedBlockId != -1) { + String clientPlacedBlockTypeKey = BlockType.getAssetMap().getAsset(packet.placedBlockId).getId(); + BlockType heldBlockType = BlockType.getAssetMap().getAsset(heldBlockKey); + if (heldBlockType != null && BlockPlaceUtils.canPlaceBlock(heldBlockType, clientPlacedBlockTypeKey)) { + heldBlockKey = clientPlacedBlockTypeKey; } } + + BlockPlaceUtils.placeBlock( + ref, + itemInHand, + heldBlockKey, + inventory.getHotbar(), + Vector3i.ZERO, + targetBlock, + blockRotation, + inventory, + inventory.getActiveHotbarSlot(), + playerComponent.getGameMode() != GameMode.Creative, + chunkReference, + chunkStore, + store + ); } } } - ); + } } } - public void handle(@Nonnull RemoveMapMarker packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> world.getWorldMapManager().handleUserRemoveMarker(this.playerRef, packet)); - } + public void handleRemoveMapMarker(@Nonnull RemoveMapMarker packet, Ref ref, World world, Store store) { + world.getWorldMapManager().handleUserRemoveMarker(this.playerRef, packet); } - public void handle(@Nonnull CloseWindow packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleCloseWindow(@Nonnull CloseWindow packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - playerComponent.getWindowManager().closeWindow(ref, packet.id, store); - }); - } + playerComponent.getWindowManager().closeWindow(ref, packet.id, store); } public void handle(@Nonnull UpdateServerAccess packet) { @@ -661,36 +614,7 @@ public class GamePacketHandler extends GenericPacketHandler implements IPacketHa this.writeNoCache(new SetMachinimaActorModel(Model.createUnitScaleModel(modelAsset).toPacket(), packet.sceneName, packet.actorName)); } - public void handle(@Nonnull UpdateMachinimaScene packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute( - () -> { - UpdateMachinimaScene updatePacket = new UpdateMachinimaScene( - this.playerRef.getUsername(), packet.sceneName, packet.frame, packet.updateType, packet.scene - ); - if ("*".equals(packet.player)) { - for (PlayerRef otherPlayerRef : world.getPlayerRefs()) { - if (!Objects.equals(otherPlayerRef, this.playerRef)) { - otherPlayerRef.getPacketHandler().writeNoCache(updatePacket); - } - } - - this.playerRef.sendMessage(Message.translation("server.io.gamepackethandler.sceneUpdateSent")); - } else { - PlayerRef target = NameMatching.DEFAULT.find(Universe.get().getPlayers(), packet.player, PlayerRef::getUsername); - if (target != null && target.getReference().getStore().getExternalData().getWorld() == world) { - target.getPacketHandler().write(updatePacket); - this.playerRef.sendMessage(Message.translation("server.io.gamepackethander.sceneUpdateSentToPlayer").param("name", target.getUsername())); - } else { - this.playerRef.sendMessage(Message.translation("server.io.gamepackethandler.playerNotFound").param("name", packet.player)); - } - } - } - ); - } + public void handleUpdateMachinimaScene(@Nonnull UpdateMachinimaScene packet, Ref ref, World world, Store store) { } public void handle(@Nonnull ClientReady packet) { @@ -720,160 +644,115 @@ public class GamePacketHandler extends GenericPacketHandler implements IPacketHa } } - public void handle(@Nonnull UpdateWorldMapVisible packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleUpdateWorldMapVisible(@Nonnull UpdateWorldMapVisible packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - playerComponent.getWorldMapTracker().setClientHasWorldMapVisible(packet.visible); - }); - } + playerComponent.getWorldMapTracker().setClientHasWorldMapVisible(packet.visible); } - public void handle(@Nonnull TeleportToWorldMapMarker packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleTeleportToWorldMapMarker(@Nonnull TeleportToWorldMapMarker packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - WorldMapTracker worldMapTracker = playerComponent.getWorldMapTracker(); - if (!worldMapTracker.isAllowTeleportToMarkers()) { - this.disconnect("You are not allowed to use TeleportToWorldMapMarker!"); - } else { - MapMarker marker = worldMapTracker.getSentMarkers().get(packet.id); - if (marker != null) { - Transform transform = PositionUtil.toTransform(marker.transform); - if (MapMarkerUtils.isUserMarker(marker)) { - int blockX = (int)transform.getPosition().getX(); - int blockZ = (int)transform.getPosition().getZ(); - WorldChunk chunk = world.getChunk(ChunkUtil.indexChunkFromBlock(blockX, blockZ)); - int height = chunk == null ? 319 : chunk.getHeight(blockX, blockZ); - transform.getPosition().setY(height); - } - - Teleport teleportComponent = Teleport.createForPlayer(transform); - world.getEntityStore().getStore().addComponent(this.playerRef.getReference(), Teleport.getComponentType(), teleportComponent); - } + WorldMapTracker worldMapTracker = playerComponent.getWorldMapTracker(); + if (!worldMapTracker.isAllowTeleportToMarkers()) { + this.disconnect("You are not allowed to use TeleportToWorldMapMarker!"); + } else { + MapMarker marker = worldMapTracker.getSentMarkers().get(packet.id); + if (marker != null) { + Transform transform = PositionUtil.toTransform(marker.transform); + if (MapMarkerUtils.isUserMarker(marker)) { + int blockX = (int)transform.getPosition().getX(); + int blockZ = (int)transform.getPosition().getZ(); + WorldChunk chunk = world.getChunk(ChunkUtil.indexChunkFromBlock(blockX, blockZ)); + int height = chunk == null ? 319 : chunk.getHeight(blockX, blockZ); + transform.getPosition().setY(height); } - }); + + Teleport teleportComponent = Teleport.createForPlayer(transform); + world.getEntityStore().getStore().addComponent(this.playerRef.getReference(), Teleport.getComponentType(), teleportComponent); + } } } - public void handle(@Nonnull TeleportToWorldMapPosition packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleTeleportToWorldMapPosition(@Nonnull TeleportToWorldMapPosition packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - WorldMapTracker worldMapTracker = playerComponent.getWorldMapTracker(); - if (!worldMapTracker.isAllowTeleportToCoordinates()) { - this.disconnect("You are not allowed to use TeleportToWorldMapMarker!"); - } else { - world.getChunkStore().getChunkReferenceAsync(ChunkUtil.indexChunkFromBlock(packet.x, packet.y)).thenAcceptAsync(chunkRef -> { - BlockChunk blockChunkComponent = world.getChunkStore().getStore().getComponent((Ref)chunkRef, BlockChunk.getComponentType()); + WorldMapTracker worldMapTracker = playerComponent.getWorldMapTracker(); + if (!worldMapTracker.isAllowTeleportToCoordinates()) { + this.disconnect("You are not allowed to use TeleportToWorldMapMarker!"); + } else { + world.getChunkStore().getChunkReferenceAsync(ChunkUtil.indexChunkFromBlock(packet.x, packet.y)).thenAcceptAsync(chunkRef -> { + BlockChunk blockChunkComponent = world.getChunkStore().getStore().getComponent((Ref)chunkRef, BlockChunk.getComponentType()); - assert blockChunkComponent != null; + assert blockChunkComponent != null; - Vector3d position = new Vector3d(packet.x, blockChunkComponent.getHeight(packet.x, packet.y) + 2, packet.y); - Teleport teleportComponent = Teleport.createForPlayer(null, position, new Vector3f(0.0F, 0.0F, 0.0F)); - world.getEntityStore().getStore().addComponent(this.playerRef.getReference(), Teleport.getComponentType(), teleportComponent); - }, world); - } - }); + Vector3d position = new Vector3d(packet.x, blockChunkComponent.getHeight(packet.x, packet.y) + 2, packet.y); + Teleport teleportComponent = Teleport.createForPlayer(null, position, new Vector3f(0.0F, 0.0F, 0.0F)); + world.getEntityStore().getStore().addComponent(this.playerRef.getReference(), Teleport.getComponentType(), teleportComponent); + }, world); } } - public void handle(@Nonnull CreateUserMarker packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - WorldMapManager worldMapManager = world.getWorldMapManager(); - worldMapManager.handleUserCreateMarker(this.playerRef, packet); - }); - } + public void handleCreateUserMarker(@Nonnull CreateUserMarker packet, Ref ref, World world, Store store) { + WorldMapManager worldMapManager = world.getWorldMapManager(); + worldMapManager.handleUserCreateMarker(this.playerRef, packet); } public void handle(@Nonnull SyncInteractionChains packet) { Collections.addAll(this.interactionPacketQueue, packet.updates); } - public void handle(@Nonnull MountMovement packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleMountMovement(@Nonnull MountMovement packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - Ref entityReference = world.getEntityStore().getRefFromNetworkId(playerComponent.getMountEntityId()); - if (entityReference != null && entityReference.isValid()) { - TransformComponent transformComponent = store.getComponent(entityReference, TransformComponent.getComponentType()); + Ref entityReference = world.getEntityStore().getRefFromNetworkId(playerComponent.getMountEntityId()); + if (entityReference != null && entityReference.isValid()) { + TransformComponent transformComponent = store.getComponent(entityReference, TransformComponent.getComponentType()); - assert transformComponent != null; + assert transformComponent != null; - transformComponent.setPosition(PositionUtil.toVector3d(packet.absolutePosition)); - transformComponent.setRotation(PositionUtil.toRotation(packet.bodyOrientation)); - MovementStatesComponent movementStatesComponent = store.getComponent(entityReference, MovementStatesComponent.getComponentType()); + transformComponent.setPosition(PositionUtil.toVector3d(packet.absolutePosition)); + transformComponent.setRotation(PositionUtil.toRotation(packet.bodyOrientation)); + MovementStatesComponent movementStatesComponent = store.getComponent(entityReference, MovementStatesComponent.getComponentType()); - assert movementStatesComponent != null; + assert movementStatesComponent != null; - movementStatesComponent.setMovementStates(packet.movementStates); - } - }); + movementStatesComponent.setMovementStates(packet.movementStates); } } - public void handle(@Nonnull SetPaused packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - if (world.getPlayerCount() == 1 && Constants.SINGLEPLAYER) { - world.setPaused(packet.paused); - } - }); + public void handleSetPaused(@Nonnull SetPaused packet, Ref ref, World world, Store store) { + if (world.getPlayerCount() == 1 && Constants.SINGLEPLAYER) { + world.setPaused(packet.paused); } } - public void handle(@Nonnull RequestFlyCameraMode packet) { - Ref ref = this.playerRef.getReference(); - if (ref != null && ref.isValid()) { - Store store = ref.getStore(); - World world = store.getExternalData().getWorld(); - world.execute(() -> { - Player playerComponent = store.getComponent(ref, Player.getComponentType()); + public void handleRequestFlyCameraMode(@Nonnull RequestFlyCameraMode packet, Ref ref, World world, Store store) { + Player playerComponent = store.getComponent(ref, Player.getComponentType()); - assert playerComponent != null; + assert playerComponent != null; - if (playerComponent.hasPermission("hytale.camera.flycam")) { - this.writeNoCache(new SetFlyCameraMode(packet.entering)); - if (packet.entering) { - this.playerRef.sendMessage(Message.translation("server.general.flyCamera.enabled")); - } else { - this.playerRef.sendMessage(Message.translation("server.general.flyCamera.disabled")); - } - } else { - this.playerRef.sendMessage(Message.translation("server.general.flyCamera.noPermission")); - } - }); + if (playerComponent.hasPermission("hytale.camera.flycam")) { + this.writeNoCache(new SetFlyCameraMode(packet.entering)); + if (packet.entering) { + this.playerRef.sendMessage(Message.translation("server.general.flyCamera.enabled")); + } else { + this.playerRef.sendMessage(Message.translation("server.general.flyCamera.disabled")); + } + } else { + this.playerRef.sendMessage(Message.translation("server.general.flyCamera.noPermission")); } } + + private interface WorldPacketHandler { + void consumer(T var1, Ref var2, World var3, Store var4); + } } diff --git a/src/com/hypixel/hytale/server/core/io/handlers/game/InventoryPacketHandler.java b/src/com/hypixel/hytale/server/core/io/handlers/game/InventoryPacketHandler.java index 40a60d1d..c3c0a7ce 100644 --- a/src/com/hypixel/hytale/server/core/io/handlers/game/InventoryPacketHandler.java +++ b/src/com/hypixel/hytale/server/core/io/handlers/game/InventoryPacketHandler.java @@ -39,6 +39,7 @@ import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction import com.hypixel.hytale.server.core.io.PacketHandler; import com.hypixel.hytale.server.core.io.handlers.IPacketHandler; import com.hypixel.hytale.server.core.io.handlers.SubPacketHandler; +import com.hypixel.hytale.server.core.modules.entity.player.PlayerSettings; import com.hypixel.hytale.server.core.modules.item.ItemModule; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.SoundUtil; @@ -255,32 +256,34 @@ public class InventoryPacketHandler implements SubPacketHandler { } else { Inventory inventory = playerComponent.getInventory(); ItemStack itemStack = ItemStack.fromPacket(packet.item); - switch (packet.moveType) { - case EquipOrMergeStack: - Item item = itemStack.getItem(); - ItemArmor itemArmor = item.getArmor(); - if (itemArmor != null) { - inventory.getArmor().setItemStackForSlot((short)itemArmor.getArmorSlot().ordinal(), itemStack); - return; - } - - int quantity = itemStack.getQuantity(); - if (item.getUtility().isUsable()) { - ItemStackTransaction transaction = inventory.getUtility().addItemStack(itemStack); - ItemStack remainder = transaction.getRemainder(); - if (ItemStack.isEmpty(remainder) || remainder.getQuantity() != quantity) { - for (ItemStackSlotTransaction slotTransaction : transaction.getSlotTransactions()) { - if (slotTransaction.succeeded()) { - inventory.setActiveUtilitySlot((byte)slotTransaction.getSlot()); - } - } + if (itemStack != null) { + switch (packet.moveType) { + case EquipOrMergeStack: + Item item = itemStack.getItem(); + ItemArmor itemArmor = item.getArmor(); + if (itemArmor != null) { + inventory.getArmor().setItemStackForSlot((short)itemArmor.getArmorSlot().ordinal(), itemStack); + return; } - return; - } - break; - case PutInHotbarOrWindow: - inventory.getCombinedHotbarFirst().addItemStack(itemStack); + int quantity = itemStack.getQuantity(); + if (item.getUtility().isUsable()) { + ItemStackTransaction transaction = inventory.getUtility().addItemStack(itemStack); + ItemStack remainder = transaction.getRemainder(); + if (ItemStack.isEmpty(remainder) || remainder.getQuantity() != quantity) { + for (ItemStackSlotTransaction slotTransaction : transaction.getSlotTransactions()) { + if (slotTransaction.succeeded()) { + inventory.setActiveUtilitySlot((byte)slotTransaction.getSlot()); + } + } + } + + return; + } + break; + case PutInHotbarOrWindow: + playerComponent.giveItem(itemStack, ref, store); + } } } } @@ -375,7 +378,12 @@ public class InventoryPacketHandler implements SubPacketHandler { assert playerComponent != null; Inventory inventory = playerComponent.getInventory(); - inventory.smartMoveItem(packet.fromSectionId, packet.fromSlotId, packet.quantity, packet.moveType); + PlayerSettings settings = store.getComponent(ref, PlayerSettings.getComponentType()); + if (settings == null) { + settings = PlayerSettings.defaults(); + } + + inventory.smartMoveItem(packet.fromSectionId, packet.fromSlotId, packet.quantity, packet.moveType, settings); }); } } @@ -436,10 +444,15 @@ public class InventoryPacketHandler implements SubPacketHandler { assert playerComponent != null; Inventory inventory = playerComponent.getInventory(); + PlayerSettings settings = store.getComponent(ref, PlayerSettings.getComponentType()); + if (settings == null) { + settings = PlayerSettings.defaults(); + } + switch (packet.inventoryActionType) { case TakeAll: if (packet.inventorySectionId == -9) { - inventory.takeAll(packet.inventorySectionId); + inventory.takeAll(packet.inventorySectionId, settings); return; } @@ -449,10 +462,10 @@ public class InventoryPacketHandler implements SubPacketHandler { if (itemContainerWindow.getItemContainer() instanceof CombinedItemContainer combinedItemContainer && combinedItemContainer.getContainersSize() >= 3) { ItemContainer outputContainer = combinedItemContainer.getContainer(2); - outputContainer.moveAllItemStacksTo(inventory.getCombinedHotbarFirst()); + inventory.takeAllWithPriority(outputContainer, settings); } } else { - inventory.takeAll(packet.inventorySectionId); + inventory.takeAll(packet.inventorySectionId, settings); } } break; diff --git a/src/com/hypixel/hytale/server/core/modules/accesscontrol/commands/WhitelistStatusCommand.java b/src/com/hypixel/hytale/server/core/modules/accesscontrol/commands/WhitelistStatusCommand.java index 2080f1b9..68fb4a5e 100644 --- a/src/com/hypixel/hytale/server/core/modules/accesscontrol/commands/WhitelistStatusCommand.java +++ b/src/com/hypixel/hytale/server/core/modules/accesscontrol/commands/WhitelistStatusCommand.java @@ -4,7 +4,6 @@ import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.command.system.CommandContext; import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase; import com.hypixel.hytale.server.core.modules.accesscontrol.provider.HytaleWhitelistProvider; -import com.hypixel.hytale.server.core.util.message.MessageFormat; import javax.annotation.Nonnull; public class WhitelistStatusCommand extends CommandBase { @@ -18,6 +17,6 @@ public class WhitelistStatusCommand extends CommandBase { @Override protected void executeSync(@Nonnull CommandContext context) { - context.sendMessage(Message.translation("server.modules.whitelist.status").param("status", MessageFormat.enabled(this.whitelistProvider.isEnabled()))); + context.sendMessage(Message.translation("server.modules.whitelist.status").param("enabled", this.whitelistProvider.isEnabled() ? "true" : "false")); } } diff --git a/src/com/hypixel/hytale/server/core/modules/debug/DebugUtils.java b/src/com/hypixel/hytale/server/core/modules/debug/DebugUtils.java index 7a30ca60..71aca04e 100644 --- a/src/com/hypixel/hytale/server/core/modules/debug/DebugUtils.java +++ b/src/com/hypixel/hytale/server/core/modules/debug/DebugUtils.java @@ -16,10 +16,52 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class DebugUtils { + public static final Vector3f COLOR_BLACK = new Vector3f(0.0F, 0.0F, 0.0F); + public static final Vector3f COLOR_WHITE = new Vector3f(1.0F, 1.0F, 1.0F); + public static final Vector3f COLOR_RED = new Vector3f(1.0F, 0.0F, 0.0F); + public static final Vector3f COLOR_LIME = new Vector3f(0.0F, 1.0F, 0.0F); + public static final Vector3f COLOR_BLUE = new Vector3f(0.0F, 0.0F, 1.0F); + public static final Vector3f COLOR_YELLOW = new Vector3f(1.0F, 1.0F, 0.0F); + public static final Vector3f COLOR_CYAN = new Vector3f(0.0F, 1.0F, 1.0F); + public static final Vector3f COLOR_MAGENTA = new Vector3f(1.0F, 0.0F, 1.0F); + public static final Vector3f COLOR_SILVER = new Vector3f(0.75F, 0.75F, 0.75F); + public static final Vector3f COLOR_GRAY = new Vector3f(0.5F, 0.5F, 0.5F); + public static final Vector3f COLOR_MAROON = new Vector3f(0.5F, 0.0F, 0.0F); + public static final Vector3f COLOR_OLIVE = new Vector3f(0.5F, 0.5F, 0.0F); + public static final Vector3f COLOR_GREEN = new Vector3f(0.0F, 0.5F, 0.0F); + public static final Vector3f COLOR_PURPLE = new Vector3f(0.5F, 0.0F, 0.5F); + public static final Vector3f COLOR_TEAL = new Vector3f(0.0F, 0.5F, 0.5F); + public static final Vector3f COLOR_NAVY = new Vector3f(0.0F, 0.0F, 0.5F); + public static final Vector3f[] INDEXED_COLORS = new Vector3f[]{ + COLOR_RED, COLOR_BLUE, COLOR_LIME, COLOR_YELLOW, COLOR_CYAN, COLOR_MAGENTA, COLOR_PURPLE, COLOR_GREEN + }; + public static final String[] INDEXED_COLOR_NAMES = new String[]{"Red", "Blue", "Lime", "Yellow", "Cyan", "Magenta", "Purple", "Green"}; public static boolean DISPLAY_FORCES = false; + public static final float DEFAULT_OPACITY = 0.8F; public static void add(@Nonnull World world, @Nonnull DebugShape shape, @Nonnull Matrix4d matrix, @Nonnull Vector3f color, float time, boolean fade) { - DisplayDebug packet = new DisplayDebug(shape, matrix.asFloatData(), new com.hypixel.hytale.protocol.Vector3f(color.x, color.y, color.z), time, fade, null); + add(world, shape, matrix, color, 0.8F, time, fade, null); + } + + public static void add( + @Nonnull World world, @Nonnull DebugShape shape, @Nonnull Matrix4d matrix, @Nonnull Vector3f color, float opacity, float time, boolean fade + ) { + add(world, shape, matrix, color, opacity, time, fade, null); + } + + private static void add( + @Nonnull World world, + @Nonnull DebugShape shape, + @Nonnull Matrix4d matrix, + @Nonnull Vector3f color, + float opacity, + float time, + boolean fade, + @Nullable float[] shapeParams + ) { + DisplayDebug packet = new DisplayDebug( + shape, matrix.asFloatData(), new com.hypixel.hytale.protocol.Vector3f(color.x, color.y, color.z), time, fade, shapeParams, opacity + ); for (PlayerRef playerRef : world.getPlayerRefs()) { playerRef.getPacketHandler().write(packet); @@ -29,18 +71,7 @@ public class DebugUtils { public static void addFrustum( @Nonnull World world, @Nonnull Matrix4d matrix, @Nonnull Matrix4d frustumProjection, @Nonnull Vector3f color, float time, boolean fade ) { - DisplayDebug packet = new DisplayDebug( - DebugShape.Frustum, - matrix.asFloatData(), - new com.hypixel.hytale.protocol.Vector3f(color.x, color.y, color.z), - time, - fade, - frustumProjection.asFloatData() - ); - - for (PlayerRef playerRef : world.getPlayerRefs()) { - playerRef.getPacketHandler().write(packet); - } + add(world, DebugShape.Frustum, matrix, color, 0.8F, time, fade, frustumProjection.asFloatData()); } public static void clear(@Nonnull World world) { @@ -67,7 +98,14 @@ public class DebugUtils { } public static void addSphere(@Nonnull World world, @Nonnull Vector3d pos, @Nonnull Vector3f color, double scale, float time) { - Matrix4d matrix = makeMatrix(pos, scale); + addSphere(world, pos.x, pos.y, pos.z, color, scale, time); + } + + public static void addSphere(@Nonnull World world, double x, double y, double z, @Nonnull Vector3f color, double scale, float time) { + Matrix4d matrix = new Matrix4d(); + matrix.identity(); + matrix.translate(x, y, z); + matrix.scale(scale, scale, scale); add(world, DebugShape.Sphere, matrix, color, time, true); } @@ -77,7 +115,14 @@ public class DebugUtils { } public static void addCube(@Nonnull World world, @Nonnull Vector3d pos, @Nonnull Vector3f color, double scale, float time) { - Matrix4d matrix = makeMatrix(pos, scale); + addCube(world, pos.x, pos.y, pos.z, color, scale, time); + } + + public static void addCube(@Nonnull World world, double x, double y, double z, @Nonnull Vector3f color, double scale, float time) { + Matrix4d matrix = new Matrix4d(); + matrix.identity(); + matrix.translate(x, y, z); + matrix.scale(scale, scale, scale); add(world, DebugShape.Cube, matrix, color, time, true); } @@ -86,6 +131,160 @@ public class DebugUtils { add(world, DebugShape.Cylinder, matrix, color, time, true); } + public static void addLine( + @Nonnull World world, @Nonnull Vector3d start, @Nonnull Vector3d end, @Nonnull Vector3f color, double thickness, float time, boolean fade + ) { + addLine(world, start.x, start.y, start.z, end.x, end.y, end.z, color, thickness, time, fade); + } + + public static void addLine( + @Nonnull World world, + double startX, + double startY, + double startZ, + double endX, + double endY, + double endZ, + @Nonnull Vector3f color, + double thickness, + float time, + boolean fade + ) { + double dirX = endX - startX; + double dirY = endY - startY; + double dirZ = endZ - startZ; + double length = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); + if (!(length < 0.001)) { + Matrix4d tmp = new Matrix4d(); + Matrix4d matrix = new Matrix4d(); + matrix.identity(); + matrix.translate(startX, startY, startZ); + double angleY = Math.atan2(dirZ, dirX); + matrix.rotateAxis(angleY + (Math.PI / 2), 0.0, 1.0, 0.0, tmp); + double angleX = Math.atan2(Math.sqrt(dirX * dirX + dirZ * dirZ), dirY); + matrix.rotateAxis(angleX, 1.0, 0.0, 0.0, tmp); + matrix.translate(0.0, length / 2.0, 0.0); + matrix.scale(thickness, length, thickness); + add(world, DebugShape.Cylinder, matrix, color, time, fade); + } + } + + public static void addDisc(@Nonnull World world, @Nonnull Vector3d center, double radius, @Nonnull Vector3f color, float time, boolean fade) { + addDisc(world, center.x, center.y, center.z, radius, 0.0, color, 0.8F, time, fade); + } + + public static void addDisc(@Nonnull World world, double x, double y, double z, double radius, @Nonnull Vector3f color, float time, boolean fade) { + addDisc(world, x, y, z, radius, 0.0, color, 0.8F, time, fade); + } + + public static void addDisc( + @Nonnull World world, double x, double y, double z, double radius, @Nonnull Vector3f color, float opacity, float time, boolean fade + ) { + addDisc(world, x, y, z, radius, 0.0, color, opacity, 32, time, fade); + } + + public static void addDisc( + @Nonnull World world, + double x, + double y, + double z, + double outerRadius, + double innerRadius, + @Nonnull Vector3f color, + float opacity, + float time, + boolean fade + ) { + addDisc(world, x, y, z, outerRadius, innerRadius, color, opacity, 32, time, fade); + } + + public static void addDisc( + @Nonnull World world, + double x, + double y, + double z, + double outerRadius, + double innerRadius, + @Nonnull Vector3f color, + float opacity, + int segmentCount, + float time, + boolean fade + ) { + Matrix4d matrix = new Matrix4d(); + matrix.identity(); + matrix.translate(x, y, z); + float[] shapeParams = new float[]{ + (float)outerRadius, segmentCount, (float)innerRadius, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F + }; + add(world, DebugShape.Disc, matrix, color, opacity, time, fade, shapeParams); + } + + public static void addSector( + @Nonnull World world, double x, double y, double z, double heading, double radius, double angle, @Nonnull Vector3f color, float time, boolean fade + ) { + addSector(world, x, y, z, heading, radius, angle, 0.0, color, 0.8F, 16, time, fade); + } + + public static void addSector( + @Nonnull World world, + double x, + double y, + double z, + double heading, + double radius, + double angle, + @Nonnull Vector3f color, + float opacity, + float time, + boolean fade + ) { + addSector(world, x, y, z, heading, radius, angle, 0.0, color, opacity, 16, time, fade); + } + + public static void addSector( + @Nonnull World world, + double x, + double y, + double z, + double heading, + double outerRadius, + double angle, + double innerRadius, + @Nonnull Vector3f color, + float opacity, + float time, + boolean fade + ) { + addSector(world, x, y, z, heading, outerRadius, angle, innerRadius, color, opacity, 16, time, fade); + } + + public static void addSector( + @Nonnull World world, + double x, + double y, + double z, + double heading, + double outerRadius, + double angle, + double innerRadius, + @Nonnull Vector3f color, + float opacity, + int segmentCount, + float time, + boolean fade + ) { + Matrix4d tmp = new Matrix4d(); + Matrix4d matrix = new Matrix4d(); + matrix.identity(); + matrix.translate(x, y, z); + matrix.rotateAxis(heading, 0.0, 1.0, 0.0, tmp); + float[] shapeParams = new float[]{ + (float)outerRadius, (float)angle, (float)innerRadius, segmentCount, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F + }; + add(world, DebugShape.Sector, matrix, color, opacity, time, fade, shapeParams); + } + public static void addArrow(@Nonnull World world, @Nonnull Vector3d position, @Nonnull Vector3d direction, @Nonnull Vector3f color, float time, boolean fade) { Vector3d directionClone = direction.clone(); Matrix4d tmp = new Matrix4d(); diff --git a/src/com/hypixel/hytale/server/core/modules/entity/component/TransformComponent.java b/src/com/hypixel/hytale/server/core/modules/entity/component/TransformComponent.java index 3d7883d2..8b881dae 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/component/TransformComponent.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/component/TransformComponent.java @@ -42,7 +42,6 @@ public class TransformComponent implements Component { @Nullable private Ref chunkRef; - @Nonnull public static ComponentType getComponentType() { return EntityModule.get().getTransformComponentType(); } diff --git a/src/com/hypixel/hytale/server/core/modules/entity/damage/DamageModule.java b/src/com/hypixel/hytale/server/core/modules/entity/damage/DamageModule.java index 325bec08..faed3cb6 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/damage/DamageModule.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/damage/DamageModule.java @@ -97,6 +97,7 @@ public class DamageModule extends JavaPlugin { entityStoreRegistry.registerSystem(new RespawnSystems.ClearEntityEffectsRespawnSystem()); entityStoreRegistry.registerSystem(new RespawnSystems.ClearInteractionsRespawnSystem()); entityStoreRegistry.registerSystem(new RespawnSystems.CheckBrokenItemsRespawnSystem()); + entityStoreRegistry.registerSystem(new RespawnSystems.ClearRespawnUI()); entityStoreRegistry.registerSystem(new DamageCalculatorSystems.SequenceModifier()); this.getCommandRegistry().registerCommand(new DesyncDamageCommand()); } diff --git a/src/com/hypixel/hytale/server/core/modules/entity/damage/DeathComponent.java b/src/com/hypixel/hytale/server/core/modules/entity/damage/DeathComponent.java index 064a1944..0312b0ca 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/damage/DeathComponent.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/damage/DeathComponent.java @@ -18,6 +18,7 @@ import com.hypixel.hytale.server.core.asset.type.gameplay.DeathConfig; import com.hypixel.hytale.server.core.asset.type.gameplay.respawn.RespawnController; import com.hypixel.hytale.server.core.entity.InteractionChain; import com.hypixel.hytale.server.core.inventory.ItemStack; +import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import java.util.List; @@ -210,15 +211,17 @@ public class DeathComponent implements Component { return deathComponent.respawnFuture; } else { World world = componentAccessor.getExternalData().getWorld(); + PlayerRef playerRefComponent = componentAccessor.getComponent(ref, PlayerRef.getComponentType()); RespawnController respawnController = world.getDeathConfig().getRespawnController(); deathComponent.respawnFuture = respawnController.respawnPlayer(world, ref, componentAccessor).whenComplete((ignore, ex) -> { if (ex != null) { LOGGER.atSevere().withCause(ex).log("Failed to respawn entity"); } - Store store = world.getEntityStore().getStore(); - if (ref.isValid()) { - store.tryRemoveComponent(ref, getComponentType()); + Ref currentRef = playerRefComponent.getReference(); + if (currentRef != null && currentRef.isValid()) { + Store store = currentRef.getStore(); + store.tryRemoveComponent(currentRef, getComponentType()); } }); return deathComponent.respawnFuture; diff --git a/src/com/hypixel/hytale/server/core/modules/entity/damage/RespawnSystems.java b/src/com/hypixel/hytale/server/core/modules/entity/damage/RespawnSystems.java index c4372fb8..6d0614e4 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/damage/RespawnSystems.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/damage/RespawnSystems.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.RefChangeSystem; +import com.hypixel.hytale.protocol.packets.interface_.Page; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.entity.InteractionManager; import com.hypixel.hytale.server.core.entity.effect.EffectControllerComponent; @@ -16,6 +17,7 @@ import com.hypixel.hytale.server.core.modules.entitystats.EntityStatValue; import com.hypixel.hytale.server.core.modules.interaction.InteractionModule; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class RespawnSystems { public static class CheckBrokenItemsRespawnSystem extends RespawnSystems.OnRespawnSystem { @@ -70,6 +72,24 @@ public class RespawnSystems { } } + public static class ClearRespawnUI extends RespawnSystems.OnRespawnSystem { + public void onComponentRemoved( + @Nonnull Ref ref, @Nonnull DeathComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer + ) { + Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType()); + + assert playerComponent != null; + + playerComponent.getPageManager().setPage(ref, store, Page.None); + } + + @Nullable + @Override + public Query getQuery() { + return Player.getComponentType(); + } + } + public abstract static class OnRespawnSystem extends RefChangeSystem { @Nonnull @Override diff --git a/src/com/hypixel/hytale/server/core/modules/entity/item/ItemComponent.java b/src/com/hypixel/hytale/server/core/modules/entity/item/ItemComponent.java index 59734b8c..6c7e9b71 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/item/ItemComponent.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/item/ItemComponent.java @@ -25,7 +25,6 @@ import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction import com.hypixel.hytale.server.core.modules.entity.BlockMigrationExtraInfo; import com.hypixel.hytale.server.core.modules.entity.DespawnComponent; import com.hypixel.hytale.server.core.modules.entity.EntityModule; -import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; import com.hypixel.hytale.server.core.modules.entity.component.Intangible; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId; @@ -249,35 +248,40 @@ public class ItemComponent implements Component { } } - @Nonnull + @Nullable public static Holder generatePickedUpItem( @Nonnull Ref ref, @Nonnull ComponentAccessor componentAccessor, @Nonnull Ref targetRef, @Nonnull Vector3d targetPosition ) { - Holder holder = EntityStore.REGISTRY.newHolder(); - TransformComponent itemTransformComponent = componentAccessor.getComponent(ref, TransformComponent.getComponentType()); - - assert itemTransformComponent != null; - - ItemComponent itemItemComponent = componentAccessor.getComponent(ref, getComponentType()); - - assert itemItemComponent != null; - - HeadRotation itemHeadRotationComponent = componentAccessor.getComponent(ref, HeadRotation.getComponentType()); - - assert itemHeadRotationComponent != null; - - PickupItemComponent pickupItemComponent = new PickupItemComponent(targetRef, targetPosition.clone()); - holder.addComponent(PickupItemComponent.getComponentType(), pickupItemComponent); - holder.addComponent(getComponentType(), itemItemComponent.clone()); - holder.addComponent(TransformComponent.getComponentType(), itemTransformComponent.clone()); - holder.ensureComponent(PreventItemMerging.getComponentType()); - holder.ensureComponent(Intangible.getComponentType()); - holder.addComponent(NetworkId.getComponentType(), new NetworkId(ref.getStore().getExternalData().takeNextNetworkId())); - holder.ensureComponent(EntityStore.REGISTRY.getNonSerializedComponentType()); - return holder; + if (!ref.isValid()) { + LOGGER.at(Level.WARNING).log("Attempted to generate picked up item from invalid entity reference %s", Integer.valueOf(ref.getIndex())); + return null; + } else { + TransformComponent itemTransformComponent = componentAccessor.getComponent(ref, TransformComponent.getComponentType()); + if (itemTransformComponent == null) { + LOGGER.at(Level.WARNING).log("Attempted to generate picked up item from entity %s without a TransformComponent", Integer.valueOf(ref.getIndex())); + return null; + } else { + ItemComponent itemItemComponent = componentAccessor.getComponent(ref, getComponentType()); + if (itemItemComponent == null) { + LOGGER.at(Level.WARNING).log("Attempted to generate picked up item from entity %s without an ItemComponent", Integer.valueOf(ref.getIndex())); + return null; + } else { + Holder holder = EntityStore.REGISTRY.newHolder(); + PickupItemComponent pickupItemComponent = new PickupItemComponent(targetRef, targetPosition.clone()); + holder.addComponent(PickupItemComponent.getComponentType(), pickupItemComponent); + holder.addComponent(getComponentType(), itemItemComponent.clone()); + holder.addComponent(TransformComponent.getComponentType(), itemTransformComponent.clone()); + holder.ensureComponent(PreventItemMerging.getComponentType()); + holder.ensureComponent(Intangible.getComponentType()); + holder.addComponent(NetworkId.getComponentType(), new NetworkId(ref.getStore().getExternalData().takeNextNetworkId())); + holder.ensureComponent(EntityStore.REGISTRY.getNonSerializedComponentType()); + return holder; + } + } + } } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/modules/entity/player/PlayerItemEntityPickupSystem.java b/src/com/hypixel/hytale/server/core/modules/entity/player/PlayerItemEntityPickupSystem.java index b7b99a35..8bcda79c 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/player/PlayerItemEntityPickupSystem.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/player/PlayerItemEntityPickupSystem.java @@ -25,7 +25,6 @@ import com.hypixel.hytale.server.core.entity.InteractionContext; import com.hypixel.hytale.server.core.entity.InteractionManager; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.inventory.ItemStack; -import com.hypixel.hytale.server.core.inventory.container.ItemContainer; import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction; import com.hypixel.hytale.server.core.modules.entity.DespawnComponent; import com.hypixel.hytale.server.core.modules.entity.component.Interactable; @@ -162,20 +161,16 @@ public class PlayerItemEntityPickupSystem extends EntityTickingSystem pickupItemHolder = ItemComponent.generatePickedUpItem(itemRef, commandBuffer, targetPlayerRef, itemEntityPosition); - commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); + if (pickupItemHolder != null) { + commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); + } break; } @@ -186,7 +181,10 @@ public class PlayerItemEntityPickupSystem extends EntityTickingSystem pickupItemHolder = ItemComponent.generatePickedUpItem(itemRef, commandBuffer, targetPlayerRef, itemEntityPosition); - commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); + if (pickupItemHolder != null) { + commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN); + } + if (quantity > 0) { playerComponent.notifyPickupItem(targetPlayerRef, remainder.withQuantity(quantity), itemEntityPosition, commandBuffer); } diff --git a/src/com/hypixel/hytale/server/core/modules/entity/system/ModelSystems.java b/src/com/hypixel/hytale/server/core/modules/entity/system/ModelSystems.java index cb4cf944..d639b27a 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/system/ModelSystems.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/system/ModelSystems.java @@ -19,6 +19,7 @@ import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.HolderSystem; import com.hypixel.hytale.component.system.RefChangeSystem; import com.hypixel.hytale.component.system.tick.EntityTickingSystem; +import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.math.shape.Box; import com.hypixel.hytale.protocol.ComponentUpdate; import com.hypixel.hytale.protocol.ComponentUpdateType; @@ -50,9 +51,15 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ModelSystems { + @Nonnull + private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + public static class AnimationEntityTrackerUpdate extends EntityTickingSystem { + @Nonnull private final ComponentType visibleComponentType = EntityTrackerSystems.Visible.getComponentType(); + @Nonnull private final ComponentType activeAnimationComponentType = ActiveAnimationComponent.getComponentType(); + @Nonnull private final Query query = Query.and(this.visibleComponentType, this.activeAnimationComponentType); @Nullable @@ -112,8 +119,11 @@ public class ModelSystems { } public static class ApplyRandomSkin extends HolderSystem { + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final ComponentType randomSkinComponent = ApplyRandomSkinPersistedComponent.getComponentType(); + @Nonnull private final Query query = Query.and(this.randomSkinComponent, this.modelComponentType); @Override @@ -134,8 +144,11 @@ public class ModelSystems { } public static class AssignNetworkIdToProps extends HolderSystem { + @Nonnull private final ComponentType propComponentType = PropComponent.getComponentType(); + @Nonnull private final ComponentType networkIdComponentType = NetworkId.getComponentType(); + @Nonnull private final Query query = Query.and(this.propComponentType, Query.not(this.networkIdComponentType)); @Override @@ -155,6 +168,7 @@ public class ModelSystems { } public static class EnsurePropsPrefabCopyable extends HolderSystem { + @Nonnull private final ComponentType propComponentType = PropComponent.getComponentType(); @Override @@ -174,7 +188,9 @@ public class ModelSystems { } public static class ModelChange extends RefChangeSystem { + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final ComponentType persistentModelComponentType = PersistentModel.getComponentType(); @Override @@ -200,8 +216,11 @@ public class ModelSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - PersistentModel persistentModel = store.getComponent(ref, this.persistentModelComponentType); - persistentModel.setModelReference(newComponent.getModel().toReference()); + PersistentModel persistentModelComponent = store.getComponent(ref, this.persistentModelComponentType); + + assert persistentModelComponent != null; + + persistentModelComponent.setModelReference(newComponent.getModel().toReference()); } public void onComponentRemoved( @@ -212,23 +231,36 @@ public class ModelSystems { } public static class ModelSpawned extends HolderSystem { + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final ComponentType boundingBoxComponentType = BoundingBox.getComponentType(); + @Nonnull private final Set> dependencies = Set.of(new SystemDependency<>(Order.AFTER, ModelSystems.SetRenderedModel.class)); @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - Model model = holder.getComponent(this.modelComponentType).getModel(); - Box modelBoundingBox = model.getBoundingBox(); - if (modelBoundingBox != null) { - BoundingBox boundingBox = holder.getComponent(this.boundingBoxComponentType); - if (boundingBox == null) { - boundingBox = new BoundingBox(); - holder.addComponent(this.boundingBoxComponentType, boundingBox); - } + ModelComponent modelComponent = holder.getComponent(this.modelComponentType); - boundingBox.setBoundingBox(modelBoundingBox); - boundingBox.setDetailBoxes(model.getDetailBoxes()); + assert modelComponent != null; + + Model model = modelComponent.getModel(); + if (model == null) { + ModelSystems.LOGGER.atWarning().log("Failed to set bounding box for entity as model is null"); + } else { + Box modelBoundingBox = model.getBoundingBox(); + if (modelBoundingBox == null) { + ModelSystems.LOGGER.atWarning().log("Failed to set bounding box for entity as model bounding box is null: %s", model.getModel()); + } else { + BoundingBox boundingBox = holder.getComponent(this.boundingBoxComponentType); + if (boundingBox == null) { + boundingBox = new BoundingBox(); + holder.addComponent(this.boundingBoxComponentType, boundingBox); + } + + boundingBox.setBoundingBox(modelBoundingBox); + boundingBox.setDetailBoxes(model.getDetailBoxes()); + } } } @@ -249,16 +281,23 @@ public class ModelSystems { } public static class PlayerConnect extends HolderSystem { + @Nonnull private final ComponentType playerComponentType = Player.getComponentType(); + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final Query query = Query.and(this.playerComponentType, Query.not(this.modelComponentType)); + @Nonnull private final Set> dependencies = Set.of(new SystemDependency<>(Order.BEFORE, ModelSystems.ModelSpawned.class)); @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - Player player = holder.getComponent(this.playerComponentType); + Player playerComponent = holder.getComponent(this.playerComponentType); + + assert playerComponent != null; + DefaultAssetMap assetMap = ModelAsset.getAssetMap(); - String preset = player.getPlayerConfigData().getPreset(); + String preset = playerComponent.getPlayerConfigData().getPreset(); ModelAsset modelAsset = preset != null ? assetMap.getAsset(preset) : null; if (modelAsset != null) { Model model = Model.createUnitScaleModel(modelAsset); @@ -290,9 +329,13 @@ public class ModelSystems { } public static class PlayerUpdateMovementManager extends RefChangeSystem { + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final ComponentType playerComponentType = Player.getComponentType(); + @Nonnull private final Query query = Query.and(this.playerComponentType, MovementManager.getComponentType()); + @Nonnull private final Set> dependencies = Set.of(new SystemDependency<>(Order.AFTER, ModelSystems.UpdateBoundingBox.class)); @Nonnull @@ -316,7 +359,7 @@ public class ModelSystems { public void onComponentAdded( @Nonnull Ref ref, @Nonnull ModelComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - this.updateMovementController(ref, commandBuffer); + updateMovementController(ref, commandBuffer); } public void onComponentSet( @@ -326,16 +369,16 @@ public class ModelSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - this.updateMovementController(ref, commandBuffer); + updateMovementController(ref, commandBuffer); } public void onComponentRemoved( @Nonnull Ref ref, @Nonnull ModelComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - this.updateMovementController(ref, commandBuffer); + updateMovementController(ref, commandBuffer); } - private void updateMovementController(@Nonnull Ref ref, @Nonnull ComponentAccessor componentAccessor) { + private static void updateMovementController(@Nonnull Ref ref, @Nonnull ComponentAccessor componentAccessor) { MovementManager movementManagerComponent = componentAccessor.getComponent(ref, MovementManager.getComponentType()); assert movementManagerComponent != null; @@ -345,14 +388,26 @@ public class ModelSystems { } public static class SetRenderedModel extends HolderSystem { + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final ComponentType persistentModelComponentType = PersistentModel.getComponentType(); + @Nonnull private final Query query = Query.and(this.persistentModelComponentType, Query.not(this.modelComponentType)); @Override public void onEntityAdd(@Nonnull Holder holder, @Nonnull AddReason reason, @Nonnull Store store) { - PersistentModel persistentModel = holder.getComponent(this.persistentModelComponentType); - holder.putComponent(this.modelComponentType, new ModelComponent(persistentModel.getModelReference().toModel())); + PersistentModel persistentModelComponent = holder.getComponent(this.persistentModelComponentType); + + assert persistentModelComponent != null; + + Model model = persistentModelComponent.getModelReference().toModel(); + if (model != null) { + ModelComponent modelComponent = new ModelComponent(model); + holder.putComponent(this.modelComponentType, modelComponent); + } else { + ModelSystems.LOGGER.atWarning().log("Failed to load model for entity with PersistentModel: {}", persistentModelComponent.getModelReference()); + } } @Override @@ -367,8 +422,11 @@ public class ModelSystems { } public static class UpdateBoundingBox extends RefChangeSystem { + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final ComponentType boundingBoxComponentType = BoundingBox.getComponentType(); + @Nonnull private final ComponentType movementStatesComponentType = MovementStatesComponent.getComponentType(); @Override @@ -385,9 +443,15 @@ public class ModelSystems { public void onComponentAdded( @Nonnull Ref ref, @Nonnull ModelComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - BoundingBox boundingBox = commandBuffer.getComponent(ref, this.boundingBoxComponentType); - MovementStatesComponent movementStates = commandBuffer.getComponent(ref, this.movementStatesComponentType); - updateBoundingBox(component.getModel(), boundingBox, movementStates); + BoundingBox boundingBoxComponent = commandBuffer.getComponent(ref, this.boundingBoxComponentType); + + assert boundingBoxComponent != null; + + MovementStatesComponent movementStatesComponent = commandBuffer.getComponent(ref, this.movementStatesComponentType); + + assert movementStatesComponent != null; + + updateBoundingBox(component.getModel(), boundingBoxComponent, movementStatesComponent); } public void onComponentSet( @@ -397,15 +461,25 @@ public class ModelSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - BoundingBox boundingBox = commandBuffer.getComponent(ref, this.boundingBoxComponentType); - MovementStatesComponent movementStates = commandBuffer.getComponent(ref, this.movementStatesComponentType); - updateBoundingBox(newComponent.getModel(), boundingBox, movementStates); + BoundingBox boundingBoxComponent = commandBuffer.getComponent(ref, this.boundingBoxComponentType); + + assert boundingBoxComponent != null; + + MovementStatesComponent movementStatesComponent = commandBuffer.getComponent(ref, this.movementStatesComponentType); + + assert movementStatesComponent != null; + + updateBoundingBox(newComponent.getModel(), boundingBoxComponent, movementStatesComponent); } public void onComponentRemoved( @Nonnull Ref ref, @Nonnull ModelComponent component, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - commandBuffer.getComponent(ref, this.boundingBoxComponentType).setBoundingBox(new Box()); + BoundingBox boundingBoxComponent = commandBuffer.getComponent(ref, this.boundingBoxComponentType); + + assert boundingBoxComponent != null; + + boundingBoxComponent.setBoundingBox(new Box()); } protected static void updateBoundingBox(@Nonnull Model model, @Nonnull BoundingBox boundingBox, @Nullable MovementStatesComponent movementStatesComponent) { @@ -423,12 +497,17 @@ public class ModelSystems { } public static class UpdateCrouchingBoundingBox extends EntityTickingSystem { + @Nonnull public static final Set> DEPENDENCIES = Collections.singleton( new SystemDependency<>(Order.BEFORE, MovementStatesSystems.TickingSystem.class) ); + @Nonnull private final ComponentType movementStatesComponentType = MovementStatesComponent.getComponentType(); + @Nonnull private final ComponentType boundingBoxComponentType = BoundingBox.getComponentType(); + @Nonnull private final ComponentType modelComponentType = ModelComponent.getComponentType(); + @Nonnull private final Query query = Query.and(this.movementStatesComponentType, this.boundingBoxComponentType, this.modelComponentType); @Override @@ -456,13 +535,23 @@ public class ModelSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - MovementStatesComponent movementStates = archetypeChunk.getComponent(index, this.movementStatesComponentType); - MovementStates newMovementStates = movementStates.getMovementStates(); - MovementStates sentMovementStates = movementStates.getSentMovementStates(); + MovementStatesComponent movementStatesComponent = archetypeChunk.getComponent(index, this.movementStatesComponentType); + + assert movementStatesComponent != null; + + MovementStates newMovementStates = movementStatesComponent.getMovementStates(); + MovementStates sentMovementStates = movementStatesComponent.getSentMovementStates(); if (newMovementStates.crouching != sentMovementStates.crouching || newMovementStates.forcedCrouching != sentMovementStates.forcedCrouching) { - Model model = archetypeChunk.getComponent(index, this.modelComponentType).getModel(); - BoundingBox boundingBox = archetypeChunk.getComponent(index, this.boundingBoxComponentType); - ModelSystems.UpdateBoundingBox.updateBoundingBox(model, boundingBox, newMovementStates); + ModelComponent modelComponent = archetypeChunk.getComponent(index, this.modelComponentType); + + assert modelComponent != null; + + Model model = modelComponent.getModel(); + BoundingBox boundingBoxComponent = archetypeChunk.getComponent(index, this.boundingBoxComponentType); + + assert boundingBoxComponent != null; + + ModelSystems.UpdateBoundingBox.updateBoundingBox(model, boundingBoxComponent, newMovementStates); } } } diff --git a/src/com/hypixel/hytale/server/core/modules/entity/teleport/Teleport.java b/src/com/hypixel/hytale/server/core/modules/entity/teleport/Teleport.java index b39e3ca9..25e53026 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/teleport/Teleport.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/teleport/Teleport.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.server.core.modules.entity.EntityModule; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -21,6 +22,7 @@ public class Teleport implements Component { @Nullable private Vector3f headRotation; private boolean resetVelocity = true; + private CompletableFuture onComplete; @Nonnull public static ComponentType getComponentType() { @@ -92,6 +94,14 @@ public class Teleport implements Component { return this; } + public void setOnComplete(@Nonnull CompletableFuture onComplete) { + this.onComplete = onComplete; + } + + public CompletableFuture getOnComplete() { + return this.onComplete; + } + @Nullable public World getWorld() { return this.world; diff --git a/src/com/hypixel/hytale/server/core/modules/entity/teleport/TeleportSystems.java b/src/com/hypixel/hytale/server/core/modules/entity/teleport/TeleportSystems.java index a0fc0995..d2ada8d2 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/teleport/TeleportSystems.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/teleport/TeleportSystems.java @@ -23,6 +23,7 @@ import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.util.PositionUtil; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; public class TeleportSystems { @@ -62,15 +63,22 @@ public class TeleportSystems { headRotationComponent.teleportRotation(teleport.getRotation()); } + CompletableFuture future = teleport.getOnComplete(); + commandBuffer.removeComponent(ref, this.teleportComponentType); World targetWorld = teleport.getWorld(); if (targetWorld != null && !targetWorld.equals(store.getExternalData().getWorld())) { commandBuffer.run(s -> { Holder holder = s.removeEntity(ref, RemoveReason.UNLOAD); - targetWorld.execute(() -> targetWorld.getEntityStore().getStore().addEntity(holder, AddReason.LOAD)); + targetWorld.execute(() -> { + targetWorld.getEntityStore().getStore().addEntity(holder, AddReason.LOAD); + if (future != null) { + future.complete(null); + } + }); }); + } else if (future != null) { + future.complete(null); } - - commandBuffer.removeComponent(ref, this.teleportComponentType); } public void onComponentRemoved( @@ -223,7 +231,21 @@ public class TeleportSystems { TeleportRecord teleportRecord = s.ensureAndGetComponent(ref, TeleportRecord.getComponentType()); teleportRecord.setLastTeleport(new TeleportRecord.Entry(origin, destination, System.nanoTime())); playerRefComponent.removeFromStore(); - targetWorld.addPlayer(playerRefComponent, new Transform(teleport.getPosition(), teleport.getRotation())); + CompletableFuture fut = targetWorld.addPlayer(playerRefComponent, new Transform(teleport.getPosition(), teleport.getRotation())); + CompletableFuture future = teleport.getOnComplete(); + if (future != null) { + if (fut != null) { + fut.whenComplete((playerRef, throwable) -> { + if (throwable != null) { + future.completeExceptionally(throwable); + } else { + future.complete(null); + } + }); + } else { + future.completeExceptionally(new RuntimeException("Failed to teleport player to world " + targetWorld.getName())); + } + } }); } @@ -270,6 +292,11 @@ public class TeleportSystems { teleport.isResetVelocity() ); playerRefComponent.getPacketHandler().write(teleportPacket); + CompletableFuture future = teleport.getOnComplete(); + if (future != null) { + future.complete(null); + } + commandBuffer.removeComponent(ref, this.teleportComponentType); } } diff --git a/src/com/hypixel/hytale/server/core/modules/entity/tracker/EntityTrackerSystems.java b/src/com/hypixel/hytale/server/core/modules/entity/tracker/EntityTrackerSystems.java index 0bff8910..dc18659f 100644 --- a/src/com/hypixel/hytale/server/core/modules/entity/tracker/EntityTrackerSystems.java +++ b/src/com/hypixel/hytale/server/core/modules/entity/tracker/EntityTrackerSystems.java @@ -54,51 +54,66 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class EntityTrackerSystems { + @Nonnull public static final SystemGroup FIND_VISIBLE_ENTITIES_GROUP = EntityStore.REGISTRY.registerSystemGroup(); + @Nonnull public static final SystemGroup QUEUE_UPDATE_GROUP = EntityStore.REGISTRY.registerSystemGroup(); public static boolean despawnAll(@Nonnull Ref viewerRef, @Nonnull Store store) { - EntityTrackerSystems.EntityViewer viewer = store.getComponent(viewerRef, EntityTrackerSystems.EntityViewer.getComponentType()); - if (viewer == null) { + if (!viewerRef.isValid()) { return false; } else { - int networkId = viewer.sent.removeInt(viewerRef); - EntityUpdates packet = new EntityUpdates(); - packet.removed = viewer.sent.values().toIntArray(); - viewer.packetReceiver.writeNoCache(packet); - clear(viewerRef, store); - viewer.sent.put(viewerRef, networkId); - return true; + EntityTrackerSystems.EntityViewer entityViewerComponent = store.getComponent(viewerRef, EntityTrackerSystems.EntityViewer.getComponentType()); + if (entityViewerComponent == null) { + return false; + } else { + int networkId = entityViewerComponent.sent.removeInt(viewerRef); + EntityUpdates packet = new EntityUpdates(); + packet.removed = entityViewerComponent.sent.values().toIntArray(); + entityViewerComponent.packetReceiver.writeNoCache(packet); + clear(viewerRef, store); + entityViewerComponent.sent.put(viewerRef, networkId); + return true; + } } } public static boolean clear(@Nonnull Ref viewerRef, @Nonnull Store store) { - EntityTrackerSystems.EntityViewer viewer = store.getComponent(viewerRef, EntityTrackerSystems.EntityViewer.getComponentType()); - if (viewer == null) { + if (!viewerRef.isValid()) { return false; } else { - for (Ref ref : viewer.sent.keySet()) { - EntityTrackerSystems.Visible visible = store.getComponent(ref, EntityTrackerSystems.Visible.getComponentType()); - if (visible != null) { - visible.visibleTo.remove(viewerRef); + EntityTrackerSystems.EntityViewer entityViewerComponent = store.getComponent(viewerRef, EntityTrackerSystems.EntityViewer.getComponentType()); + if (entityViewerComponent == null) { + return false; + } else { + for (Ref ref : entityViewerComponent.sent.keySet()) { + if (ref != null && ref.isValid()) { + EntityTrackerSystems.Visible visibleComponent = store.getComponent(ref, EntityTrackerSystems.Visible.getComponentType()); + if (visibleComponent != null) { + visibleComponent.visibleTo.remove(viewerRef); + } + } } - } - viewer.sent.clear(); - return true; + entityViewerComponent.sent.clear(); + return true; + } } } public static class AddToVisible extends EntityTickingSystem { + @Nonnull public static final Set> DEPENDENCIES = Collections.singleton( new SystemDependency<>(Order.AFTER, EntityTrackerSystems.EnsureVisibleComponent.class) ); + @Nonnull private final ComponentType entityViewerComponentType; + @Nonnull private final ComponentType visibleComponentType; public AddToVisible( - ComponentType entityViewerComponentType, - ComponentType visibleComponentType + @Nonnull ComponentType entityViewerComponentType, + @Nonnull ComponentType visibleComponentType ) { this.entityViewerComponentType = entityViewerComponentType; this.visibleComponentType = visibleComponentType; @@ -128,23 +143,32 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - Ref viewerRef = archetypeChunk.getReferenceTo(index); - EntityTrackerSystems.EntityViewer viewer = archetypeChunk.getComponent(index, this.entityViewerComponentType); + Ref ref = archetypeChunk.getReferenceTo(index); + EntityTrackerSystems.EntityViewer entityViewerComponent = archetypeChunk.getComponent(index, this.entityViewerComponentType); - for (Ref ref : viewer.visible) { - commandBuffer.getComponent(ref, this.visibleComponentType).addViewerParallel(viewerRef, viewer); + assert entityViewerComponent != null; + + for (Ref vislbleRef : entityViewerComponent.visible) { + if (vislbleRef != null && vislbleRef.isValid()) { + EntityTrackerSystems.Visible visibleComponent = commandBuffer.getComponent(vislbleRef, this.visibleComponentType); + if (visibleComponent != null) { + visibleComponent.addViewerParallel(ref, entityViewerComponent); + } + } } } } public static class ClearEntityViewers extends EntityTickingSystem { + @Nonnull public static final Set> DEPENDENCIES = Collections.singleton( new SystemGroupDependency<>(Order.BEFORE, EntityTrackerSystems.FIND_VISIBLE_ENTITIES_GROUP) ); - private final ComponentType componentType; + @Nonnull + private final ComponentType entityViewerComponentType; - public ClearEntityViewers(ComponentType componentType) { - this.componentType = componentType; + public ClearEntityViewers(@Nonnull ComponentType entityViewerComponentType) { + this.entityViewerComponentType = entityViewerComponentType; } @Nonnull @@ -155,7 +179,7 @@ public class EntityTrackerSystems { @Override public Query getQuery() { - return this.componentType; + return this.entityViewerComponentType; } @Override @@ -171,22 +195,27 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - EntityTrackerSystems.EntityViewer viewer = archetypeChunk.getComponent(index, this.componentType); - viewer.visible.clear(); - viewer.lodExcludedCount = 0; - viewer.hiddenCount = 0; + EntityTrackerSystems.EntityViewer entityViewerComponent = archetypeChunk.getComponent(index, this.entityViewerComponentType); + + assert entityViewerComponent != null; + + entityViewerComponent.visible.clear(); + entityViewerComponent.lodExcludedCount = 0; + entityViewerComponent.hiddenCount = 0; } } public static class ClearPreviouslyVisible extends EntityTickingSystem { + @Nonnull public static final Set> DEPENDENCIES = Set.of( new SystemDependency<>(Order.AFTER, EntityTrackerSystems.ClearEntityViewers.class), new SystemGroupDependency(Order.AFTER, EntityTrackerSystems.FIND_VISIBLE_ENTITIES_GROUP) ); - private final ComponentType componentType; + @Nonnull + private final ComponentType visibleComponentType; - public ClearPreviouslyVisible(ComponentType componentType) { - this.componentType = componentType; + public ClearPreviouslyVisible(@Nonnull ComponentType visibleComponentType) { + this.visibleComponentType = visibleComponentType; } @Nonnull @@ -197,7 +226,7 @@ public class EntityTrackerSystems { @Override public Query getQuery() { - return this.componentType; + return this.visibleComponentType; } @Override @@ -213,24 +242,29 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - EntityTrackerSystems.Visible visible = archetypeChunk.getComponent(index, this.componentType); - Map, EntityTrackerSystems.EntityViewer> oldVisibleTo = visible.previousVisibleTo; - visible.previousVisibleTo = visible.visibleTo; - visible.visibleTo = oldVisibleTo; - visible.visibleTo.clear(); - visible.newlyVisibleTo.clear(); + EntityTrackerSystems.Visible visibleComponent = archetypeChunk.getComponent(index, this.visibleComponentType); + + assert visibleComponent != null; + + Map, EntityTrackerSystems.EntityViewer> oldVisibleTo = visibleComponent.previousVisibleTo; + visibleComponent.previousVisibleTo = visibleComponent.visibleTo; + visibleComponent.visibleTo = oldVisibleTo; + visibleComponent.visibleTo.clear(); + visibleComponent.newlyVisibleTo.clear(); } } public static class CollectVisible extends EntityTickingSystem { - private final ComponentType componentType; + @Nonnull + private final ComponentType entityViewerComponentType; + @Nonnull private final Query query; @Nonnull private final Set> dependencies; - public CollectVisible(ComponentType componentType) { - this.componentType = componentType; - this.query = Archetype.of(componentType, TransformComponent.getComponentType()); + public CollectVisible(@Nonnull ComponentType entityViewerComponentType) { + this.entityViewerComponentType = entityViewerComponentType; + this.query = Archetype.of(entityViewerComponentType, TransformComponent.getComponentType()); this.dependencies = Collections.singleton(new SystemDependency<>(Order.AFTER, NetworkSendableSpatialSystem.class)); } @@ -264,14 +298,20 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - TransformComponent transform = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); - Vector3d position = transform.getPosition(); - EntityTrackerSystems.EntityViewer entityViewer = archetypeChunk.getComponent(index, this.componentType); + TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); + + assert transformComponent != null; + + Vector3d position = transformComponent.getPosition(); + EntityTrackerSystems.EntityViewer entityViewerComponent = archetypeChunk.getComponent(index, this.entityViewerComponentType); + + assert entityViewerComponent != null; + SpatialStructure> spatialStructure = store.getResource(EntityModule.get().getNetworkSendableSpatialResourceType()) .getSpatialStructure(); ObjectList> results = SpatialResource.getThreadLocalReferenceList(); - spatialStructure.collect(position, entityViewer.viewRadiusBlocks, results); - entityViewer.visible.addAll(results); + spatialStructure.collect(position, entityViewerComponent.viewRadiusBlocks, results); + entityViewerComponent.visible.addAll(results); } } @@ -321,17 +361,17 @@ public class EntityTrackerSystems { assert visibleComponent != null; - Ref entityRef = archetypeChunk.getReferenceTo(index); EffectControllerComponent effectControllerComponent = archetypeChunk.getComponent(index, this.effectControllerComponentType); assert effectControllerComponent != null; + Ref ref = archetypeChunk.getReferenceTo(index); if (!visibleComponent.newlyVisibleTo.isEmpty()) { - queueFullUpdate(entityRef, effectControllerComponent, visibleComponent.newlyVisibleTo); + queueFullUpdate(ref, effectControllerComponent, visibleComponent.newlyVisibleTo); } if (effectControllerComponent.consumeNetworkOutdated()) { - queueUpdatesFor(entityRef, effectControllerComponent, visibleComponent.visibleTo, visibleComponent.newlyVisibleTo); + queueUpdatesFor(ref, effectControllerComponent, visibleComponent.visibleTo, visibleComponent.newlyVisibleTo); } } @@ -373,15 +413,18 @@ public class EntityTrackerSystems { } public static class EnsureVisibleComponent extends EntityTickingSystem { + @Nonnull public static final Set> DEPENDENCIES = Collections.singleton( new SystemDependency<>(Order.AFTER, EntityTrackerSystems.ClearPreviouslyVisible.class) ); + @Nonnull private final ComponentType entityViewerComponentType; + @Nonnull private final ComponentType visibleComponentType; public EnsureVisibleComponent( - ComponentType entityViewerComponentType, - ComponentType visibleComponentType + @Nonnull ComponentType entityViewerComponentType, + @Nonnull ComponentType visibleComponentType ) { this.entityViewerComponentType = entityViewerComponentType; this.visibleComponentType = visibleComponentType; @@ -411,9 +454,13 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - for (Ref ref : archetypeChunk.getComponent(index, this.entityViewerComponentType).visible) { - if (!commandBuffer.getArchetype(ref).contains(this.visibleComponentType)) { - commandBuffer.ensureComponent(ref, this.visibleComponentType); + EntityTrackerSystems.EntityViewer entityViewerComponent = archetypeChunk.getComponent(index, this.entityViewerComponentType); + + assert entityViewerComponent != null; + + for (Ref visibleRef : entityViewerComponent.visible) { + if (visibleRef != null && visibleRef.isValid() && !commandBuffer.getArchetype(visibleRef).contains(this.visibleComponentType)) { + commandBuffer.ensureComponent(visibleRef, this.visibleComponentType); } } } @@ -477,9 +524,13 @@ public class EntityTrackerSystems { public static class EntityViewer implements Component { public int viewRadiusBlocks; + @Nonnull public IPacketReceiver packetReceiver; + @Nonnull public Set> visible; + @Nonnull public Map, EntityTrackerSystems.EntityUpdate> updates; + @Nonnull public Object2IntMap> sent; public int lodExcludedCount; public int hiddenCount; @@ -488,7 +539,7 @@ public class EntityTrackerSystems { return EntityModule.get().getEntityViewerComponentType(); } - public EntityViewer(int viewRadiusBlocks, IPacketReceiver packetReceiver) { + public EntityViewer(int viewRadiusBlocks, @Nonnull IPacketReceiver packetReceiver) { this.viewRadiusBlocks = viewRadiusBlocks; this.packetReceiver = packetReceiver; this.visible = new ObjectOpenHashSet<>(); @@ -517,7 +568,7 @@ public class EntityTrackerSystems { return new EntityTrackerSystems.EntityViewer(this); } - public void queueRemove(Ref ref, ComponentUpdateType type) { + public void queueRemove(@Nonnull Ref ref, @Nonnull ComponentUpdateType type) { if (!this.visible.contains(ref)) { throw new IllegalArgumentException("Entity is not visible!"); } else { @@ -525,7 +576,7 @@ public class EntityTrackerSystems { } } - public void queueUpdate(Ref ref, ComponentUpdate update) { + public void queueUpdate(@Nonnull Ref ref, @Nonnull ComponentUpdate update) { if (!this.visible.contains(ref)) { throw new IllegalArgumentException("Entity is not visible!"); } else { @@ -535,14 +586,16 @@ public class EntityTrackerSystems { } public static class RemoveEmptyVisibleComponent extends EntityTickingSystem { + @Nonnull public static final Set> DEPENDENCIES = Set.of( new SystemDependency<>(Order.AFTER, EntityTrackerSystems.AddToVisible.class), new SystemGroupDependency(Order.BEFORE, EntityTrackerSystems.QUEUE_UPDATE_GROUP) ); - private final ComponentType componentType; + @Nonnull + private final ComponentType visibleComponentType; - public RemoveEmptyVisibleComponent(ComponentType componentType) { - this.componentType = componentType; + public RemoveEmptyVisibleComponent(@Nonnull ComponentType visibleComponentType) { + this.visibleComponentType = visibleComponentType; } @Nonnull @@ -553,7 +606,7 @@ public class EntityTrackerSystems { @Override public Query getQuery() { - return this.componentType; + return this.visibleComponentType; } @Override @@ -569,22 +622,27 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - if (archetypeChunk.getComponent(index, this.componentType).visibleTo.isEmpty()) { - commandBuffer.removeComponent(archetypeChunk.getReferenceTo(index), this.componentType); + EntityTrackerSystems.Visible visibleComponent = archetypeChunk.getComponent(index, this.visibleComponentType); + + assert visibleComponent != null; + + if (visibleComponent.visibleTo.isEmpty()) { + commandBuffer.removeComponent(archetypeChunk.getReferenceTo(index), this.visibleComponentType); } } } public static class RemoveVisibleComponent extends HolderSystem { - private final ComponentType componentType; + @Nonnull + private final ComponentType visibleComponentType; - public RemoveVisibleComponent(ComponentType componentType) { - this.componentType = componentType; + public RemoveVisibleComponent(@Nonnull ComponentType visibleComponentType) { + this.visibleComponentType = visibleComponentType; } @Override public Query getQuery() { - return this.componentType; + return this.visibleComponentType; } @Override @@ -593,18 +651,22 @@ public class EntityTrackerSystems { @Override public void onEntityRemoved(@Nonnull Holder holder, @Nonnull RemoveReason reason, @Nonnull Store store) { - holder.removeComponent(this.componentType); + holder.removeComponent(this.visibleComponentType); } } public static class SendPackets extends EntityTickingSystem { + @Nonnull public static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + @Nonnull public static final ThreadLocal INT_LIST_THREAD_LOCAL = ThreadLocal.withInitial(IntArrayList::new); + @Nonnull public static final Set> DEPENDENCIES = Set.of(new SystemGroupDependency<>(Order.AFTER, EntityTrackerSystems.QUEUE_UPDATE_GROUP)); - private final ComponentType componentType; + @Nonnull + private final ComponentType entityViewerComponentType; - public SendPackets(ComponentType componentType) { - this.componentType = componentType; + public SendPackets(@Nonnull ComponentType entityViewerComponentType) { + this.entityViewerComponentType = entityViewerComponentType; } @Nullable @@ -621,7 +683,7 @@ public class EntityTrackerSystems { @Override public Query getQuery() { - return this.componentType; + return this.entityViewerComponentType; } @Override @@ -637,61 +699,70 @@ public class EntityTrackerSystems { @Nonnull Store store, @Nonnull CommandBuffer commandBuffer ) { - EntityTrackerSystems.EntityViewer viewer = archetypeChunk.getComponent(index, this.componentType); + EntityTrackerSystems.EntityViewer entityViewerComponent = archetypeChunk.getComponent(index, this.entityViewerComponentType); + + assert entityViewerComponent != null; + IntList removedEntities = INT_LIST_THREAD_LOCAL.get(); removedEntities.clear(); - int before = viewer.updates.size(); - viewer.updates.entrySet().removeIf(v -> !v.getKey().isValid()); - if (before != viewer.updates.size()) { - LOGGER.atWarning().log("Removed %d invalid updates for removed entities.", before - viewer.updates.size()); + int before = entityViewerComponent.updates.size(); + entityViewerComponent.updates.entrySet().removeIf(v -> !v.getKey().isValid()); + if (before != entityViewerComponent.updates.size()) { + LOGGER.atWarning().log("Removed %d invalid updates for removed entities.", before - entityViewerComponent.updates.size()); } - ObjectIterator>> iterator = viewer.sent.object2IntEntrySet().iterator(); + ObjectIterator>> iterator = entityViewerComponent.sent + .object2IntEntrySet() + .iterator(); while (iterator.hasNext()) { it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> entry = iterator.next(); Ref ref = entry.getKey(); - if (!ref.isValid() || !viewer.visible.contains(ref)) { + if (ref == null || !ref.isValid() || !entityViewerComponent.visible.contains(ref)) { removedEntities.add(entry.getIntValue()); iterator.remove(); - if (viewer.updates.remove(ref) != null) { + if (entityViewerComponent.updates.remove(ref) != null) { LOGGER.atSevere().log("Entity can't be removed and also receive an update! " + ref); } } } - if (!removedEntities.isEmpty() || !viewer.updates.isEmpty()) { - Iterator> iteratorx = viewer.updates.keySet().iterator(); + if (!removedEntities.isEmpty() || !entityViewerComponent.updates.isEmpty()) { + Iterator> iteratorx = entityViewerComponent.updates.keySet().iterator(); while (iteratorx.hasNext()) { Ref ref = iteratorx.next(); - if (!ref.isValid() || ref.getStore() != store) { + if (ref == null || !ref.isValid() || ref.getStore() != store) { iteratorx.remove(); - } else if (!viewer.sent.containsKey(ref)) { - int networkId = commandBuffer.getComponent(ref, NetworkId.getComponentType()).getId(); + } else if (!entityViewerComponent.sent.containsKey(ref)) { + NetworkId networkIdComponent = commandBuffer.getComponent(ref, NetworkId.getComponentType()); + + assert networkIdComponent != null; + + int networkId = networkIdComponent.getId(); if (networkId == -1) { throw new IllegalArgumentException("Invalid entity network id: " + ref); } - viewer.sent.put(ref, networkId); + entityViewerComponent.sent.put(ref, networkId); } } EntityUpdates packet = new EntityUpdates(); packet.removed = !removedEntities.isEmpty() ? removedEntities.toIntArray() : null; - packet.updates = new com.hypixel.hytale.protocol.EntityUpdate[viewer.updates.size()]; + packet.updates = new com.hypixel.hytale.protocol.EntityUpdate[entityViewerComponent.updates.size()]; int i = 0; - for (Entry, EntityTrackerSystems.EntityUpdate> entry : viewer.updates.entrySet()) { + for (Entry, EntityTrackerSystems.EntityUpdate> entry : entityViewerComponent.updates.entrySet()) { com.hypixel.hytale.protocol.EntityUpdate entityUpdate = packet.updates[i++] = new com.hypixel.hytale.protocol.EntityUpdate(); - entityUpdate.networkId = viewer.sent.getInt(entry.getKey()); + entityUpdate.networkId = entityViewerComponent.sent.getInt(entry.getKey()); EntityTrackerSystems.EntityUpdate update = entry.getValue(); entityUpdate.removed = update.toRemovedArray(); entityUpdate.updates = update.toUpdatesArray(); } - viewer.updates.clear(); - viewer.packetReceiver.writeNoCache(packet); + entityViewerComponent.updates.clear(); + entityViewerComponent.packetReceiver.writeNoCache(packet); } } } @@ -717,13 +788,13 @@ public class EntityTrackerSystems { return new EntityTrackerSystems.Visible(); } - public void addViewerParallel(Ref ref, EntityTrackerSystems.EntityViewer entityViewer) { + public void addViewerParallel(@Nonnull Ref ref, @Nonnull EntityTrackerSystems.EntityViewer entityViewerComponent) { long stamp = this.lock.writeLock(); try { - this.visibleTo.put(ref, entityViewer); + this.visibleTo.put(ref, entityViewerComponent); if (!this.previousVisibleTo.containsKey(ref)) { - this.newlyVisibleTo.put(ref, entityViewer); + this.newlyVisibleTo.put(ref, entityViewerComponent); } } finally { this.lock.unlockWrite(stamp); diff --git a/src/com/hypixel/hytale/server/core/modules/entitystats/asset/EntityStatType.java b/src/com/hypixel/hytale/server/core/modules/entitystats/asset/EntityStatType.java index 448a3f59..7ac317bb 100644 --- a/src/com/hypixel/hytale/server/core/modules/entitystats/asset/EntityStatType.java +++ b/src/com/hypixel/hytale/server/core/modules/entitystats/asset/EntityStatType.java @@ -92,6 +92,13 @@ public class EntityStatType (entityStatType, parent) -> entityStatType.ignoreInvulnerability = parent.ignoreInvulnerability ) .add() + .appendInherited( + new KeyedCodec<>("HideFromTooltip", Codec.BOOLEAN), + (entityStatType, aBoolean) -> entityStatType.hideFromTooltip = aBoolean, + entityStatType -> entityStatType.hideFromTooltip, + (entityStatType, parent) -> entityStatType.hideFromTooltip = parent.hideFromTooltip + ) + .add() .build(); public static final ValidatorCache VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(EntityStatType::getAssetStore)); private static AssetStore> ASSET_STORE; @@ -107,6 +114,7 @@ public class EntityStatType @Nullable protected EntityStatType.Regenerating[] regenerating; protected boolean ignoreInvulnerability; + protected boolean hideFromTooltip; protected EntityStatType.EntityStatEffects minValueEffects; protected EntityStatType.EntityStatEffects maxValueEffects; protected EntityStatResetBehavior resetBehavior = EntityStatResetBehavior.InitialValue; @@ -214,6 +222,7 @@ public class EntityStatType } packet.resetBehavior = this.resetBehavior; + packet.hideFromTooltip = this.hideFromTooltip; this.cachedPacket = new SoftReference<>(packet); return packet; } @@ -246,6 +255,8 @@ public class EntityStatType + this.resetBehavior + ", ignoreInvulnerability=" + this.ignoreInvulnerability + + ", hideFromTooltip=" + + this.hideFromTooltip + "}"; } diff --git a/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/client/PlaceFluidInteraction.java b/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/client/PlaceFluidInteraction.java index 25879f1c..4dd9a4e5 100644 --- a/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/client/PlaceFluidInteraction.java +++ b/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/client/PlaceFluidInteraction.java @@ -79,7 +79,8 @@ public class PlaceFluidInteraction extends SimpleBlockInteraction { Fluid fluid = Fluid.getAssetMap().getAsset(fluidIndex); Vector3i target = targetBlock; BlockType targetBlockType = world.getBlockType(targetBlock); - if (FluidTicker.isSolid(targetBlockType)) { + FluidTicker ticker = fluid.getTicker(); + if (!ticker.canOccupySolidBlocks() && FluidTicker.isSolid(targetBlockType)) { target = targetBlock.clone(); BlockFace face = BlockFace.fromProtocolFace(context.getClientState().blockFace); target.add(face.getDirection()); diff --git a/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/server/SpawnPrefabInteraction.java b/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/server/SpawnPrefabInteraction.java index 11f08702..282ab664 100644 --- a/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/server/SpawnPrefabInteraction.java +++ b/src/com/hypixel/hytale/server/core/modules/interaction/interaction/config/server/SpawnPrefabInteraction.java @@ -63,46 +63,48 @@ public class SpawnPrefabInteraction extends SimpleInstantInteraction { @Override protected void firstRun(@Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler) { - Path prefabRoot = PrefabStore.get().getAssetPrefabsPath(); - IPrefabBuffer prefab = PrefabBufferUtil.getCached(prefabRoot.resolve(this.prefabPath)); - if (prefab != null) { - CommandBuffer commandBuffer = context.getCommandBuffer(); - World world = commandBuffer.getExternalData().getWorld(); - Ref ref = context.getEntity(); - TransformComponent transformComponent = commandBuffer.getComponent(ref, TransformComponent.getComponentType()); + Path resolvedPath = PrefabStore.get().findAssetPrefabPath(this.prefabPath); + if (resolvedPath != null) { + IPrefabBuffer prefab = PrefabBufferUtil.getCached(resolvedPath); + if (prefab != null) { + CommandBuffer commandBuffer = context.getCommandBuffer(); + World world = commandBuffer.getExternalData().getWorld(); + Ref ref = context.getEntity(); + TransformComponent transformComponent = commandBuffer.getComponent(ref, TransformComponent.getComponentType()); - assert transformComponent != null; + assert transformComponent != null; - Vector3d entityPosition = transformComponent.getPosition(); - Rotation yaw = this.rotationYaw; - Vector3i target; - switch (this.originSource) { - case ENTITY: - target = entityPosition.toVector3i(); - target.add(this.offset); - break; - case BLOCK: - BlockPosition targetBlock = context.getTargetBlock(); - if (targetBlock == null) { - return; - } + Vector3d entityPosition = transformComponent.getPosition(); + Rotation yaw = this.rotationYaw; + Vector3i target; + switch (this.originSource) { + case ENTITY: + target = entityPosition.toVector3i(); + target.add(this.offset); + break; + case BLOCK: + BlockPosition targetBlock = context.getTargetBlock(); + if (targetBlock == null) { + return; + } - WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z)); - if (chunk == null) { - return; - } + WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z)); + if (chunk == null) { + return; + } - Rotation blockYaw = chunk.getRotation(targetBlock.x, targetBlock.y, targetBlock.z).yaw(); - target = new Vector3i(); - blockYaw.rotateYaw(this.offset, target); - yaw = yaw.add(blockYaw); - target.add(targetBlock.x, targetBlock.y, targetBlock.z); - break; - default: - throw new IllegalArgumentException("Unhandled origin source"); + Rotation blockYaw = chunk.getRotation(targetBlock.x, targetBlock.y, targetBlock.z).yaw(); + target = new Vector3i(); + blockYaw.rotateYaw(this.offset, target); + yaw = yaw.add(blockYaw); + target.add(targetBlock.x, targetBlock.y, targetBlock.z); + break; + default: + throw new IllegalArgumentException("Unhandled origin source"); + } + + PrefabUtil.paste(prefab, world, target, yaw, this.force, new FastRandom(), commandBuffer); } - - PrefabUtil.paste(prefab, world, target, yaw, this.force, new FastRandom(), commandBuffer); } } diff --git a/src/com/hypixel/hytale/server/core/modules/projectile/config/BallisticData.java b/src/com/hypixel/hytale/server/core/modules/projectile/config/BallisticData.java index 6c330ebd..b36b8a30 100644 --- a/src/com/hypixel/hytale/server/core/modules/projectile/config/BallisticData.java +++ b/src/com/hypixel/hytale/server/core/modules/projectile/config/BallisticData.java @@ -7,6 +7,8 @@ public interface BallisticData { double getVerticalCenterShot(); + double getHorizontalCenterShot(); + double getDepthShot(); boolean isPitchAdjustShot(); diff --git a/src/com/hypixel/hytale/server/core/modules/projectile/config/ProjectileConfig.java b/src/com/hypixel/hytale/server/core/modules/projectile/config/ProjectileConfig.java index 6fd2506a..1f555f9b 100644 --- a/src/com/hypixel/hytale/server/core/modules/projectile/config/ProjectileConfig.java +++ b/src/com/hypixel/hytale/server/core/modules/projectile/config/ProjectileConfig.java @@ -201,6 +201,11 @@ public class ProjectileConfig return this.spawnOffset.y; } + @Override + public double getHorizontalCenterShot() { + return this.spawnOffset.x; + } + @Override public double getDepthShot() { return this.spawnOffset.z; diff --git a/src/com/hypixel/hytale/server/core/modules/singleplayer/commands/PlayCommandBase.java b/src/com/hypixel/hytale/server/core/modules/singleplayer/commands/PlayCommandBase.java index 918e0b0d..c6170084 100644 --- a/src/com/hypixel/hytale/server/core/modules/singleplayer/commands/PlayCommandBase.java +++ b/src/com/hypixel/hytale/server/core/modules/singleplayer/commands/PlayCommandBase.java @@ -8,7 +8,6 @@ import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalAr import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase; import com.hypixel.hytale.server.core.modules.singleplayer.SingleplayerModule; -import com.hypixel.hytale.server.core.util.message.MessageFormat; import javax.annotation.Nonnull; public abstract class PlayCommandBase extends CommandBase { @@ -76,7 +75,7 @@ public abstract class PlayCommandBase extends CommandBase { } } } else { - boolean enabled = this.enabledArg.get(context); + Boolean enabled = this.enabledArg.get(context); if (!enabled && access == this.commandAccess) { this.singleplayerModule.requestServerAccess(Access.Private); switch (this.commandAccess) { @@ -110,20 +109,16 @@ public abstract class PlayCommandBase extends CommandBase { } else { switch (this.commandAccess) { case Private: - context.sendMessage( - Message.translation("server.commands.play.accessAlreadyToggledPrivate").param("enabled", MessageFormat.enabled(enabled)) - ); + context.sendMessage(Message.translation("server.commands.play.accessAlreadyToggledPrivate").param("enabled", enabled.toString())); break; case LAN: - context.sendMessage(Message.translation("server.commands.play.accessAlreadyToggledLan").param("enabled", MessageFormat.enabled(enabled))); + context.sendMessage(Message.translation("server.commands.play.accessAlreadyToggledLan").param("enabled", enabled.toString())); break; case Friend: - context.sendMessage( - Message.translation("server.commands.play.accessAlreadyToggledFriend").param("enabled", MessageFormat.enabled(enabled)) - ); + context.sendMessage(Message.translation("server.commands.play.accessAlreadyToggledFriend").param("enabled", enabled.toString())); break; case Open: - context.sendMessage(Message.translation("server.commands.play.accessAlreadyToggledOpen").param("enabled", MessageFormat.enabled(enabled))); + context.sendMessage(Message.translation("server.commands.play.accessAlreadyToggledOpen").param("enabled", enabled.toString())); } } } diff --git a/src/com/hypixel/hytale/server/core/permissions/HytalePermissions.java b/src/com/hypixel/hytale/server/core/permissions/HytalePermissions.java index 87837372..ef1688b2 100644 --- a/src/com/hypixel/hytale/server/core/permissions/HytalePermissions.java +++ b/src/com/hypixel/hytale/server/core/permissions/HytalePermissions.java @@ -22,6 +22,7 @@ public class HytalePermissions { public static final String WORLD_MAP_COORDINATE_TELEPORT = "hytale.world_map.teleport.coordinate"; public static final String WORLD_MAP_MARKER_TELEPORT = "hytale.world_map.teleport.marker"; public static final String UPDATE_NOTIFY = "hytale.system.update.notify"; + public static final String MODS_OUTDATED_NOTIFY = "hytale.mods.outdated.notify"; @Nonnull public static String fromCommand(@Nonnull String name) { diff --git a/src/com/hypixel/hytale/server/core/plugin/JavaPlugin.java b/src/com/hypixel/hytale/server/core/plugin/JavaPlugin.java index 46422ee3..cd5f29f9 100644 --- a/src/com/hypixel/hytale/server/core/plugin/JavaPlugin.java +++ b/src/com/hypixel/hytale/server/core/plugin/JavaPlugin.java @@ -26,8 +26,8 @@ public abstract class JavaPlugin extends PluginBase { } @Override - protected void start0() { - super.start0(); + protected void setup0() { + super.setup0(); if (this.getManifest().includesAssetPack()) { AssetModule assetModule = AssetModule.get(); String id = new PluginIdentifier(this.getManifest()).toString(); diff --git a/src/com/hypixel/hytale/server/core/plugin/PluginBase.java b/src/com/hypixel/hytale/server/core/plugin/PluginBase.java index c61b3698..0b25e750 100644 --- a/src/com/hypixel/hytale/server/core/plugin/PluginBase.java +++ b/src/com/hypixel/hytale/server/core/plugin/PluginBase.java @@ -87,6 +87,7 @@ public abstract class PluginBase implements CommandOwner { private final Map, IRegistry> codecMapRegistries = new ConcurrentHashMap<>(); @Nonnull private final String basePermission; + private Throwable failureCause; public PluginBase(@Nonnull PluginInit init) { PluginManifest pluginManifest = init.getPluginManifest(); @@ -234,7 +235,7 @@ public abstract class PluginBase implements CommandOwner { } public boolean isDisabled() { - return this.state == PluginState.NONE || this.state == PluginState.DISABLED || this.state == PluginState.SHUTDOWN; + return this.state == PluginState.NONE || this.state == PluginState.DISABLED || this.state == PluginState.SHUTDOWN || this.state == PluginState.FAILED; } public boolean isEnabled() { @@ -251,7 +252,8 @@ public abstract class PluginBase implements CommandOwner { this.setup(); } catch (Throwable var2) { this.logger.at(Level.SEVERE).withCause(var2).log("Failed to setup plugin %s", this.identifier); - this.state = PluginState.DISABLED; + this.state = PluginState.FAILED; + this.failureCause = var2; } } } @@ -270,7 +272,8 @@ public abstract class PluginBase implements CommandOwner { this.state = PluginState.ENABLED; } catch (Throwable var2) { this.logger.at(Level.SEVERE).withCause(var2).log("Failed to start %s", this.identifier); - this.state = PluginState.DISABLED; + this.state = PluginState.FAILED; + this.failureCause = var2; } } } @@ -283,9 +286,13 @@ public abstract class PluginBase implements CommandOwner { try { this.shutdown(); - this.state = PluginState.DISABLED; + this.state = this.failureCause == null ? PluginState.DISABLED : PluginState.FAILED; } catch (Throwable var3) { this.logger.at(Level.SEVERE).withCause(var3).log("Failed to shutdown %s", this.identifier); + this.state = PluginState.FAILED; + if (this.failureCause == null) { + this.failureCause = var3; + } } this.cleanup(shutdown); @@ -310,6 +317,14 @@ public abstract class PluginBase implements CommandOwner { } } + Throwable getFailureCause() { + return this.failureCause; + } + + void setFailureCause(Throwable t) { + this.failureCause = t; + } + @Nonnull public abstract PluginType getType(); } diff --git a/src/com/hypixel/hytale/server/core/plugin/PluginClassLoader.java b/src/com/hypixel/hytale/server/core/plugin/PluginClassLoader.java index 5bbc3a2f..2595dc01 100644 --- a/src/com/hypixel/hytale/server/core/plugin/PluginClassLoader.java +++ b/src/com/hypixel/hytale/server/core/plugin/PluginClassLoader.java @@ -1,5 +1,6 @@ package com.hypixel.hytale.server.core.plugin; +import com.hypixel.hytale.common.plugin.PluginIdentifier; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.io.IOException; import java.net.URL; @@ -10,15 +11,14 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class PluginClassLoader extends URLClassLoader { - public static final String THIRD_PARTY_LOADER_NAME = "ThirdPartyPlugin"; @Nonnull private final PluginManager pluginManager; private final boolean inServerClassPath; @Nullable private JavaPlugin plugin; - public PluginClassLoader(@Nonnull PluginManager pluginManager, boolean inServerClassPath, @Nonnull URL... urls) { - super(inServerClassPath ? "BuiltinPlugin" : "ThirdPartyPlugin", urls, null); + public PluginClassLoader(@Nonnull PluginManager pluginManager, @Nullable PluginIdentifier identifier, boolean inServerClassPath, @Nonnull URL... urls) { + super((inServerClassPath ? "BuiltinPlugin" : "ThirdParty") + (identifier != null ? "(" + identifier + ")" : ""), urls, null); this.inServerClassPath = inServerClassPath; this.pluginManager = pluginManager; } @@ -157,7 +157,7 @@ public class PluginClassLoader extends URLClassLoader { public static boolean isFromThirdPartyPlugin(@Nullable Throwable throwable) { while (throwable != null) { for (StackTraceElement element : throwable.getStackTrace()) { - if ("ThirdPartyPlugin".equals(element.getClassLoaderName())) { + if ("ThirdParty".equals(element.getClassLoaderName())) { return true; } } diff --git a/src/com/hypixel/hytale/server/core/plugin/PluginManager.java b/src/com/hypixel/hytale/server/core/plugin/PluginManager.java index 5e14a5ac..6e286e77 100644 --- a/src/com/hypixel/hytale/server/core/plugin/PluginManager.java +++ b/src/com/hypixel/hytale/server/core/plugin/PluginManager.java @@ -7,27 +7,32 @@ import com.hypixel.hytale.codec.codecs.array.ArrayCodec; import com.hypixel.hytale.codec.util.RawJsonReader; import com.hypixel.hytale.common.plugin.PluginIdentifier; import com.hypixel.hytale.common.plugin.PluginManifest; -import com.hypixel.hytale.common.semver.Semver; import com.hypixel.hytale.common.semver.SemverRange; import com.hypixel.hytale.common.util.java.ManifestUtil; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.event.IEventDispatcher; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.metrics.MetricsRegistry; +import com.hypixel.hytale.server.core.Constants; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.HytaleServerConfig; +import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.Options; import com.hypixel.hytale.server.core.ShutdownReason; import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.command.system.CommandManager; +import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.event.events.player.AddPlayerToWorldEvent; import com.hypixel.hytale.server.core.plugin.commands.PluginCommand; import com.hypixel.hytale.server.core.plugin.event.PluginSetupEvent; import com.hypixel.hytale.server.core.plugin.pending.PendingLoadJavaPlugin; import com.hypixel.hytale.server.core.plugin.pending.PendingLoadPlugin; +import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.awt.Color; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -40,9 +45,12 @@ import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Duration; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -70,13 +78,14 @@ public class PluginManager { ); private static PluginManager instance; @Nonnull - private final PluginClassLoader corePluginClassLoader = new PluginClassLoader(this, true); + private final PluginClassLoader corePluginClassLoader = new PluginClassLoader(this, null, true); @Nonnull private final List corePlugins = new ObjectArrayList<>(); private final PluginManager.PluginBridgeClassLoader bridgeClassLoader = new PluginManager.PluginBridgeClassLoader(this, PluginManager.class.getClassLoader()); private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final Map plugins = new Object2ObjectLinkedOpenHashMap<>(); private final Map classLoaders = new ConcurrentHashMap<>(); + private boolean hasOutdatedPlugins = false; private final boolean loadExternalPlugins = true; @Nonnull private PluginState state = PluginState.NONE; @@ -147,8 +156,8 @@ public class PluginManager { Path self; try { self = Paths.get(PluginManager.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - } catch (URISyntaxException var18) { - throw new RuntimeException(var18); + } catch (URISyntaxException var30) { + throw new RuntimeException(var30); } this.loadPluginsFromDirectory(pending, self.getParent().resolve("builtin"), false, this.availablePlugins); @@ -173,8 +182,8 @@ public class PluginManager { try { this.validatePluginDeps(pendingLoadPlugin, pending); - } catch (MissingPluginDependencyException var17) { - LOGGER.at(Level.SEVERE).log(var17.getMessage()); + } catch (MissingPluginDependencyException var29) { + LOGGER.at(Level.SEVERE).log(var29.getMessage()); iterator.remove(); } } @@ -182,10 +191,34 @@ public class PluginManager { this.lock.readLock().unlock(); } + if (this.hasOutdatedPlugins && System.getProperty("hytale.allow_outdated_mods") == null) { + LOGGER.at(Level.SEVERE) + .log("One or more plugins are targeting a different server version. It is recommended to update these plugins to ensure compatibility."); + + try { + if (!Constants.SINGLEPLAYER) { + Thread.sleep(Duration.ofSeconds(2L)); + } + } catch (InterruptedException var32) { + throw new RuntimeException(var32); + } + + HytaleServer.get().getEventBus().registerGlobal(AddPlayerToWorldEvent.class, event -> { + PlayerRef playerRef = event.getHolder().getComponent(PlayerRef.getComponentType()); + Player player = event.getHolder().getComponent(Player.getComponentType()); + if (playerRef != null && player != null) { + if (player.hasPermission("hytale.mods.outdated.notify")) { + playerRef.sendMessage(Message.translation("server.pluginManager.outOfDatePlugins").color(Color.RED)); + } + } + }); + } + this.loadOrder = PendingLoadPlugin.calculateLoadOrder(pending); this.loading = new Object2ObjectOpenHashMap<>(); pending.forEach((identifier, pendingLoad) -> this.availablePlugins.put(identifier, pendingLoad.getManifest())); - ObjectArrayList var24 = new ObjectArrayList(); + ObjectArrayList> preLoadFutures = new ObjectArrayList<>(); + ObjectArrayList failedBootPlugins = new ObjectArrayList<>(); this.lock.writeLock().lock(); try { @@ -193,26 +226,55 @@ public class PluginManager { for (PendingLoadPlugin pendingLoadPlugin : this.loadOrder) { LOGGER.at(Level.FINE).log("- %s", pendingLoadPlugin.getIdentifier()); - PluginBase plugin = pendingLoadPlugin.load(); - if (plugin != null) { + + try { + PluginBase plugin = pendingLoadPlugin.load(); this.plugins.put(plugin.getIdentifier(), plugin); this.loading.put(plugin.getIdentifier(), plugin); CompletableFuture future = plugin.preLoad(); if (future != null) { - var24.add(future); + preLoadFutures.add(future); } + } catch (ClassNotFoundException var26) { + LOGGER.at(Level.SEVERE).withCause(var26).log("Failed to load plugin %s. Failed to find main class!", pendingLoadPlugin.getPath()); + failedBootPlugins.add(pendingLoadPlugin.getIdentifier()); + } catch (NoSuchMethodException var27) { + LOGGER.at(Level.SEVERE).withCause(var27).log("Failed to load plugin %s. Requires default constructor!", pendingLoadPlugin.getPath()); + failedBootPlugins.add(pendingLoadPlugin.getIdentifier()); + } catch (Throwable var28) { + LOGGER.at(Level.SEVERE).withCause(var28).log("Failed to load plugin %s", pendingLoadPlugin.getPath()); + failedBootPlugins.add(pendingLoadPlugin.getIdentifier()); } } } finally { this.lock.writeLock().unlock(); } - CompletableFuture.allOf(var24.toArray(CompletableFuture[]::new)).join(); + if (!failedBootPlugins.isEmpty() && !Constants.shouldSkipModValidation()) { + StringBuilder sb = new StringBuilder("Failed to boot the following plugins:\n"); - for (PendingLoadPlugin pendingPlugin : this.loadOrder) { - PluginBase plugin = this.loading.get(pendingPlugin.getIdentifier()); - if (plugin != null && !this.setup(plugin)) { - this.loading.remove(pendingPlugin.getIdentifier()); + for (PluginIdentifier failed : failedBootPlugins) { + sb.append(" - ").append(failed).append('\n'); + } + + HytaleServer.get().shutdownServer(ShutdownReason.MOD_ERROR.withMessage(sb.toString().trim())); + } else { + CompletableFuture.allOf(preLoadFutures.toArray(CompletableFuture[]::new)).join(); + boolean hasFailed = false; + + for (PendingLoadPlugin pendingPlugin : this.loadOrder) { + PluginBase plugin = this.loading.get(pendingPlugin.getIdentifier()); + if (plugin != null && !this.setup(plugin)) { + hasFailed = true; + } + } + + if (!Constants.shouldSkipModValidation() && hasFailed) { + StringBuilder sb = new StringBuilder("Failed to setup the following plugins:\n"); + this.collectFailedPlugins(sb); + HytaleServer.get().shutdownServer(ShutdownReason.MOD_ERROR.withMessage(sb.toString().trim())); + } else { + this.loading.values().removeIf(v -> v.getState().isInactive()); } } } @@ -223,16 +285,15 @@ public class PluginManager { throw new IllegalStateException("Expected PluginState.SETUP but found " + this.state); } else { this.state = PluginState.START; + boolean hasFailed = false; for (PendingLoadPlugin pendingPlugin : this.loadOrder) { PluginBase plugin = this.loading.get(pendingPlugin.getIdentifier()); if (plugin != null && !this.start(plugin)) { - this.loading.remove(pendingPlugin.getIdentifier()); + hasFailed = true; } } - this.loadOrder = null; - this.loading = null; StringBuilder sb = new StringBuilder(); for (Entry entry : HytaleServer.get().getConfig().getModConfig().entrySet()) { @@ -241,7 +302,6 @@ public class PluginManager { SemverRange requiredVersion = modConfig.getRequiredVersion(); if (requiredVersion != null && !this.hasPlugin(identifier, requiredVersion)) { sb.append(String.format("%s, Version: %s\n", identifier, modConfig)); - return; } } @@ -249,6 +309,25 @@ public class PluginManager { String msg = "Failed to start server! Missing Mods:\n" + sb; LOGGER.at(Level.SEVERE).log(msg); HytaleServer.get().shutdownServer(ShutdownReason.MISSING_REQUIRED_PLUGIN.withMessage(msg)); + } else if (hasFailed && !Constants.shouldSkipModValidation()) { + sb = new StringBuilder("Failed to start the following plugins:\n"); + this.collectFailedPlugins(sb); + HytaleServer.get().shutdownServer(ShutdownReason.MOD_ERROR.withMessage(sb.toString().trim())); + } else { + this.loadOrder = null; + this.loading = null; + } + } + } + + private void collectFailedPlugins(StringBuilder sb) { + if (this.loading != null) { + for (Entry failed : this.loading.entrySet()) { + if (failed.getValue().getState() == PluginState.FAILED) { + Throwable reasonThrowable = failed.getValue().getFailureCause(); + String reason = reasonThrowable != null ? reasonThrowable.toString() : "Unknown"; + sb.append(" - ").append(failed.getKey()).append(": ").append(reason).append('\n'); + } } } } @@ -288,48 +367,63 @@ public class PluginManager { } private void validatePluginDeps(@Nonnull PendingLoadPlugin pendingLoadPlugin, @Nullable Map pending) { - Semver serverVersion = ManifestUtil.getVersion(); - SemverRange serverVersionRange = pendingLoadPlugin.getManifest().getServerVersion(); - if (serverVersionRange != null && serverVersion != null && !serverVersionRange.satisfies(serverVersion)) { - throw new MissingPluginDependencyException( - String.format("Failed to load '%s' because version of server does not satisfy '%s'! ", pendingLoadPlugin.getIdentifier(), serverVersion) - ); - } else { - for (Entry entry : pendingLoadPlugin.getManifest().getDependencies().entrySet()) { - PluginIdentifier identifier = entry.getKey(); - PluginManifest dependency = null; - if (pending != null) { - PendingLoadPlugin pendingDependency = pending.get(identifier); - if (pendingDependency != null) { - dependency = pendingDependency.getManifest(); - } - } - - if (dependency == null) { - PluginBase loadedBase = this.plugins.get(identifier); - if (loadedBase != null) { - dependency = loadedBase.getManifest(); - } - } - - if (dependency == null) { - throw new MissingPluginDependencyException( - String.format("Failed to load '%s' because the dependency '%s' could not be found!", pendingLoadPlugin.getIdentifier(), identifier) - ); - } - - SemverRange expectedVersion = entry.getValue(); - if (!dependency.getVersion().satisfies(expectedVersion)) { - throw new MissingPluginDependencyException( - String.format( - "Failed to load '%s' because version of dependency '%s'(%s) does not satisfy '%s'!", + String serverVersion = ManifestUtil.getVersion(); + if (!pendingLoadPlugin.getManifest().getGroup().equals("Hytale")) { + String targetServerVersion = pendingLoadPlugin.getManifest().getServerVersion(); + if (targetServerVersion == null || serverVersion != null && !targetServerVersion.equals(serverVersion)) { + if (targetServerVersion != null && !"*".equals(targetServerVersion)) { + LOGGER.at(Level.WARNING) + .log( + "Plugin '%s' targets a different server version %s. You may encounter issues, please check for plugin updates.", pendingLoadPlugin.getIdentifier(), - identifier, - dependency.getVersion(), - expectedVersion - ) - ); + serverVersion + ); + } else { + LOGGER.at(Level.WARNING) + .log( + "Plugin '%s' does not specify a target server version. You may encounter issues, please check for plugin updates. This will be a hard error in the future", + pendingLoadPlugin.getIdentifier() + ); } + + this.hasOutdatedPlugins = true; + } + } + + for (Entry entry : pendingLoadPlugin.getManifest().getDependencies().entrySet()) { + PluginIdentifier identifier = entry.getKey(); + PluginManifest dependency = null; + if (pending != null) { + PendingLoadPlugin pendingDependency = pending.get(identifier); + if (pendingDependency != null) { + dependency = pendingDependency.getManifest(); + } + } + + if (dependency == null) { + PluginBase loadedBase = this.plugins.get(identifier); + if (loadedBase != null) { + dependency = loadedBase.getManifest(); + } + } + + if (dependency == null) { + throw new MissingPluginDependencyException( + String.format("Failed to load '%s' because the dependency '%s' could not be found!", pendingLoadPlugin.getIdentifier(), identifier) + ); + } + + SemverRange expectedVersion = entry.getValue(); + if (!dependency.getVersion().satisfies(expectedVersion)) { + throw new MissingPluginDependencyException( + String.format( + "Failed to load '%s' because version of dependency '%s'(%s) does not satisfy '%s'!", + pendingLoadPlugin.getIdentifier(), + identifier, + dependency.getVersion(), + expectedVersion + ) + ); } } } @@ -376,32 +470,42 @@ public class PluginManager { @Nullable private PendingLoadJavaPlugin loadPendingJavaPlugin(@Nonnull Path file) { try { - URL url = file.toUri().toURL(); - PluginClassLoader pluginClassLoader = this.classLoaders.computeIfAbsent(file, path -> new PluginClassLoader(this, false, url)); - URL resource = pluginClassLoader.findResource("manifest.json"); - if (resource == null) { - LOGGER.at(Level.SEVERE).log("Failed to load pending plugin from '%s'. Failed to load manifest file!", file.toString()); - return null; + PendingLoadJavaPlugin var22; + try (FileSystem fs = FileSystems.newFileSystem(file)) { + Path resource = fs.getPath("manifest.json"); + if (!Files.exists(resource)) { + LOGGER.at(Level.SEVERE).log("Failed to load pending plugin from '%s'. Failed to load manifest file!", file.toString()); + return null; + } + + PluginManifest manifest; + try ( + InputStream stream = Files.newInputStream(resource); + InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8); + ) { + char[] buffer = RawJsonReader.READ_BUFFER.get(); + RawJsonReader rawJsonReader = new RawJsonReader(reader, buffer); + ExtraInfo extraInfo = ExtraInfo.THREAD_LOCAL.get(); + manifest = PluginManifest.CODEC.decodeJson(rawJsonReader, extraInfo); + if (manifest == null) { + LOGGER.at(Level.SEVERE).log("Failed to load pending plugin from '%s'. Failed to decode manifest file!", file.toString()); + return null; + } + + extraInfo.getValidationResults().logOrThrowValidatorExceptions(LOGGER); + } + + URL url = file.toUri().toURL(); + PluginClassLoader pluginClassLoader = this.classLoaders + .computeIfAbsent(file, path -> new PluginClassLoader(this, new PluginIdentifier(manifest), false, url)); + var22 = new PendingLoadJavaPlugin(file, manifest, pluginClassLoader); } - PendingLoadJavaPlugin var11; - try ( - InputStream stream = resource.openStream(); - InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8); - ) { - char[] buffer = RawJsonReader.READ_BUFFER.get(); - RawJsonReader rawJsonReader = new RawJsonReader(reader, buffer); - ExtraInfo extraInfo = ExtraInfo.THREAD_LOCAL.get(); - PluginManifest manifest = PluginManifest.CODEC.decodeJson(rawJsonReader, extraInfo); - extraInfo.getValidationResults().logOrThrowValidatorExceptions(LOGGER); - var11 = new PendingLoadJavaPlugin(file, manifest, pluginClassLoader); - } - - return var11; - } catch (MalformedURLException var16) { - LOGGER.at(Level.SEVERE).withCause(var16).log("Failed to load pending plugin from '%s'. Failed to create URLClassLoader!", file.toString()); - } catch (IOException var17) { - LOGGER.at(Level.SEVERE).withCause(var17).log("Failed to load pending plugin %s. Failed to load manifest file!", file.toString()); + return var22; + } catch (MalformedURLException var17) { + LOGGER.at(Level.SEVERE).withCause(var17).log("Failed to load pending plugin from '%s'. Failed to create URLClassLoader!", file.toString()); + } catch (IOException var18) { + LOGGER.at(Level.SEVERE).withCause(var18).log("Failed to load pending plugin %s. Failed to load manifest file!", file.toString()); } return null; @@ -429,27 +533,36 @@ public class PluginManager { ExtraInfo extraInfo = ExtraInfo.THREAD_LOCAL.get(); PluginManifest manifest = PluginManifest.CODEC.decodeJson(rawJsonReader, extraInfo); extraInfo.getValidationResults().logOrThrowValidatorExceptions(LOGGER); - PendingLoadJavaPlugin plugin; - if (connection instanceof JarURLConnection jarURLConnection) { - URL classpathUrl = jarURLConnection.getJarFileURL(); - Path path = Path.of(classpathUrl.toURI()); - PluginClassLoader pluginClassLoader = this.classLoaders.computeIfAbsent(path, f -> new PluginClassLoader(this, true, classpathUrl)); - plugin = new PendingLoadJavaPlugin(path, manifest, pluginClassLoader); - } else { - URI pluginUri = manifestUrl.toURI().resolve("."); - Path path = Paths.get(pluginUri); - URL classpathUrl = pluginUri.toURL(); - PluginClassLoader pluginClassLoader = this.classLoaders.computeIfAbsent(path, f -> new PluginClassLoader(this, true, classpathUrl)); - plugin = new PendingLoadJavaPlugin(path, manifest, pluginClassLoader); + if (manifest != null) { + PendingLoadJavaPlugin plugin; + if (connection instanceof JarURLConnection jarURLConnection) { + URL classpathUrl = jarURLConnection.getJarFileURL(); + Path path = Path.of(classpathUrl.toURI()); + PluginClassLoader pluginClassLoader = this.classLoaders + .computeIfAbsent(path, f -> new PluginClassLoader(this, new PluginIdentifier(manifest), true, classpathUrl)); + plugin = new PendingLoadJavaPlugin(path, manifest, pluginClassLoader); + } else { + URI pluginUri = manifestUrl.toURI().resolve("."); + Path path = Paths.get(pluginUri); + URL classpathUrl = pluginUri.toURL(); + PluginClassLoader pluginClassLoader = this.classLoaders + .computeIfAbsent(path, f -> new PluginClassLoader(this, new PluginIdentifier(manifest), true, classpathUrl)); + plugin = new PendingLoadJavaPlugin(path, manifest, pluginClassLoader); + } + + LOGGER.at(Level.INFO).log("- %s", plugin.getIdentifier()); + if (this.canLoadOnBoot(plugin)) { + loadPendingPlugin(pending, plugin); + } else { + rejectedBootList.put(plugin.getIdentifier(), plugin.getManifest()); + } + continue; } - LOGGER.at(Level.INFO).log("- %s", plugin.getIdentifier()); - if (this.canLoadOnBoot(plugin)) { - loadPendingPlugin(pending, plugin); - } else { - rejectedBootList.put(plugin.getIdentifier(), plugin.getManifest()); - } + LOGGER.at(Level.SEVERE).log("Failed to load pending plugin from '%s'. Failed to decode manifest file!", manifestUrl); } + + return; } URL manifestsUrl = classLoader.getResource("manifests.json"); @@ -458,17 +571,17 @@ public class PluginManager { InputStream stream = manifestsUrl.openStream(); InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8); ) { - char[] bufferx = RawJsonReader.READ_BUFFER.get(); - RawJsonReader rawJsonReaderx = new RawJsonReader(reader, bufferx); - ExtraInfo extraInfox = ExtraInfo.THREAD_LOCAL.get(); - PluginManifest[] manifests = PluginManifest.ARRAY_CODEC.decodeJson(rawJsonReaderx, extraInfox); - extraInfox.getValidationResults().logOrThrowValidatorExceptions(LOGGER); + char[] buffer = RawJsonReader.READ_BUFFER.get(); + RawJsonReader rawJsonReader = new RawJsonReader(reader, buffer); + ExtraInfo extraInfo = ExtraInfo.THREAD_LOCAL.get(); + PluginManifest[] manifests = PluginManifest.ARRAY_CODEC.decodeJson(rawJsonReader, extraInfo); + extraInfo.getValidationResults().logOrThrowValidatorExceptions(LOGGER); URL url = uri.toURL(); Path path = Paths.get(uri); - PluginClassLoader pluginClassLoader = this.classLoaders.computeIfAbsent(path, f -> new PluginClassLoader(this, true, url)); + PluginClassLoader pluginClassLoader = this.classLoaders.computeIfAbsent(path, f -> new PluginClassLoader(this, null, true, url)); - for (PluginManifest manifestx : manifests) { - PendingLoadJavaPlugin pluginx = new PendingLoadJavaPlugin(path, manifestx, pluginClassLoader); + for (PluginManifest manifest : manifests) { + PendingLoadJavaPlugin pluginx = new PendingLoadJavaPlugin(path, manifest, pluginClassLoader); LOGGER.at(Level.INFO).log("- %s", pluginx.getIdentifier()); if (this.canLoadOnBoot(pluginx)) { loadPendingPlugin(pending, pluginx); @@ -610,7 +723,7 @@ public class PluginManager { continue; } - PluginClassLoader pluginClassLoader = new PluginClassLoader(this, true, uri.toURL()); + PluginClassLoader pluginClassLoader = new PluginClassLoader(this, identifier, true, uri.toURL()); PendingLoadJavaPlugin pluginx = new PendingLoadJavaPlugin(Paths.get(uri), manifestx, pluginClassLoader); manifest = this.load(pluginx); } @@ -632,7 +745,7 @@ public class PluginManager { for (PluginManifest manifest : manifests) { if (new PluginIdentifier(manifest).equals(identifier)) { - PluginClassLoader pluginClassLoader = new PluginClassLoader(this, true, uri.toURL()); + PluginClassLoader pluginClassLoader = new PluginClassLoader(this, identifier, true, uri.toURL()); PendingLoadJavaPlugin pluginx = new PendingLoadJavaPlugin(Paths.get(uri), manifest, pluginClassLoader); return this.load(pluginx); } @@ -733,9 +846,9 @@ public class PluginManager { if (pendingLoadPlugin == null) { return false; } else { - this.validatePluginDeps(pendingLoadPlugin, null); - PluginBase plugin = pendingLoadPlugin.load(); - if (plugin != null) { + try { + this.validatePluginDeps(pendingLoadPlugin, null); + PluginBase plugin = pendingLoadPlugin.load(); this.lock.writeLock().lock(); try { @@ -752,13 +865,23 @@ public class PluginManager { } preload.thenAccept(v -> { - this.setup(plugin); - this.start(plugin); - this.pluginListPageManager.notifyPluginChange(this.plugins, plugin.getIdentifier()); + if (!this.setup(plugin)) { + this.pluginListPageManager.notifyPluginChange(this.plugins, plugin.getIdentifier()); + } else if (!this.start(plugin)) { + this.pluginListPageManager.notifyPluginChange(this.plugins, plugin.getIdentifier()); + } else { + this.pluginListPageManager.notifyPluginChange(this.plugins, plugin.getIdentifier()); + } }); + this.pluginListPageManager.notifyPluginChange(this.plugins, pendingLoadPlugin.getIdentifier()); + } catch (ClassNotFoundException var10) { + LOGGER.at(Level.SEVERE).withCause(var10).log("Failed to load plugin %s. Failed to find main class!", pendingLoadPlugin.getPath()); + } catch (NoSuchMethodException var11) { + LOGGER.at(Level.SEVERE).withCause(var11).log("Failed to load plugin %s. Requires default constructor!", pendingLoadPlugin.getPath()); + } catch (Throwable var12) { + LOGGER.at(Level.SEVERE).withCause(var12).log("Failed to load plugin %s", pendingLoadPlugin.getPath()); } - this.pluginListPageManager.notifyPluginChange(this.plugins, pendingLoadPlugin.getIdentifier()); return false; } } @@ -768,11 +891,16 @@ public class PluginManager { LOGGER.at(Level.FINE).log("Setting up plugin %s", plugin.getIdentifier()); boolean prev = AssetStore.DISABLE_DYNAMIC_DEPENDENCIES; AssetStore.DISABLE_DYNAMIC_DEPENDENCIES = false; - plugin.setup0(); - AssetStore.DISABLE_DYNAMIC_DEPENDENCIES = prev; + + try { + plugin.setup0(); + } finally { + AssetStore.DISABLE_DYNAMIC_DEPENDENCIES = prev; + } + AssetModule.get().initPendingStores(); HytaleServer.get().doneSetup(plugin); - if (plugin.getState() != PluginState.DISABLED) { + if (!plugin.getState().isInactive()) { IEventDispatcher dispatch = HytaleServer.get() .getEventBus() .dispatchFor(PluginSetupEvent.class, (Class)plugin.getClass()); @@ -798,7 +926,7 @@ public class PluginManager { LOGGER.at(Level.FINE).log("Starting plugin %s", plugin.getIdentifier()); plugin.start0(); HytaleServer.get().doneStart(plugin); - if (plugin.getState() != PluginState.DISABLED) { + if (!plugin.getState().isInactive()) { LOGGER.at(Level.INFO).log("Enabled plugin %s", plugin.getIdentifier()); return true; } @@ -819,6 +947,7 @@ public class PluginManager { if (dependency == null || dependency.getState() != requiredState) { LOGGER.at(Level.SEVERE).log(plugin.getName() + " is lacking dependency " + dependencyOnManifest.getName() + " at stage " + stage); LOGGER.at(Level.SEVERE).log(plugin.getName() + " DISABLED!"); + plugin.setFailureCause(new Exception("Missing dependency " + dependencyOnManifest.getName())); return false; } } @@ -828,7 +957,7 @@ public class PluginManager { private static void loadPendingPlugin(@Nonnull Map pending, @Nonnull PendingLoadPlugin plugin) { if (pending.putIfAbsent(plugin.getIdentifier(), plugin) != null) { - throw new IllegalArgumentException("Tried to load duplicate plugin"); + throw new IllegalArgumentException("Tried to load duplicate plugin: " + plugin.getIdentifier()); } else { for (PendingLoadPlugin subPlugin : plugin.createSubPendingLoadPlugins()) { loadPendingPlugin(pending, subPlugin); diff --git a/src/com/hypixel/hytale/server/core/plugin/PluginState.java b/src/com/hypixel/hytale/server/core/plugin/PluginState.java index 7a6967f2..0f06d5ca 100644 --- a/src/com/hypixel/hytale/server/core/plugin/PluginState.java +++ b/src/com/hypixel/hytale/server/core/plugin/PluginState.java @@ -6,5 +6,13 @@ public enum PluginState { START, ENABLED, SHUTDOWN, - DISABLED; + DISABLED, + FAILED; + + public boolean isInactive() { + return switch (this) { + case NONE, DISABLED, FAILED -> true; + default -> false; + }; + } } diff --git a/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadJavaPlugin.java b/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadJavaPlugin.java index 6bb39ec0..9ccea665 100644 --- a/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadJavaPlugin.java +++ b/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadJavaPlugin.java @@ -8,7 +8,6 @@ import com.hypixel.hytale.server.core.plugin.PluginClassLoader; import com.hypixel.hytale.server.core.plugin.PluginManager; import java.lang.reflect.Constructor; import java.nio.file.Path; -import java.util.logging.Level; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -33,28 +32,18 @@ public class PendingLoadJavaPlugin extends PendingLoadPlugin { return this.urlClassLoader.isInServerClassPath(); } - @Nullable - public JavaPlugin load() { - try { - PluginManifest manifest = this.getManifest(); - Class mainClass = this.urlClassLoader.loadLocalClass(manifest.getMain()); - if (JavaPlugin.class.isAssignableFrom(mainClass)) { - Constructor constructor = mainClass.getConstructor(JavaPluginInit.class); - Path dataDirectory = PluginManager.MODS_PATH.resolve(manifest.getGroup() + "_" + manifest.getName()); - JavaPluginInit init = new JavaPluginInit(manifest, dataDirectory, this.getPath(), this.urlClassLoader); - return (JavaPlugin)constructor.newInstance(init); - } - + @Nonnull + public JavaPlugin load() throws Exception { + PluginManifest manifest = this.getManifest(); + Class mainClass = this.urlClassLoader.loadLocalClass(manifest.getMain()); + if (JavaPlugin.class.isAssignableFrom(mainClass)) { + Constructor constructor = mainClass.getConstructor(JavaPluginInit.class); + Path dataDirectory = PluginManager.MODS_PATH.resolve(manifest.getGroup() + "_" + manifest.getName()); + JavaPluginInit init = new JavaPluginInit(manifest, dataDirectory, this.getPath(), this.urlClassLoader); + return (JavaPlugin)constructor.newInstance(init); + } else { throw new ClassCastException(manifest.getMain() + " does not extend JavaPlugin"); - } catch (ClassNotFoundException var6) { - LOGGER.at(Level.SEVERE).withCause(var6).log("Failed to load plugin %s. Failed to find main class!", this.getPath()); - } catch (NoSuchMethodException var7) { - LOGGER.at(Level.SEVERE).withCause(var7).log("Failed to load plugin %s. Requires default constructor!", this.getPath()); - } catch (Throwable var8) { - LOGGER.at(Level.SEVERE).withCause(var8).log("Failed to load plugin %s", this.getPath()); } - - return null; } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadPlugin.java b/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadPlugin.java index d942361a..1398cd43 100644 --- a/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadPlugin.java +++ b/src/com/hypixel/hytale/server/core/plugin/pending/PendingLoadPlugin.java @@ -48,8 +48,8 @@ public abstract class PendingLoadPlugin { public abstract PendingLoadPlugin createSubPendingLoadPlugin(PluginManifest var1); - @Nullable - public abstract PluginBase load(); + @Nonnull + public abstract PluginBase load() throws Exception; @Nonnull public List createSubPendingLoadPlugins() { diff --git a/src/com/hypixel/hytale/server/core/prefab/PrefabStore.java b/src/com/hypixel/hytale/server/core/prefab/PrefabStore.java index 1cb76f17..c73f9095 100644 --- a/src/com/hypixel/hytale/server/core/prefab/PrefabStore.java +++ b/src/com/hypixel/hytale/server/core/prefab/PrefabStore.java @@ -2,6 +2,7 @@ package com.hypixel.hytale.server.core.prefab; import com.hypixel.hytale.assetstore.AssetPack; import com.hypixel.hytale.common.plugin.PluginManifest; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.server.core.asset.AssetModule; import com.hypixel.hytale.server.core.prefab.config.SelectionPrefabSerializer; import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection; @@ -34,9 +35,19 @@ public class PrefabStore { private PrefabStore() { } + @Nonnull + private static Path resolvePrefabKey(@Nonnull Path basePath, @Nonnull String key) { + Path resolved = PathUtil.resolvePathWithinDir(basePath, key); + if (resolved == null) { + throw new PrefabLoadException(PrefabLoadException.Type.NOT_FOUND); + } else { + return resolved; + } + } + @Nonnull public BlockSelection getServerPrefab(@Nonnull String key) { - return this.getPrefab(this.getServerPrefabsPath().resolve(key)); + return this.getPrefab(resolvePrefabKey(this.getServerPrefabsPath(), key)); } @Nonnull @@ -56,7 +67,7 @@ public class PrefabStore { @Nonnull public Map getServerPrefabDir(@Nonnull String key) { - return this.getPrefabDir(this.getServerPrefabsPath().resolve(key)); + return this.getPrefabDir(resolvePrefabKey(this.getServerPrefabsPath(), key)); } @Nonnull @@ -80,7 +91,7 @@ public class PrefabStore { } public void saveWorldGenPrefab(@Nonnull String key, @Nonnull BlockSelection prefab, boolean overwrite) { - this.savePrefab(this.getWorldGenPrefabsPath().resolve(key), prefab, overwrite); + this.savePrefab(resolvePrefabKey(this.getWorldGenPrefabsPath(), key), prefab, overwrite); } public void savePrefab(@Nonnull Path path, @Nonnull BlockSelection prefab, boolean overwrite) { @@ -112,11 +123,17 @@ public class PrefabStore { @Nonnull public Path getWorldGenPrefabsPath(@Nullable String name) { name = name == null ? "Default" : name; - return Universe.getWorldGenPath().resolve(name).resolve("Prefabs"); + Path worldGenPath = Universe.getWorldGenPath(); + Path resolved = PathUtil.resolvePathWithinDir(worldGenPath, name); + if (resolved == null) { + throw new IllegalArgumentException("Invalid world gen name: " + name); + } else { + return resolved.resolve("Prefabs"); + } } public void saveServerPrefab(@Nonnull String key, @Nonnull BlockSelection prefab, boolean overwrite) { - this.savePrefab(this.getServerPrefabsPath().resolve(key), prefab, overwrite); + this.savePrefab(resolvePrefabKey(this.getServerPrefabsPath(), key), prefab, overwrite); } @Nonnull @@ -147,8 +164,8 @@ public class PrefabStore { public BlockSelection getAssetPrefabFromAnyPack(@Nonnull String key) { for (AssetPack pack : AssetModule.get().getAssetPacks()) { Path prefabsPath = this.getAssetPrefabsPathForPack(pack); - Path prefabPath = prefabsPath.resolve(key); - if (Files.exists(prefabPath)) { + Path prefabPath = PathUtil.resolvePathWithinDir(prefabsPath, key); + if (prefabPath != null && Files.exists(prefabPath)) { return this.getPrefab(prefabPath); } } @@ -160,8 +177,8 @@ public class PrefabStore { public Path findAssetPrefabPath(@Nonnull String key) { for (AssetPack pack : AssetModule.get().getAssetPacks()) { Path prefabsPath = this.getAssetPrefabsPathForPack(pack); - Path prefabPath = prefabsPath.resolve(key); - if (Files.exists(prefabPath)) { + Path prefabPath = PathUtil.resolvePathWithinDir(prefabsPath, key); + if (prefabPath != null && Files.exists(prefabPath)) { return prefabPath; } } @@ -185,12 +202,12 @@ public class PrefabStore { @Nonnull public BlockSelection getAssetPrefab(@Nonnull String key) { - return this.getPrefab(this.getAssetPrefabsPath().resolve(key)); + return this.getPrefab(resolvePrefabKey(this.getAssetPrefabsPath(), key)); } @Nonnull public Map getAssetPrefabDir(@Nonnull String key) { - return this.getPrefabDir(this.getAssetPrefabsPath().resolve(key)); + return this.getPrefabDir(resolvePrefabKey(this.getAssetPrefabsPath(), key)); } public void saveAssetPrefab(@Nonnull String key, @Nonnull BlockSelection prefab) { @@ -198,7 +215,7 @@ public class PrefabStore { } public void saveAssetPrefab(@Nonnull String key, @Nonnull BlockSelection prefab, boolean overwrite) { - this.savePrefab(this.getAssetPrefabsPath().resolve(key), prefab, overwrite); + this.savePrefab(resolvePrefabKey(this.getAssetPrefabsPath(), key), prefab, overwrite); } @Nonnull @@ -208,12 +225,12 @@ public class PrefabStore { @Nonnull public BlockSelection getWorldGenPrefab(@Nonnull Path prefabsPath, @Nonnull String key) { - return this.getPrefab(prefabsPath.resolve(key)); + return this.getPrefab(resolvePrefabKey(prefabsPath, key)); } @Nonnull public Map getWorldGenPrefabDir(@Nonnull String key) { - return this.getPrefabDir(this.getWorldGenPrefabsPath().resolve(key)); + return this.getPrefabDir(resolvePrefabKey(this.getWorldGenPrefabsPath(), key)); } public void saveWorldGenPrefab(@Nonnull String key, @Nonnull BlockSelection prefab) { diff --git a/src/com/hypixel/hytale/server/core/prefab/selection/buffer/PrefabLoader.java b/src/com/hypixel/hytale/server/core/prefab/selection/buffer/PrefabLoader.java index 1697cf8b..26319311 100644 --- a/src/com/hypixel/hytale/server/core/prefab/selection/buffer/PrefabLoader.java +++ b/src/com/hypixel/hytale/server/core/prefab/selection/buffer/PrefabLoader.java @@ -1,5 +1,6 @@ package com.hypixel.hytale.server.core.prefab.selection.buffer; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.server.core.util.io.FileUtil; import java.io.File; import java.io.IOException; @@ -34,6 +35,10 @@ public class PrefabLoader { resolvePrefabFolder(rootFolder, prefabName, pathConsumer); } else { Path prefabPath = rootFolder.resolve(prefabName.replace('.', File.separatorChar) + ".prefab.json"); + if (!PathUtil.isChildOf(rootFolder, prefabPath)) { + throw new IllegalArgumentException("Invalid prefab name: " + prefabName); + } + if (!Files.exists(prefabPath)) { return; } @@ -45,7 +50,9 @@ public class PrefabLoader { public static void resolvePrefabFolder(@Nonnull Path rootFolder, @Nonnull String prefabName, @Nonnull final Consumer pathConsumer) throws IOException { String prefabDirectory = prefabName.substring(0, prefabName.length() - 2); Path directoryPath = rootFolder.resolve(prefabDirectory.replace('.', File.separatorChar)); - if (Files.exists(directoryPath)) { + if (!PathUtil.isChildOf(rootFolder, directoryPath)) { + throw new IllegalArgumentException("Invalid prefab name: " + prefabName); + } else if (Files.exists(directoryPath)) { if (!Files.isDirectory(directoryPath)) { throw new NotDirectoryException(directoryPath.toString()); } else { diff --git a/src/com/hypixel/hytale/server/core/ui/browser/ServerFileBrowser.java b/src/com/hypixel/hytale/server/core/ui/browser/ServerFileBrowser.java index ad82b111..bb2dc132 100644 --- a/src/com/hypixel/hytale/server/core/ui/browser/ServerFileBrowser.java +++ b/src/com/hypixel/hytale/server/core/ui/browser/ServerFileBrowser.java @@ -208,8 +208,9 @@ public class ServerFileBrowser { return this.handleAssetPackNavigation(fileName); } else { if (this.config.enableDirectoryNav()) { - Path targetPath = this.root.resolve(this.currentDir.toString()).resolve(fileName); - if (Files.isDirectory(targetPath)) { + Path currentPath = this.root.resolve(this.currentDir.toString()); + Path targetPath = PathUtil.resolvePathWithinDir(currentPath, fileName); + if (targetPath != null && Files.isDirectory(targetPath) && PathUtil.isChildOf(this.root, targetPath)) { this.currentDir = PathUtil.relativize(this.root, targetPath); return true; } @@ -327,8 +328,8 @@ public class ServerFileBrowser { if (packx != null) { Path packSubPath = this.getAssetPackSubPath(packx); if (packSubPath != null) { - Path targetDir = subDir.isEmpty() ? packSubPath : packSubPath.resolve(subDir); - if (Files.isDirectory(targetDir)) { + Path targetDir = subDir.isEmpty() ? packSubPath : PathUtil.resolvePathWithinDir(packSubPath, subDir); + if (targetDir != null && Files.isDirectory(targetDir)) { try (DirectoryStream stream = Files.newDirectoryStream(targetDir)) { for (Path file : stream) { String fileName = file.getFileName().toString(); @@ -382,8 +383,8 @@ public class ServerFileBrowser { if (packx != null) { Path packSubPath = this.getAssetPackSubPath(packx); if (packSubPath != null) { - Path searchRoot = subDir.isEmpty() ? packSubPath : packSubPath.resolve(subDir); - if (Files.isDirectory(searchRoot)) { + Path searchRoot = subDir.isEmpty() ? packSubPath : PathUtil.resolvePathWithinDir(packSubPath, subDir); + if (searchRoot != null && Files.isDirectory(searchRoot)) { this.searchInAssetPackDirectory(searchRoot, packName, subDir, allResults); } } @@ -472,18 +473,24 @@ public class ServerFileBrowser { if (packSubPath == null) { return false; } else { - Path targetDir = subDir.isEmpty() ? packSubPath : packSubPath.resolve(subDir); - Path targetPath = targetDir.resolve(fileName); - if (Files.isDirectory(targetPath)) { - if (this.isTerminalDirectory(targetPath)) { - return false; - } else { - String newPath = subDir.isEmpty() ? packName + "/" + fileName : packName + "/" + subDir + "/" + fileName; - this.currentDir = Paths.get(newPath); - return true; - } - } else { + Path targetDir = subDir.isEmpty() ? packSubPath : PathUtil.resolvePathWithinDir(packSubPath, subDir); + if (targetDir == null) { return false; + } else { + Path targetPath = PathUtil.resolvePathWithinDir(targetDir, fileName); + if (targetPath == null) { + return false; + } else if (Files.isDirectory(targetPath)) { + if (this.isTerminalDirectory(targetPath)) { + return false; + } else { + String newPath = subDir.isEmpty() ? packName + "/" + fileName : packName + "/" + subDir + "/" + fileName; + this.currentDir = Paths.get(newPath); + return true; + } + } else { + return false; + } } } } @@ -535,7 +542,7 @@ public class ServerFileBrowser { if (packSubPath == null) { return null; } else { - return subPath.isEmpty() ? packSubPath : packSubPath.resolve(subPath); + return subPath.isEmpty() ? packSubPath : PathUtil.resolvePathWithinDir(packSubPath, subPath); } } } else { @@ -573,7 +580,12 @@ public class ServerFileBrowser { } public void setCurrentDir(@Nonnull Path currentDir) { - this.currentDir = currentDir; + Path resolved = this.root.resolve(currentDir.toString()); + if (!PathUtil.isChildOf(this.root, resolved)) { + throw new IllegalArgumentException("Invalid path"); + } else { + this.currentDir = currentDir; + } } @Nonnull @@ -594,7 +606,7 @@ public class ServerFileBrowser { public void navigateTo(@Nonnull Path relativePath) { Path targetPath = this.root.resolve(this.currentDir.toString()).resolve(relativePath.toString()); - if (targetPath.normalize().startsWith(this.root.normalize())) { + if (PathUtil.isChildOf(this.root, targetPath)) { if (Files.isDirectory(targetPath)) { this.currentDir = PathUtil.relativize(this.root, targetPath); } @@ -624,18 +636,6 @@ public class ServerFileBrowser { return this.config; } - @Nullable - public Path resolveSecure(@Nonnull String relativePath) { - Path resolved = this.root.resolve(relativePath); - return !resolved.normalize().startsWith(this.root.normalize()) ? null : resolved; - } - - @Nullable - public Path resolveFromCurrent(@Nonnull String fileName) { - Path resolved = this.root.resolve(this.currentDir.toString()).resolve(fileName); - return !resolved.normalize().startsWith(this.root.normalize()) ? null : resolved; - } - @Nullable private Path findConfigRoot(@Nonnull String pathStr) { for (FileBrowserConfig.RootEntry rootEntry : this.config.roots()) { diff --git a/src/com/hypixel/hytale/server/core/universe/Universe.java b/src/com/hypixel/hytale/server/core/universe/Universe.java index 0cfad631..0ecd55ac 100644 --- a/src/com/hypixel/hytale/server/core/universe/Universe.java +++ b/src/com/hypixel/hytale/server/core/universe/Universe.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.common.plugin.PluginIdentifier; import com.hypixel.hytale.common.plugin.PluginManifest; import com.hypixel.hytale.common.semver.SemverRange; import com.hypixel.hytale.common.util.CompletableFutureUtil; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.component.ComponentRegistryProxy; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Holder; @@ -143,6 +144,8 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv private ComponentType playerRefComponentType; @Nonnull private final Path path = Constants.UNIVERSE_PATH; + private final Path worldsPath = this.path.resolve("worlds"); + private final Path worldsDeletedPath = this.worldsPath.resolveSibling("worlds-deleted"); @Nonnull private final Map players = new ConcurrentHashMap<>(); @Nonnull @@ -294,8 +297,8 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv LEGACY_BLOCK_ID_MAP = Collections.unmodifiableMap(map); } - } catch (IOException var14) { - this.getLogger().at(Level.SEVERE).withCause(var14).log("Failed to delete blockIdMap.json"); + } catch (IOException var15) { + this.getLogger().at(Level.SEVERE).withCause(var15).log("Failed to delete blockIdMap.json"); } if (Options.getOptionSet().has(Options.BARE)) { @@ -305,16 +308,23 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv ObjectArrayList> loadingWorlds = new ObjectArrayList<>(); try { - Path worldsPath = this.path.resolve("worlds"); - Files.createDirectories(worldsPath); + if (Files.exists(this.worldsDeletedPath)) { + FileUtil.deleteDirectory(this.worldsDeletedPath); + } + } catch (Throwable var14) { + throw new RuntimeException("Failed to complete deletion of " + this.worldsDeletedPath.toAbsolutePath(), var14); + } - try (DirectoryStream stream = Files.newDirectoryStream(worldsPath)) { + try { + Files.createDirectories(this.worldsPath); + + try (DirectoryStream stream = Files.newDirectoryStream(this.worldsPath)) { for (Path file : stream) { if (HytaleServer.get().isShuttingDown()) { return; } - if (!file.equals(worldsPath) && Files.isDirectory(file)) { + if (!file.equals(this.worldsPath) && Files.isDirectory(file)) { String name = file.getFileName().toString(); if (this.getWorld(name) == null) { loadingWorlds.add(this.loadWorldFromStart(file, name).exceptionally(throwable -> { @@ -386,7 +396,7 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv } public boolean isWorldLoadable(@Nonnull String name) { - Path savePath = this.path.resolve("worlds").resolve(name); + Path savePath = this.validateWorldPath(name); return Files.isDirectory(savePath) && (Files.exists(savePath.resolve("config.bson")) || Files.exists(savePath.resolve("config.json"))); } @@ -405,7 +415,7 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv } else if (this.isWorldLoadable(name)) { throw new IllegalArgumentException("World " + name + " already exists on disk!"); } else { - Path savePath = this.path.resolve("worlds").resolve(name); + Path savePath = this.validateWorldPath(name); return this.worldConfigProvider.load(savePath, name).thenCompose(worldConfig -> { if (generatorType != null && !"default".equals(generatorType)) { BuilderCodec providerCodec = IWorldGenProvider.CODEC.getCodecFor(generatorType); @@ -434,6 +444,15 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv } } + public Path validateWorldPath(@Nonnull String name) { + Path savePath = PathUtil.resolvePathWithinDir(this.worldsPath, name); + if (savePath == null) { + throw new IllegalArgumentException("World " + name + " contains invalid characters!"); + } else { + return savePath; + } + } + @Nonnull @CheckReturnValue public CompletableFuture makeWorld(@Nonnull String name, @Nonnull Path savePath, @Nonnull WorldConfig worldConfig) { @@ -443,66 +462,70 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv @Nonnull @CheckReturnValue public CompletableFuture makeWorld(@Nonnull String name, @Nonnull Path savePath, @Nonnull WorldConfig worldConfig, boolean start) { - Map map = worldConfig.getRequiredPlugins(); - if (map != null) { - PluginManager pluginManager = PluginManager.get(); + if (!PathUtil.isChildOf(this.worldsPath, savePath) && !PathUtil.isInTrustedRoot(savePath)) { + throw new IllegalArgumentException("Invalid path"); + } else { + Map map = worldConfig.getRequiredPlugins(); + if (map != null) { + PluginManager pluginManager = PluginManager.get(); - for (Entry entry : map.entrySet()) { - if (!pluginManager.hasPlugin(entry.getKey(), entry.getValue())) { - this.getLogger().at(Level.SEVERE).log("Failed to load world! Missing plugin: %s, Version: %s", entry.getKey(), entry.getValue()); - throw new IllegalStateException("Missing plugin"); + for (Entry entry : map.entrySet()) { + if (!pluginManager.hasPlugin(entry.getKey(), entry.getValue())) { + this.getLogger().at(Level.SEVERE).log("Failed to load world! Missing plugin: %s, Version: %s", entry.getKey(), entry.getValue()); + throw new IllegalStateException("Missing plugin"); + } } } - } - if (this.worlds.containsKey(name)) { - throw new IllegalArgumentException("World " + name + " already exists!"); - } else { - return CompletableFuture.supplyAsync( - SneakyThrow.sneakySupplier( - () -> { - World world = new World(name, savePath, worldConfig); - AddWorldEvent event = HytaleServer.get().getEventBus().dispatchFor(AddWorldEvent.class, name).dispatch(new AddWorldEvent(world)); - if (!event.isCancelled() && !HytaleServer.get().isShuttingDown()) { - World oldWorldByName = this.worlds.putIfAbsent(name.toLowerCase(), world); - if (oldWorldByName != null) { - throw new ConcurrentModificationException( - "World with name " + name + " already exists but didn't before! Looks like you have a race condition." - ); - } else { - World oldWorldByUuid = this.worldsByUuid.putIfAbsent(worldConfig.getUuid(), world); - if (oldWorldByUuid != null) { + if (this.worlds.containsKey(name)) { + throw new IllegalArgumentException("World " + name + " already exists!"); + } else { + return CompletableFuture.supplyAsync( + SneakyThrow.sneakySupplier( + () -> { + World world = new World(name, savePath, worldConfig); + AddWorldEvent event = HytaleServer.get().getEventBus().dispatchFor(AddWorldEvent.class, name).dispatch(new AddWorldEvent(world)); + if (!event.isCancelled() && !HytaleServer.get().isShuttingDown()) { + World oldWorldByName = this.worlds.putIfAbsent(name.toLowerCase(), world); + if (oldWorldByName != null) { throw new ConcurrentModificationException( - "World with UUID " + worldConfig.getUuid() + " already exists but didn't before! Looks like you have a race condition." + "World with name " + name + " already exists but didn't before! Looks like you have a race condition." ); } else { - return world; + World oldWorldByUuid = this.worldsByUuid.putIfAbsent(worldConfig.getUuid(), world); + if (oldWorldByUuid != null) { + throw new ConcurrentModificationException( + "World with UUID " + worldConfig.getUuid() + " already exists but didn't before! Looks like you have a race condition." + ); + } else { + return world; + } } + } else { + throw new WorldLoadCancelledException(); } - } else { - throw new WorldLoadCancelledException(); } - } + ) ) - ) - .thenCompose(World::init) - .thenCompose( - world -> !Options.getOptionSet().has(Options.MIGRATIONS) && start - ? world.start().thenApply(v -> world) - : CompletableFuture.completedFuture(world) - ) - .whenComplete((world, throwable) -> { - if (throwable != null) { - String nameLower = name.toLowerCase(); - if (this.worlds.containsKey(nameLower)) { - try { - this.removeWorldExceptionally(name); - } catch (Exception var6x) { - this.getLogger().at(Level.WARNING).withCause(var6x).log("Failed to clean up world '%s' after init failure", name); + .thenCompose(World::init) + .thenCompose( + world -> !Options.getOptionSet().has(Options.MIGRATIONS) && start + ? world.start().thenApply(v -> world) + : CompletableFuture.completedFuture(world) + ) + .whenComplete((world, throwable) -> { + if (throwable != null) { + String nameLower = name.toLowerCase(); + if (this.worlds.containsKey(nameLower)) { + try { + this.removeWorldExceptionally(name, Map.of()); + } catch (Exception var6x) { + this.getLogger().at(Level.WARNING).withCause(var6x).log("Failed to clean up world '%s' after init failure", name); + } } } - } - }); + }); + } } } @@ -525,7 +548,7 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv if (this.worlds.containsKey(name)) { throw new IllegalArgumentException("World " + name + " already loaded!"); } else { - Path savePath = this.path.resolve("worlds").resolve(name); + Path savePath = this.validateWorldPath(name); if (!Files.isDirectory(savePath)) { throw new IllegalArgumentException("World " + name + " does not exist!"); } else { @@ -572,7 +595,11 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv this.worlds.remove(nameLower); this.worldsByUuid.remove(world.getWorldConfig().getUuid()); if (world.isAlive()) { - world.stopIndividualWorld(); + if (world.isInThread()) { + world.stopIndividualWorld(); + } else { + CompletableFuture.runAsync(world::stopIndividualWorld).join(); + } } world.validateDeleteOnRemove(); @@ -581,7 +608,7 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv } } - public void removeWorldExceptionally(@Nonnull String name) { + public void removeWorldExceptionally(@Nonnull String name, Map players) { Objects.requireNonNull(name, "Name can't be null!"); this.getLogger().at(Level.INFO).log("Removing world exceptionally: %s", name); String nameLower = name.toLowerCase(); @@ -596,7 +623,11 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv this.worlds.remove(nameLower); this.worldsByUuid.remove(world.getWorldConfig().getUuid()); if (world.isAlive()) { - world.stopIndividualWorld(); + if (world.isInThread()) { + world.stopIndividualWorld(players); + } else { + CompletableFuture.runAsync(() -> world.stopIndividualWorld(players)).join(); + } } world.validateDeleteOnRemove(); @@ -608,6 +639,14 @@ public class Universe extends JavaPlugin implements IMessageReceiver, MetricProv return this.path; } + public Path getWorldsPath() { + return this.worldsPath; + } + + public Path getWorldsDeletedPath() { + return this.worldsDeletedPath; + } + @Nonnull public Map getWorlds() { return this.unmodifiableWorlds; diff --git a/src/com/hypixel/hytale/server/core/universe/datastore/DiskDataStore.java b/src/com/hypixel/hytale/server/core/universe/datastore/DiskDataStore.java index e44819ea..4cf60865 100644 --- a/src/com/hypixel/hytale/server/core/universe/datastore/DiskDataStore.java +++ b/src/com/hypixel/hytale/server/core/universe/datastore/DiskDataStore.java @@ -3,6 +3,7 @@ package com.hypixel.hytale.server.core.universe.datastore; import com.hypixel.hytale.codec.ExtraInfo; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.util.RawJsonReader; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.util.BsonUtil; @@ -33,20 +34,26 @@ public class DiskDataStore implements DataStore { public DiskDataStore(@Nonnull String path, BuilderCodec codec) { this.logger = HytaleLogger.get("DataStore|" + path); - this.path = Universe.get().getPath().resolve(path); - this.codec = codec; - if (Files.isDirectory(this.path)) { - try (DirectoryStream paths = Files.newDirectoryStream(this.path, "*.bson")) { - for (Path oldPath : paths) { - Path newPath = getPathFromId(this.path, getIdFromPath(oldPath)); + Path universePath = Universe.get().getPath(); + Path resolved = PathUtil.resolvePathWithinDir(universePath, path); + if (resolved == null) { + throw new IllegalStateException("Data store path must be within universe directory: " + path); + } else { + this.path = resolved; + this.codec = codec; + if (Files.isDirectory(this.path)) { + try (DirectoryStream paths = Files.newDirectoryStream(this.path, "*.bson")) { + for (Path oldPath : paths) { + Path newPath = getPathFromId(this.path, getIdFromPath(oldPath)); - try { - Files.move(oldPath, newPath); - } catch (IOException var9) { + try { + Files.move(oldPath, newPath); + } catch (IOException var11) { + } } + } catch (IOException var13) { + this.logger.at(Level.SEVERE).withCause(var13).log("Failed to migrate files form .bson to .json!"); } - } catch (IOException var11) { - this.logger.at(Level.SEVERE).withCause(var11).log("Failed to migrate files form .bson to .json!"); } } } @@ -126,12 +133,20 @@ public class DiskDataStore implements DataStore { @Nonnull protected static Path getPathFromId(@Nonnull Path path, String id) { - return path.resolve(id + ".json"); + if (!PathUtil.isValidName(id)) { + throw new IllegalArgumentException("Invalid ID: " + id); + } else { + return path.resolve(id + ".json"); + } } @Nonnull protected static Path getBackupPathFromId(@Nonnull Path path, String id) { - return path.resolve(id + ".json.bak"); + if (!PathUtil.isValidName(id)) { + throw new IllegalArgumentException("Invalid ID: " + id); + } else { + return path.resolve(id + ".json.bak"); + } } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/universe/playerdata/DiskPlayerStorageProvider.java b/src/com/hypixel/hytale/server/core/universe/playerdata/DiskPlayerStorageProvider.java index 391df204..fe4e3fbb 100644 --- a/src/com/hypixel/hytale/server/core/universe/playerdata/DiskPlayerStorageProvider.java +++ b/src/com/hypixel/hytale/server/core/universe/playerdata/DiskPlayerStorageProvider.java @@ -24,7 +24,7 @@ import org.bson.BsonDocument; public class DiskPlayerStorageProvider implements PlayerStorageProvider { public static final String ID = "Disk"; public static final BuilderCodec CODEC = BuilderCodec.builder(DiskPlayerStorageProvider.class, DiskPlayerStorageProvider::new) - .append(new KeyedCodec<>("Path", Codec.STRING), (o, s) -> o.path = PathUtil.get(s), o -> o.path.toString()) + .append(new KeyedCodec<>("Path", Codec.STRING), (o, s) -> o.path = Path.of(s), o -> o.path.toString()) .add() .build(); @Nonnull @@ -38,7 +38,11 @@ public class DiskPlayerStorageProvider implements PlayerStorageProvider { @Nonnull @Override public PlayerStorage getPlayerStorage() { - return new DiskPlayerStorageProvider.DiskPlayerStorage(this.path); + if (!PathUtil.isInTrustedRoot(this.path)) { + throw new IllegalStateException("Player storage path must be within a trusted directory: " + this.path); + } else { + return new DiskPlayerStorageProvider.DiskPlayerStorage(this.path); + } } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/universe/world/SoundUtil.java b/src/com/hypixel/hytale/server/core/universe/world/SoundUtil.java index c4d5b640..f9b52382 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/SoundUtil.java +++ b/src/com/hypixel/hytale/server/core/universe/world/SoundUtil.java @@ -2,13 +2,17 @@ package com.hypixel.hytale.server.core.universe.world; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.spatial.SpatialResource; import com.hypixel.hytale.math.vector.Vector3d; +import com.hypixel.hytale.protocol.ItemSoundEvent; import com.hypixel.hytale.protocol.Position; import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.protocol.packets.world.PlaySoundEvent2D; import com.hypixel.hytale.protocol.packets.world.PlaySoundEvent3D; import com.hypixel.hytale.protocol.packets.world.PlaySoundEventEntity; +import com.hypixel.hytale.server.core.asset.type.item.config.Item; +import com.hypixel.hytale.server.core.asset.type.itemsound.config.ItemSoundSet; import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.EntityUtils; @@ -22,6 +26,21 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; public class SoundUtil { + public static void playItemSoundEvent( + @Nonnull Ref ref, @Nonnull Store store, @Nonnull Item item, @Nonnull ItemSoundEvent itemSoundEvent + ) { + ItemSoundSet soundSet = ItemSoundSet.getAssetMap().getAsset(item.getItemSoundSetIndex()); + if (soundSet != null) { + String soundEventId = soundSet.getSoundEventIds().get(itemSoundEvent); + if (soundEventId != null) { + int soundEventIndex = SoundEvent.getAssetMap().getIndex(soundEventId); + if (soundEventIndex != 0) { + playSoundEvent2d(ref, soundEventIndex, SoundCategory.UI, store); + } + } + } + } + public static void playSoundEventEntity(int soundEventIndex, int networkId, @Nonnull ComponentAccessor componentAccessor) { playSoundEventEntity(soundEventIndex, networkId, 1.0F, 1.0F, componentAccessor); } diff --git a/src/com/hypixel/hytale/server/core/universe/world/World.java b/src/com/hypixel/hytale/server/core/universe/world/World.java index ce02880b..73fd471d 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/World.java +++ b/src/com/hypixel/hytale/server/core/universe/world/World.java @@ -83,7 +83,9 @@ import com.hypixel.hytale.server.core.util.io.FileUtil; import com.hypixel.hytale.server.core.util.thread.TickingThread; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.awt.Color; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -98,6 +100,7 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; @@ -252,21 +255,55 @@ public class World extends TickingThread implements Executor, ExecutorMetricsReg } public void stopIndividualWorld() { + this.stopIndividualWorld(this.players); + } + + public void stopIndividualWorld(Map players) { this.logger.at(Level.INFO).log("Removing individual world: %s", this.name); World defaultWorld = Universe.get().getDefaultWorld(); - if (defaultWorld != null) { - this.drainPlayersTo(defaultWorld).join(); + if (defaultWorld != null && !defaultWorld.equals(this)) { + Message message; + if (this.getFailureException() == null) { + message = Message.translation("server.universe.worldRemoved"); + } else if (this.getPossibleFailureCause() == null) { + message = Message.translation("server.universe.worldCrash.unknown"); + } else { + message = Message.translation("server.universe.worldCrash.mod").param("mod", this.getPossibleFailureCause().toString()); + } + + message.color(Color.RED); + + for (PlayerRef playerRef : players.values()) { + playerRef.sendMessage(message); + } + + if (this.isInThread()) { + this.drainPlayersTo(defaultWorld, players.values()).join(); + } else { + CompletableFuture.>supplyAsync(() -> this.drainPlayersTo(defaultWorld, players.values()), this) + .thenCompose(v -> (CompletionStage)v) + .join(); + } } else { - for (PlayerRef playerRef : this.players.values()) { - playerRef.getPacketHandler().disconnect("The world you were in was shutdown and there was no default world to move you to!"); + String messagex; + if (this.getFailureException() == null) { + messagex = "The world you were on was removed"; + } else if (this.getPossibleFailureCause() == null) { + messagex = "The world you were on has crashed"; + } else { + messagex = "The world you were on has crashed (possibly caused by " + this.getPossibleFailureCause() + ")"; + } + + for (PlayerRef playerRef : players.values()) { + playerRef.getPacketHandler().disconnect(messagex); } } if (this.alive.getAndSet(false)) { try { super.stop(); - } catch (Throwable var4) { - this.logger.at(Level.SEVERE).withCause(var4).log("Exception while shutting down world:"); + } catch (Throwable var6) { + this.logger.at(Level.SEVERE).withCause(var6).log("Exception while shutting down world:"); } } } @@ -274,13 +311,23 @@ public class World extends TickingThread implements Executor, ExecutorMetricsReg public void validateDeleteOnRemove() { if (this.worldConfig.isDeleteOnRemove()) { try { - FileUtil.deleteDirectory(this.getSavePath()); + this.deleteWorldFromDisk(); } catch (Throwable var2) { this.logger.at(Level.SEVERE).withCause(var2).log("Exception while deleting world on remove:"); } } } + private void deleteWorldFromDisk() throws IOException { + Path originDir = this.getSavePath(); + Path filename = originDir.getFileName(); + String noCollisionsName = filename + "_del" + UUID.randomUUID().toString().substring(0, 8); + Path deletionDir = Universe.get().getWorldsDeletedPath().resolve(noCollisionsName); + Files.createDirectories(deletionDir.getParent()); + FileUtil.atomicMove(originDir, deletionDir); + FileUtil.deleteDirectory(deletionDir); + } + @Override protected boolean isIdle() { return this.players.isEmpty(); @@ -332,6 +379,7 @@ public class World extends TickingThread implements Executor, ExecutorMetricsReg this.chunkLighting.stop(); this.worldMapManager.stop(); this.logger.at(Level.INFO).log("Removing players..."); + Object2ObjectOpenHashMap currentPlayers = new Object2ObjectOpenHashMap<>(this.players); for (PlayerRef playerRef : this.playerRefs) { if (playerRef.getReference() != null) { @@ -359,7 +407,8 @@ public class World extends TickingThread implements Executor, ExecutorMetricsReg this.acceptingTasks.set(false); if (this.alive.getAndSet(false)) { - Universe.get().removeWorldExceptionally(this.name); + this.stopIndividualWorld(currentPlayers); + Universe.get().removeWorldExceptionally(this.name, currentPlayers); } HytaleServer.get().reportSingleplayerStatus("Closing world '" + this.name + "'"); @@ -922,25 +971,19 @@ public class World extends TickingThread implements Executor, ExecutorMetricsReg } @Nonnull - public CompletableFuture drainPlayersTo(@Nonnull World fallbackTargetWorld) { - return CompletableFuture.completedFuture((Void)null) - .thenComposeAsync( - aVoid -> { - ObjectArrayList> futures = new ObjectArrayList<>(); + public CompletableFuture drainPlayersTo(@Nonnull World fallbackTargetWorld, Collection players) { + ObjectArrayList> futures = new ObjectArrayList<>(); - for (PlayerRef playerRef : this.playerRefs) { - Holder holder = playerRef.removeFromStore(); - DrainPlayerFromWorldEvent event = HytaleServer.get() - .getEventBus() - .dispatchFor(DrainPlayerFromWorldEvent.class, this.name) - .dispatch(new DrainPlayerFromWorldEvent(holder, fallbackTargetWorld, null)); - futures.add(event.getWorld().addPlayer(playerRef, event.getTransform())); - } + for (PlayerRef playerRef : players) { + Holder holder = playerRef.getReference() != null ? playerRef.removeFromStore() : playerRef.getHolder(); + DrainPlayerFromWorldEvent event = HytaleServer.get() + .getEventBus() + .dispatchFor(DrainPlayerFromWorldEvent.class, this.name) + .dispatch(new DrainPlayerFromWorldEvent(holder, fallbackTargetWorld, null)); + futures.add(event.getWorld().addPlayer(playerRef, event.getTransform())); + } - return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); - }, - this - ); + return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/universe/world/chunk/environment/EnvironmentChunk.java b/src/com/hypixel/hytale/server/core/universe/world/chunk/environment/EnvironmentChunk.java index d392d8b6..cfaf2ee7 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/chunk/environment/EnvironmentChunk.java +++ b/src/com/hypixel/hytale/server/core/universe/world/chunk/environment/EnvironmentChunk.java @@ -271,10 +271,11 @@ public class EnvironmentChunk implements Component { public void intake(@Nonnull Int2IntFunction dataSource) { int maxYInclusive = 319; int previousEnvironment = 0; + int environmentId = 0; int runCounter = 0; for (int y = 319; y >= 0; y--) { - int environmentId = dataSource.applyAsInt(y); + environmentId = dataSource.applyAsInt(y); if (y == 319) { previousEnvironment = environmentId; this.valuesReversed.add(environmentId); @@ -289,6 +290,8 @@ public class EnvironmentChunk implements Component { runCounter = 1; } } + + this.count(environmentId, runCounter); } } } diff --git a/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockInspectPhysicsCommand.java b/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockInspectPhysicsCommand.java index 5fecdffb..75e96b7f 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockInspectPhysicsCommand.java +++ b/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockInspectPhysicsCommand.java @@ -26,7 +26,7 @@ public class BlockInspectPhysicsCommand extends AbstractPlayerCommand { private static final Message MESSAGE_COMMANDS_BLOCK_INSPECT_PHYS_NO_BLOCKS = Message.translation("server.commands.block.inspectphys.noblocks"); @Nonnull private static final Message MESSAGE_COMMANDS_BLOCK_INSPECT_PHYS_DONE = Message.translation("server.commands.block.inspectphys.done"); - private final FlagArg ALL = this.withFlagArg("all", ""); + private final FlagArg ALL = this.withFlagArg("all", "server.commands.block.inspectphys.all.desc"); public BlockInspectPhysicsCommand() { super("inspectphys", "server.commands.block.inspectphys.desc"); diff --git a/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockSetStateCommand.java b/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockSetStateCommand.java index 09ee31eb..dc4f154c 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockSetStateCommand.java +++ b/src/com/hypixel/hytale/server/core/universe/world/commands/block/BlockSetStateCommand.java @@ -8,10 +8,10 @@ import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import javax.annotation.Nonnull; public class BlockSetStateCommand extends SimpleBlockCommand { - private final RequiredArg stateArg = this.withRequiredArg("state", "", ArgTypes.STRING); + private final RequiredArg stateArg = this.withRequiredArg("state", "server.commands.block.setstate.arg.state", ArgTypes.STRING); public BlockSetStateCommand() { - super("setstate", ""); + super("setstate", "server.commands.block.setstate.desc"); } @Override diff --git a/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindCommand.java b/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindCommand.java index 6942ef2b..3de98f2f 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindCommand.java +++ b/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindCommand.java @@ -33,15 +33,15 @@ public class BlockBulkFindCommand extends AbstractWorldCommand { @Nonnull private static final Message MESSAGE_COMMANDS_BLOCK_FIND_DONE = Message.translation("server.commands.block.find.done"); @Nonnull - private final RequiredArg chunkXArg = this.withRequiredArg("chunkX", "", ArgTypes.RELATIVE_INT_COORD); + private final RequiredArg chunkXArg = this.withRequiredArg("chunkX", "server.commands.block.find.chunkX.desc", ArgTypes.RELATIVE_INT_COORD); @Nonnull - private final RequiredArg chunkZArg = this.withRequiredArg("chunkZ", "", ArgTypes.RELATIVE_INT_COORD); + private final RequiredArg chunkZArg = this.withRequiredArg("chunkZ", "server.commands.block.find.chunkZ.desc", ArgTypes.RELATIVE_INT_COORD); @Nonnull - private final RequiredArg blockTypeArg = this.withRequiredArg("block", "", ArgTypes.BLOCK_TYPE_KEY); + private final RequiredArg blockTypeArg = this.withRequiredArg("block", "server.commands.block.find.block.desc", ArgTypes.BLOCK_TYPE_KEY); @Nonnull - private final RequiredArg countArg = this.withRequiredArg("count", "", ArgTypes.INTEGER); + private final RequiredArg countArg = this.withRequiredArg("count", "server.commands.block.find.count.desc", ArgTypes.INTEGER); @Nonnull - private final RequiredArg timeoutArg = this.withRequiredArg("timeout", "", ArgTypes.INTEGER); + private final RequiredArg timeoutArg = this.withRequiredArg("timeout", "server.commands.block.find.timeout.desc", ArgTypes.INTEGER); public BlockBulkFindCommand() { super("find", "server.commands.block.find.desc", true); diff --git a/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindHereCommand.java b/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindHereCommand.java index 70cec30f..b89f6eb8 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindHereCommand.java +++ b/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkFindHereCommand.java @@ -29,11 +29,13 @@ import javax.annotation.Nonnull; public class BlockBulkFindHereCommand extends AbstractPlayerCommand { @Nonnull - private final FlagArg printNameArg = this.withFlagArg("print", ""); + private final FlagArg printNameArg = this.withFlagArg("print", "server.commands.block.find-here.print.desc"); @Nonnull - private final RequiredArg blockTypeArg = this.withRequiredArg("block", "", ArgTypes.BLOCK_TYPE_KEY); + private final RequiredArg blockTypeArg = this.withRequiredArg("block", "server.commands.block.find-here.block.desc", ArgTypes.BLOCK_TYPE_KEY); @Nonnull - private final DefaultArg radiusArg = this.withDefaultArg("radius", "", ArgTypes.INTEGER, 3, ""); + private final DefaultArg radiusArg = this.withDefaultArg( + "radius", "server.commands.block.find-here.radius.desc", ArgTypes.INTEGER, 3, "server.commands.block.bulk.find-here.radius.default" + ); public BlockBulkFindHereCommand() { super("find-here", "server.commands.block.find-here.desc"); diff --git a/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkReplaceCommand.java b/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkReplaceCommand.java index e906784a..f13b2130 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkReplaceCommand.java +++ b/src/com/hypixel/hytale/server/core/universe/world/commands/block/bulk/BlockBulkReplaceCommand.java @@ -32,14 +32,16 @@ import javax.annotation.Nonnull; public class BlockBulkReplaceCommand extends AbstractPlayerCommand { @Nonnull - private final RequiredArg findArg = this.withRequiredArg("find", "", ArgTypes.BLOCK_TYPE_KEY); + private final RequiredArg findArg = this.withRequiredArg("find", "server.commands.block.bulk.replace.find.desc", ArgTypes.BLOCK_TYPE_KEY); @Nonnull - private final RequiredArg replaceArg = this.withRequiredArg("replaceWith", "", ArgTypes.BLOCK_TYPE_KEY); + private final RequiredArg replaceArg = this.withRequiredArg( + "replaceWith", "server.commands.block.bulk.replace.replaceWith.desc", ArgTypes.BLOCK_TYPE_KEY + ); @Nonnull - private final RequiredArg radiusArg = this.withRequiredArg("radius", "", ArgTypes.INTEGER); + private final RequiredArg radiusArg = this.withRequiredArg("radius", "server.commands.block.bulk.replace.radius.desc", ArgTypes.INTEGER); public BlockBulkReplaceCommand() { - super("replace", ""); + super("replace", "server.commands.block.bulk.replace.desc"); } @Override diff --git a/src/com/hypixel/hytale/server/core/universe/world/commands/worldconfig/WorldConfigSetPvpCommand.java b/src/com/hypixel/hytale/server/core/universe/world/commands/worldconfig/WorldConfigSetPvpCommand.java index 418029d0..8bd28c7b 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/commands/worldconfig/WorldConfigSetPvpCommand.java +++ b/src/com/hypixel/hytale/server/core/universe/world/commands/worldconfig/WorldConfigSetPvpCommand.java @@ -9,7 +9,6 @@ import com.hypixel.hytale.server.core.command.system.basecommands.AbstractWorldC import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.WorldConfig; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; -import com.hypixel.hytale.server.core.util.message.MessageFormat; import javax.annotation.Nonnull; public class WorldConfigSetPvpCommand extends AbstractWorldCommand { @@ -27,7 +26,7 @@ public class WorldConfigSetPvpCommand extends AbstractWorldCommand { worldConfig.setPvpEnabled(isPvpEnabled); worldConfig.markChanged(); context.sendMessage( - Message.translation("server.universe.setpvp.info").param("status", MessageFormat.enabled(isPvpEnabled)).param("worldName", world.getName()) + Message.translation("server.universe.setpvp.info").param("enabled", isPvpEnabled ? "true" : "false").param("worldName", world.getName()) ); } } diff --git a/src/com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/StairConnectedBlockRuleSet.java b/src/com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/StairConnectedBlockRuleSet.java index 2415dbe4..14e47989 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/StairConnectedBlockRuleSet.java +++ b/src/com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/StairConnectedBlockRuleSet.java @@ -55,6 +55,7 @@ public class StairConnectedBlockRuleSet extends ConnectedBlockRuleSet implements .append(new KeyedCodec<>("MaterialName", Codec.STRING), (ruleSet, materialName) -> ruleSet.materialName = materialName, ruleSet -> ruleSet.materialName) .add() .build(); + protected Object2IntMap stairTypeToBlockId; private ConnectedBlockOutput straight; private ConnectedBlockOutput cornerLeft; private ConnectedBlockOutput cornerRight; @@ -62,38 +63,6 @@ public class StairConnectedBlockRuleSet extends ConnectedBlockRuleSet implements private ConnectedBlockOutput invertedCornerRight; private String materialName = "Stair"; private Int2ObjectMap blockIdToStairType; - protected Object2IntMap stairTypeToBlockId; - - @Override - public boolean onlyUpdateOnPlacement() { - return false; - } - - @Override - public void updateCachedBlockTypes(BlockType baseBlockType, BlockTypeAssetMap assetMap) { - int baseIndex = assetMap.getIndex(baseBlockType.getId()); - Int2ObjectMap blockIdToStairType = new Int2ObjectOpenHashMap<>(); - Object2IntMap stairTypeToBlockId = new Object2IntOpenHashMap<>(); - stairTypeToBlockId.defaultReturnValue(baseIndex); - ConnectedBlockOutput[] outputs = new ConnectedBlockOutput[]{ - this.straight, this.cornerLeft, this.cornerRight, this.invertedCornerLeft, this.invertedCornerRight - }; - StairConnectedBlockRuleSet.StairType[] stairTypes = StairConnectedBlockRuleSet.StairType.VALUES; - - for (int i = 0; i < outputs.length; i++) { - ConnectedBlockOutput output = outputs[i]; - if (output != null) { - int index = output.resolve(baseBlockType, assetMap); - if (index != -1) { - blockIdToStairType.put(index, stairTypes[i]); - stairTypeToBlockId.put(stairTypes[i], index); - } - } - } - - this.blockIdToStairType = blockIdToStairType; - this.stairTypeToBlockId = stairTypeToBlockId; - } @Nullable protected static ObjectIntPair getStairData(World world, Vector3i coordinate, @Nullable String requiredMaterialName) { @@ -129,6 +98,130 @@ public class StairConnectedBlockRuleSet extends ConnectedBlockRuleSet implements } } + protected static StairConnectedBlockRuleSet.StairConnection getCornerConnection( + World world, + StairLikeConnectedBlockRuleSet currentRuleSet, + Vector3i coordinate, + Vector3i mutablePos, + int rotation, + Rotation currentYaw, + boolean upsideDown, + int width + ) { + StairConnectedBlockRuleSet.StairConnection backConnection = null; + mutablePos.assign(Vector3i.NORTH).scale(width); + currentYaw.rotateY(mutablePos, mutablePos); + mutablePos.add(coordinate.x, coordinate.y, coordinate.z); + ObjectIntPair backStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); + if (backStair == null && width > 1) { + mutablePos.assign(Vector3i.NORTH).scale(width + 1); + currentYaw.rotateY(mutablePos, mutablePos); + mutablePos.add(coordinate.x, coordinate.y, coordinate.z); + backStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); + if (backStair != null && backStair.first() == StairConnectedBlockRuleSet.StairType.STRAIGHT) { + backStair = null; + } + } + + if (backStair != null) { + StairConnectedBlockRuleSet.StairType otherStairType = backStair.left(); + RotationTuple otherStairRotation = RotationTuple.get(backStair.rightInt()); + Rotation otherYaw = otherStairRotation.yaw(); + boolean otherUpsideDown = otherStairRotation.pitch() != Rotation.None; + if (otherUpsideDown) { + otherYaw = otherYaw.flip(); + } + + if (canConnectTo(currentYaw, otherYaw, upsideDown, otherUpsideDown)) { + mutablePos.assign(Vector3i.SOUTH); + otherYaw.rotateY(mutablePos, mutablePos); + mutablePos.add(coordinate.x, coordinate.y, coordinate.z); + ObjectIntPair sidewaysStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); + if (sidewaysStair == null || sidewaysStair.rightInt() != rotation) { + backConnection = getConnection(currentYaw, otherYaw, otherStairType, false, upsideDown); + } + } + } + + return backConnection; + } + + protected static StairConnectedBlockRuleSet.StairConnection getInvertedCornerConnection( + World world, StairLikeConnectedBlockRuleSet currentRuleSet, Vector3i coordinate, Vector3i mutablePos, Rotation currentYaw, boolean upsideDown + ) { + StairConnectedBlockRuleSet.StairConnection frontConnection = null; + mutablePos.assign(Vector3i.SOUTH); + currentYaw.rotateY(mutablePos, mutablePos); + mutablePos.add(coordinate.x, coordinate.y, coordinate.z); + ObjectIntPair frontStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); + if (frontStair != null) { + StairConnectedBlockRuleSet.StairType otherStairType = frontStair.left(); + RotationTuple otherStairRotation = RotationTuple.get(frontStair.rightInt()); + Rotation otherYaw = otherStairRotation.yaw(); + boolean otherUpsideDown = otherStairRotation.pitch() != Rotation.None; + if (otherUpsideDown) { + otherYaw = otherYaw.flip(); + } + + if (canConnectTo(currentYaw, otherYaw, upsideDown, otherUpsideDown)) { + frontConnection = getConnection(currentYaw, otherYaw, otherStairType, true, upsideDown); + } + } + + return frontConnection; + } + + private static boolean canConnectTo(Rotation currentYaw, Rotation otherYaw, boolean upsideDown, boolean otherUpsideDown) { + return otherUpsideDown == upsideDown && otherYaw != currentYaw && otherYaw.add(Rotation.OneEighty) != currentYaw; + } + + private static StairConnectedBlockRuleSet.StairConnection getConnection( + Rotation currentYaw, Rotation otherYaw, StairConnectedBlockRuleSet.StairType otherStairType, boolean inverted, boolean upsideDown + ) { + if (otherYaw == currentYaw.add(Rotation.Ninety) + && otherStairType != StairConnectedBlockRuleSet.StairType.invertedCorner(upsideDown ^ inverted) + && otherStairType != StairConnectedBlockRuleSet.StairType.corner(upsideDown ^ !inverted)) { + return StairConnectedBlockRuleSet.StairConnection.CORNER_LEFT; + } else { + return otherYaw == currentYaw.subtract(Rotation.Ninety) + && otherStairType != StairConnectedBlockRuleSet.StairType.invertedCorner(upsideDown ^ !inverted) + && otherStairType != StairConnectedBlockRuleSet.StairType.corner(upsideDown ^ inverted) + ? StairConnectedBlockRuleSet.StairConnection.CORNER_RIGHT + : null; + } + } + + @Override + public boolean onlyUpdateOnPlacement() { + return false; + } + + @Override + public void updateCachedBlockTypes(BlockType baseBlockType, BlockTypeAssetMap assetMap) { + int baseIndex = assetMap.getIndex(baseBlockType.getId()); + Int2ObjectMap blockIdToStairType = new Int2ObjectOpenHashMap<>(); + Object2IntMap stairTypeToBlockId = new Object2IntOpenHashMap<>(); + stairTypeToBlockId.defaultReturnValue(baseIndex); + ConnectedBlockOutput[] outputs = new ConnectedBlockOutput[]{ + this.straight, this.cornerLeft, this.cornerRight, this.invertedCornerLeft, this.invertedCornerRight + }; + StairConnectedBlockRuleSet.StairType[] stairTypes = StairConnectedBlockRuleSet.StairType.VALUES; + + for (int i = 0; i < outputs.length; i++) { + ConnectedBlockOutput output = outputs[i]; + if (output != null) { + int index = output.resolve(baseBlockType, assetMap); + if (index != -1) { + blockIdToStairType.put(index, stairTypes[i]); + stairTypeToBlockId.put(stairTypes[i], index); + } + } + } + + this.blockIdToStairType = blockIdToStairType; + this.stairTypeToBlockId = stairTypeToBlockId; + } + @Override public StairConnectedBlockRuleSet.StairType getStairType(int blockId) { return this.blockIdToStairType.get(blockId); @@ -193,99 +286,6 @@ public class StairConnectedBlockRuleSet extends ConnectedBlockRuleSet implements } } - protected static StairConnectedBlockRuleSet.StairConnection getCornerConnection( - World world, - StairLikeConnectedBlockRuleSet currentRuleSet, - Vector3i coordinate, - Vector3i mutablePos, - int rotation, - Rotation currentYaw, - boolean upsideDown, - int width - ) { - StairConnectedBlockRuleSet.StairConnection backConnection = null; - mutablePos.assign(Vector3i.NORTH).scale(width); - currentYaw.rotateY(mutablePos, mutablePos); - mutablePos.add(coordinate.x, coordinate.y, coordinate.z); - ObjectIntPair backStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); - if (backStair == null && width > 1) { - mutablePos.assign(Vector3i.NORTH).scale(width + 1); - currentYaw.rotateY(mutablePos, mutablePos); - mutablePos.add(coordinate.x, coordinate.y, coordinate.z); - backStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); - if (backStair != null && backStair.first() == StairConnectedBlockRuleSet.StairType.STRAIGHT) { - backStair = null; - } - } - - if (backStair != null) { - StairConnectedBlockRuleSet.StairType otherStairType = backStair.left(); - RotationTuple otherStairRotation = RotationTuple.get(backStair.rightInt()); - Rotation otherYaw = otherStairRotation.yaw(); - boolean otherUpsideDown = otherStairRotation.pitch() != Rotation.None; - if (otherUpsideDown) { - otherYaw = otherYaw.flip(); - } - - if (canConnectTo(currentYaw, otherYaw, upsideDown, otherUpsideDown)) { - mutablePos.assign(Vector3i.SOUTH); - otherYaw.rotateY(mutablePos, mutablePos); - mutablePos.add(coordinate.x, coordinate.y, coordinate.z); - ObjectIntPair sidewaysStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); - if (sidewaysStair == null || sidewaysStair.rightInt() != rotation) { - backConnection = getConnection(currentYaw, otherYaw, otherStairType, false); - } - } - } - - return backConnection; - } - - protected static StairConnectedBlockRuleSet.StairConnection getInvertedCornerConnection( - World world, StairLikeConnectedBlockRuleSet currentRuleSet, Vector3i coordinate, Vector3i mutablePos, Rotation currentYaw, boolean upsideDown - ) { - StairConnectedBlockRuleSet.StairConnection frontConnection = null; - mutablePos.assign(Vector3i.SOUTH); - currentYaw.rotateY(mutablePos, mutablePos); - mutablePos.add(coordinate.x, coordinate.y, coordinate.z); - ObjectIntPair frontStair = getStairData(world, mutablePos, currentRuleSet.getMaterialName()); - if (frontStair != null) { - StairConnectedBlockRuleSet.StairType otherStairType = frontStair.left(); - RotationTuple otherStairRotation = RotationTuple.get(frontStair.rightInt()); - Rotation otherYaw = otherStairRotation.yaw(); - boolean otherUpsideDown = otherStairRotation.pitch() != Rotation.None; - if (otherUpsideDown) { - otherYaw = otherYaw.flip(); - } - - if (canConnectTo(currentYaw, otherYaw, upsideDown, otherUpsideDown)) { - frontConnection = getConnection(currentYaw, otherYaw, otherStairType, true); - } - } - - return frontConnection; - } - - private static boolean canConnectTo(Rotation currentYaw, Rotation otherYaw, boolean upsideDown, boolean otherUpsideDown) { - return otherUpsideDown == upsideDown && otherYaw != currentYaw && otherYaw.add(Rotation.OneEighty) != currentYaw; - } - - private static StairConnectedBlockRuleSet.StairConnection getConnection( - Rotation currentYaw, Rotation otherYaw, StairConnectedBlockRuleSet.StairType otherStairType, boolean inverted - ) { - if (otherYaw == currentYaw.add(Rotation.Ninety) - && otherStairType != StairConnectedBlockRuleSet.StairType.invertedCorner(inverted) - && otherStairType != StairConnectedBlockRuleSet.StairType.corner(!inverted)) { - return StairConnectedBlockRuleSet.StairConnection.CORNER_LEFT; - } else { - return otherYaw == currentYaw.subtract(Rotation.Ninety) - && otherStairType != StairConnectedBlockRuleSet.StairType.invertedCorner(!inverted) - && otherStairType != StairConnectedBlockRuleSet.StairType.corner(inverted) - ? StairConnectedBlockRuleSet.StairConnection.CORNER_RIGHT - : null; - } - } - @Nullable @Override public com.hypixel.hytale.protocol.ConnectedBlockRuleSet toPacket(BlockTypeAssetMap assetMap) { diff --git a/src/com/hypixel/hytale/server/core/universe/world/storage/resources/DiskResourceStorageProvider.java b/src/com/hypixel/hytale/server/core/universe/world/storage/resources/DiskResourceStorageProvider.java index 27f48a90..f178ef72 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/storage/resources/DiskResourceStorageProvider.java +++ b/src/com/hypixel/hytale/server/core/universe/world/storage/resources/DiskResourceStorageProvider.java @@ -5,6 +5,7 @@ import com.hypixel.hytale.codec.ExtraInfo; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.util.RawJsonReader; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.component.ComponentRegistry; import com.hypixel.hytale.component.IResourceStorage; import com.hypixel.hytale.component.Resource; @@ -46,7 +47,12 @@ public class DiskResourceStorageProvider implements IResourceStorageProvider { @Nonnull @Override public IResourceStorage getResourceStorage(@Nonnull World world) { - return new DiskResourceStorageProvider.DiskResourceStorage(world.getSavePath().resolve(this.path)); + Path resolved = PathUtil.resolvePathWithinDir(world.getSavePath(), this.path); + if (resolved == null) { + throw new IllegalStateException("Resource storage path must be within world directory: " + this.path); + } else { + return new DiskResourceStorageProvider.DiskResourceStorage(resolved); + } } @Nonnull diff --git a/src/com/hypixel/hytale/server/core/universe/world/worldlocationcondition/WorldLocationCondition.java b/src/com/hypixel/hytale/server/core/universe/world/worldlocationcondition/WorldLocationCondition.java index 404f37e0..cb262746 100644 --- a/src/com/hypixel/hytale/server/core/universe/world/worldlocationcondition/WorldLocationCondition.java +++ b/src/com/hypixel/hytale/server/core/universe/world/worldlocationcondition/WorldLocationCondition.java @@ -6,10 +6,12 @@ import com.hypixel.hytale.server.core.universe.world.World; import javax.annotation.Nonnull; public abstract class WorldLocationCondition { + @Nonnull public static final CodecMapCodec CODEC = new CodecMapCodec<>("Type"); + @Nonnull public static final BuilderCodec BASE_CODEC = BuilderCodec.abstractBuilder(WorldLocationCondition.class).build(); - public abstract boolean test(World var1, int var2, int var3, int var4); + public abstract boolean test(@Nonnull World var1, int var2, int var3, int var4); @Override public abstract boolean equals(Object var1); diff --git a/src/com/hypixel/hytale/server/core/util/BsonUtil.java b/src/com/hypixel/hytale/server/core/util/BsonUtil.java index fa199587..9ee352a4 100644 --- a/src/com/hypixel/hytale/server/core/util/BsonUtil.java +++ b/src/com/hypixel/hytale/server/core/util/BsonUtil.java @@ -9,6 +9,7 @@ import com.hypixel.hytale.common.util.ExceptionUtil; import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.util.io.ByteBufUtil; +import com.hypixel.hytale.server.core.util.io.FileUtil; import com.hypixel.hytale.sneakythrow.SneakyThrow; import io.netty.buffer.ByteBuf; import java.io.BufferedWriter; @@ -17,7 +18,6 @@ import java.io.StringWriter; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.CompletableFuture; @@ -80,26 +80,6 @@ public class BsonUtil { ByteBufUtil.writeByteArray(buf, writeToBytes(doc)); } - @Nonnull - public static CompletableFuture writeDocumentBytes(@Nonnull Path file, BsonDocument document) { - try { - if (Files.isRegularFile(file)) { - Path resolve = file.resolveSibling(file.getFileName() + ".bak"); - Files.move(file, resolve, StandardCopyOption.REPLACE_EXISTING); - } - - byte[] bytes; - try (BasicOutputBuffer bob = new BasicOutputBuffer()) { - codec.encode(new BsonBinaryWriter(bob), document, encoderContext); - bytes = bob.toByteArray(); - } - - return CompletableFuture.runAsync(SneakyThrow.sneakyRunnable(() -> Files.write(file, bytes))); - } catch (IOException var8) { - return CompletableFuture.failedFuture(var8); - } - } - @Nonnull public static CompletableFuture writeDocument(@Nonnull Path file, BsonDocument document) { return writeDocument(file, document, true); @@ -113,13 +93,8 @@ public class BsonUtil { Files.createDirectories(parent); } - if (backup && Files.isRegularFile(file)) { - Path resolve = file.resolveSibling(file.getFileName() + ".bak"); - Files.move(file, resolve, StandardCopyOption.REPLACE_EXISTING); - } - String json = toJson(document); - return CompletableFuture.runAsync(SneakyThrow.sneakyRunnable(() -> Files.writeString(file, json))); + return CompletableFuture.runAsync(SneakyThrow.sneakyRunnable(() -> FileUtil.writeStringAtomic(file, json, backup))); } catch (IOException var5) { return CompletableFuture.failedFuture(var5); } @@ -227,18 +202,21 @@ public class BsonUtil { Files.createDirectories(parent); } - if (Files.isRegularFile(path)) { - Path resolve = path.resolveSibling(path.getFileName() + ".bak"); - Files.move(path, resolve, StandardCopyOption.REPLACE_EXISTING); - } - ExtraInfo extraInfo = ExtraInfo.THREAD_LOCAL.get(); BsonValue bsonValue = codec.encode(value, extraInfo); extraInfo.getValidationResults().logOrThrowValidatorExceptions(logger); BsonDocument document = bsonValue.asDocument(); + Path tmpPath = path.resolveSibling(path.getFileName() + ".tmp"); + Path bakPath = path.resolveSibling(path.getFileName() + ".bak"); - try (BufferedWriter writer = Files.newBufferedWriter(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { + try (BufferedWriter writer = Files.newBufferedWriter(tmpPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) { BSON_DOCUMENT_CODEC.encode(new JsonWriter(writer, SETTINGS), document, encoderContext); } + + if (Files.isRegularFile(path)) { + FileUtil.atomicMove(path, bakPath); + } + + FileUtil.atomicMove(tmpPath, path); } } diff --git a/src/com/hypixel/hytale/server/core/util/MessageUtil.java b/src/com/hypixel/hytale/server/core/util/MessageUtil.java index 77c0182b..58c44597 100644 --- a/src/com/hypixel/hytale/server/core/util/MessageUtil.java +++ b/src/com/hypixel/hytale/server/core/util/MessageUtil.java @@ -148,7 +148,7 @@ public class MessageUtil { } else if (replacement != null) { String formattedReplacement; formattedReplacement = ""; - label155: + label171: switch (format) { case "upper": if (replacement instanceof StringParamValue s) { @@ -171,7 +171,7 @@ public class MessageUtil { case LongParamValue l -> Long.toString(l.value); default -> ""; }; - break label155; + break label171; case "decimal": case null: default: @@ -183,7 +183,7 @@ public class MessageUtil { case LongParamValue l -> Long.toString(l.value); default -> ""; }; - break label155; + break label171; } case "plural": if (options != null) { @@ -219,6 +219,22 @@ public class MessageUtil { } else { formattedReplacement = ""; } + break; + case "select": + if (options != null) { + Map selectOptions = parseSelectOptions(options); + String selectKey = replacement.toString(); + String selected; + if (selectOptions.containsKey(selectKey)) { + selected = selectOptions.get(selectKey); + } else if (selectOptions.containsKey("other")) { + selected = selectOptions.get("other"); + } else { + selected = selectOptions.isEmpty() ? "" : selectOptions.values().iterator().next(); + } + + formattedReplacement = formatText(selected, params, messageParams); + } case null: } @@ -459,6 +475,58 @@ public class MessageUtil { return "other"; } + @Nonnull + private static Map parseSelectOptions(@Nonnull String options) { + HashMap result = new HashMap<>(); + int i = 0; + int len = options.length(); + + while (i < len) { + while (i < len && Character.isWhitespace(options.charAt(i))) { + i++; + } + + if (i >= len) { + break; + } + + int keyStart = i; + + while (i < len && !Character.isWhitespace(options.charAt(i)) && options.charAt(i) != '{') { + i++; + } + + if (i == keyStart) { + break; + } + + String key = options.substring(keyStart, i); + + while (i < len && Character.isWhitespace(options.charAt(i))) { + i++; + } + + if (i >= len || options.charAt(i) != '{') { + break; + } + + int braceEnd = findMatchingBrace(options, i); + if (braceEnd < 0) { + break; + } + + if (braceEnd > i + 1) { + result.put(key, options.substring(i + 1, braceEnd)); + } else { + result.put(key, ""); + } + + i = braceEnd + 1; + } + + return result; + } + @Nullable private static Instant parseDateTime(@Nonnull ParamValue value) { return switch (value) { diff --git a/src/com/hypixel/hytale/server/core/util/io/FileUtil.java b/src/com/hypixel/hytale/server/core/util/io/FileUtil.java index 7c24b18b..2b32958c 100644 --- a/src/com/hypixel/hytale/server/core/util/io/FileUtil.java +++ b/src/com/hypixel/hytale/server/core/util/io/FileUtil.java @@ -4,6 +4,7 @@ import com.hypixel.hytale.sneakythrow.SneakyThrow; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.CopyOption; import java.nio.file.FileVisitOption; import java.nio.file.Files; @@ -104,4 +105,27 @@ public class FileUtil { } } } + + public static void writeStringAtomic(@Nonnull Path file, @Nonnull String content, boolean backup) throws IOException { + Path tmpPath = file.resolveSibling(file.getFileName() + ".tmp"); + Path bakPath = file.resolveSibling(file.getFileName() + ".bak"); + Files.writeString(tmpPath, content); + if (backup && Files.isRegularFile(file)) { + atomicMove(file, bakPath); + } + + atomicMove(tmpPath, file); + } + + public static void atomicMove(@Nonnull Path source, @Nonnull Path target) throws IOException { + try { + Files.move(source, target, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); + } catch (AtomicMoveNotSupportedException var3) { + Files.move(source, target, StandardCopyOption.REPLACE_EXISTING); + } + } + + public static void writeStringAtomic(@Nonnull Path file, @Nonnull String content) throws IOException { + writeStringAtomic(file, content, true); + } } diff --git a/src/com/hypixel/hytale/server/core/util/message/MessageFormat.java b/src/com/hypixel/hytale/server/core/util/message/MessageFormat.java index 52abde66..cb50d199 100644 --- a/src/com/hypixel/hytale/server/core/util/message/MessageFormat.java +++ b/src/com/hypixel/hytale/server/core/util/message/MessageFormat.java @@ -1,21 +1,13 @@ package com.hypixel.hytale.server.core.util.message; import com.hypixel.hytale.server.core.Message; -import java.awt.Color; import java.util.Collection; import javax.annotation.Nonnull; import javax.annotation.Nullable; public final class MessageFormat { - private static final Message ENABLED = Message.translation("server.general.enabled").color(Color.GREEN); - private static final Message DISABLED = Message.translation("server.general.disabled").color(Color.RED); private static final int LIST_MAX_INLINE_VALUES = 4; - @Nonnull - public static Message enabled(boolean b) { - return b ? ENABLED : DISABLED; - } - @Nonnull public static Message list(@Nullable Message header, @Nonnull Collection values) { Message msg = Message.empty(); diff --git a/src/com/hypixel/hytale/server/core/util/thread/TickingThread.java b/src/com/hypixel/hytale/server/core/util/thread/TickingThread.java index ef3de5fc..8470db5a 100644 --- a/src/com/hypixel/hytale/server/core/util/thread/TickingThread.java +++ b/src/com/hypixel/hytale/server/core/util/thread/TickingThread.java @@ -1,5 +1,6 @@ package com.hypixel.hytale.server.core.util.thread; +import com.hypixel.hytale.common.plugin.PluginIdentifier; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.metrics.metric.HistoricMetric; import java.util.concurrent.CompletableFuture; @@ -24,6 +25,10 @@ public abstract class TickingThread implements Runnable { private Thread thread; @Nonnull private CompletableFuture startedFuture = new CompletableFuture<>(); + @Nullable + private PluginIdentifier possibleFailureCause; + @Nullable + private Throwable failureException; public TickingThread(String threadName) { this(threadName, 30, false); @@ -74,7 +79,16 @@ public abstract class TickingThread implements Runnable { } catch (InterruptedException var9) { Thread.currentThread().interrupt(); } catch (Throwable var10) { - HytaleLogger.getLogger().at(Level.SEVERE).withCause(var10).log("Exception in thread %s:", this.thread); + this.failureException = var10; + this.possibleFailureCause = PluginIdentifier.identifyThirdPartyPlugin(var10); + if (this.possibleFailureCause == null) { + HytaleLogger.getLogger().at(Level.SEVERE).withCause(var10).log("Exception in thread %s:", this.thread); + } else { + HytaleLogger.getLogger() + .at(Level.SEVERE) + .withCause(var10) + .log("Exception in thread %s potentially caused by %s:", this.thread, this.possibleFailureCause); + } } if (this.needsShutdown.getAndSet(false)) { @@ -195,6 +209,16 @@ public abstract class TickingThread implements Runnable { return this.thread != null && this.thread.isAlive() && this.needsShutdown.get(); } + @Nullable + public PluginIdentifier getPossibleFailureCause() { + return this.possibleFailureCause; + } + + @Nullable + public Throwable getFailureException() { + return this.failureException; + } + @Deprecated protected void setThread(Thread thread) { this.thread = thread; diff --git a/src/com/hypixel/hytale/server/npc/corecomponents/SensorWithEntityFilters.java b/src/com/hypixel/hytale/server/npc/corecomponents/SensorWithEntityFilters.java index 10502147..d686ca40 100644 --- a/src/com/hypixel/hytale/server/npc/corecomponents/SensorWithEntityFilters.java +++ b/src/com/hypixel/hytale/server/npc/corecomponents/SensorWithEntityFilters.java @@ -6,6 +6,7 @@ import com.hypixel.hytale.component.Store; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderSensorBase; +import com.hypixel.hytale.server.npc.corecomponents.entity.filters.EntityFilterViewSector; import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.movement.controllers.MotionController; import com.hypixel.hytale.server.npc.role.Role; @@ -106,4 +107,14 @@ public abstract class SensorWithEntityFilters extends SensorBase implements IAnn return true; } + + protected float findViewAngleFromFilters() { + for (IEntityFilter filter : this.filters) { + if (filter instanceof EntityFilterViewSector viewSector) { + return viewSector.getViewAngle(); + } + } + + return 0.0F; + } } diff --git a/src/com/hypixel/hytale/server/npc/corecomponents/combat/HeadMotionAim.java b/src/com/hypixel/hytale/server/npc/corecomponents/combat/HeadMotionAim.java index 09c7068f..f78efc3a 100644 --- a/src/com/hypixel/hytale/server/npc/corecomponents/combat/HeadMotionAim.java +++ b/src/com/hypixel/hytale/server/npc/corecomponents/combat/HeadMotionAim.java @@ -5,32 +5,38 @@ import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.math.shape.Box; +import com.hypixel.hytale.math.vector.Transform; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; +import com.hypixel.hytale.server.core.entity.entities.ProjectileComponent; +import com.hypixel.hytale.server.core.modules.debug.DebugUtils; import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox; -import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; -import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.physics.component.Velocity; import com.hypixel.hytale.server.core.modules.physics.util.PhysicsMath; import com.hypixel.hytale.server.core.modules.projectile.config.BallisticData; +import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.core.util.TargetUtil; import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport; import com.hypixel.hytale.server.npc.corecomponents.HeadMotionBase; import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderHeadMotionAim; import com.hypixel.hytale.server.npc.movement.Steering; import com.hypixel.hytale.server.npc.role.Role; +import com.hypixel.hytale.server.npc.role.RoleDebugFlags; +import com.hypixel.hytale.server.npc.role.support.DebugSupport; import com.hypixel.hytale.server.npc.sensorinfo.IPositionProvider; import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider; import com.hypixel.hytale.server.npc.util.AimingData; import com.hypixel.hytale.server.npc.util.NPCPhysicsMath; +import java.util.EnumSet; import java.util.concurrent.ThreadLocalRandom; import javax.annotation.Nonnull; import javax.annotation.Nullable; -public class HeadMotionAim extends HeadMotionBase { +public class HeadMotionAim extends HeadMotionBase implements DebugSupport.DebugFlagsChangeListener { + public static final double MIN_RANGED_AIMING_DISTANCE = 4.0; protected static final ComponentType TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); - protected static final ComponentType MODEL_COMPONENT_TYPE = ModelComponent.getComponentType(); protected static final ComponentType BOUNDING_BOX_COMPONENT_TYPE = BoundingBox.getComponentType(); protected final double spread; protected final boolean deflection; @@ -38,9 +44,13 @@ public class HeadMotionAim extends HeadMotionBase { protected final double relativeTurnSpeed; protected final AimingData aimingData = new AimingData(); protected Ref lastTargetReference; - protected double spreadX; - protected double spreadY; - protected double spreadZ; + protected boolean debugAiming; + protected final Vector3d startPosition = new Vector3d(); + protected final Vector3d startOffset = new Vector3d(); + protected final Vector3d targetPosition = new Vector3d(); + protected final Vector3d targetOffset = new Vector3d(); + protected final Vector3d relativeVelocity = new Vector3d(); + protected final Vector3d spreadOffset = new Vector3d(); public HeadMotionAim(@Nonnull BuilderHeadMotionAim builder, @Nonnull BuilderSupport support) { super(builder); @@ -71,115 +81,154 @@ public class HeadMotionAim extends HeadMotionBase { @Nonnull Steering desiredSteering, @Nonnull ComponentAccessor componentAccessor ) { - if (sensorInfo != null && sensorInfo.hasPosition()) { - TransformComponent transformComponent = componentAccessor.getComponent(ref, TRANSFORM_COMPONENT_TYPE); - - assert transformComponent != null; - - ModelComponent modelComponent = componentAccessor.getComponent(ref, MODEL_COMPONENT_TYPE); - - assert modelComponent != null; - - Vector3d position = transformComponent.getPosition(); + if (sensorInfo != null && sensorInfo.hasPosition() && sensorInfo.getPositionProvider() != null) { + Transform lookVec = TargetUtil.getLook(ref, componentAccessor); + Vector3d lookPosition = lookVec.getPosition(); + Vector3f lookRotation = lookVec.getRotation(); IPositionProvider positionProvider = sensorInfo.getPositionProvider(); - double x = positionProvider.getX() - position.getX(); - double y = positionProvider.getY() - position.getY() - modelComponent.getModel().getEyeHeight(); - double z = positionProvider.getZ() - position.getZ(); - double vx = 0.0; - double vy = 0.0; - double vz = 0.0; + positionProvider.providePosition(this.targetPosition); + this.startPosition.assign(lookPosition); + this.relativeVelocity.assign(Vector3d.ZERO); Ref targetRef = positionProvider.getTarget(); + BallisticData ballisticData = this.aimingData.getBallisticData(); + Box boundingBox = Box.ZERO; if (targetRef != null) { Velocity targetVelocityComponent = componentAccessor.getComponent(targetRef, Velocity.getComponentType()); assert targetVelocityComponent != null; - BoundingBox boundingBoxComponent = componentAccessor.getComponent(ref, BOUNDING_BOX_COMPONENT_TYPE); - Box boundingBox = boundingBoxComponent != null ? boundingBoxComponent.getBoundingBox() : null; - if (this.aimingData.isBallistic()) { - if (boundingBox != null) { - x += (boundingBox.getMax().getX() + boundingBox.getMin().getX()) / 2.0; - y += (boundingBox.getMax().getY() + boundingBox.getMin().getY()) / 2.0; - z += (boundingBox.getMax().getZ() + boundingBox.getMin().getZ()) / 2.0; - } + BoundingBox boundingBoxComponent = componentAccessor.getComponent(targetRef, BOUNDING_BOX_COMPONENT_TYPE); + if (boundingBoxComponent != null) { + boundingBox = boundingBoxComponent.getBoundingBox(); + } + if (ballisticData != null) { if (this.deflection) { - Vector3d steeringVelocity = targetVelocityComponent.getVelocity(); - vx = steeringVelocity.getX(); - vy = steeringVelocity.getY(); - vz = steeringVelocity.getZ(); + this.relativeVelocity.assign(targetVelocityComponent.getVelocity()); } - } else if (boundingBox != null) { - double minY = y + boundingBox.getMin().y; - double maxY = y + boundingBox.getMax().y; - if (minY > 0.0) { - y = minY; - } else if (maxY < 0.0) { - y = maxY; + } else { + double targetY = this.targetPosition.getY(); + double startY = this.startPosition.getY(); + double minY = targetY + boundingBox.getMin().y; + double maxY = targetY + boundingBox.getMax().y; + if (minY > startY) { + this.targetPosition.setY(minY); + } else if (maxY < startY) { + this.targetPosition.setY(maxY); } else { - y = 0.0; + this.targetPosition.setY(startY); } } } - if (this.aimingData.isBallistic()) { - BallisticData ballisticData = this.aimingData.getBallisticData(); - if (ballisticData != null) { - y += ballisticData.getVerticalCenterShot(); - this.aimingData.setDepthOffset(ballisticData.getDepthShot(), ballisticData.isPitchAdjustShot()); + boolean isNearTarget = this.startPosition.distanceSquaredTo(this.targetPosition) <= 16.0; + if (ballisticData != null) { + this.aimingData.setDepthOffset(ballisticData.getDepthShot(), ballisticData.isPitchAdjustShot()); + if (!isNearTarget) { + ProjectileComponent.computeStartOffset( + ballisticData.isPitchAdjustShot(), + ballisticData.getVerticalCenterShot(), + ballisticData.getHorizontalCenterShot(), + ballisticData.getDepthShot(), + lookRotation.getYaw(), + lookRotation.getPitch(), + this.startOffset + ); } else { - this.aimingData.setDepthOffset(0.0, false); + this.startOffset.assign(Vector3d.ZERO); } - if (targetRef != null && (this.lastTargetReference == null || !this.lastTargetReference.equals(targetRef))) { + if (targetRef != null && !targetRef.equals(this.lastTargetReference)) { this.lastTargetReference = targetRef; this.aimingData.setHaveAttacked(true); } if (this.aimingData.isHaveAttacked()) { ThreadLocalRandom random = ThreadLocalRandom.current(); + this.spreadOffset.assign(Vector3d.ZERO); + this.targetOffset.assign(Vector3d.ZERO); if (this.spread > 0.0 && random.nextDouble() > this.hitProbability) { - double spread2 = 2.0 * this.spread * Math.sqrt(NPCPhysicsMath.dotProduct(x, y, z)) / 10.0; - this.spreadX = this.spreadX + spread2 * (random.nextDouble() - 0.5); - this.spreadY = this.spreadY + spread2 * (random.nextDouble() - 0.5); - this.spreadZ = this.spreadZ + spread2 * (random.nextDouble() - 0.5); + double spread2 = 2.0 * this.spread * this.startPosition.distanceTo(this.targetPosition) / 10.0; + this.spreadOffset.assign(random.nextDouble() - 0.5, random.nextDouble() - 0.5, random.nextDouble() - 0.5).scale(spread2); } else { - this.spreadX = 0.0; - this.spreadY = 0.0; - this.spreadZ = 0.0; + double start = 0.1; + double end = 0.9; + this.targetOffset + .assign( + NPCPhysicsMath.lerp(boundingBox.getMin().x, boundingBox.getMax().x, random.nextDouble(0.1, 0.9)), + NPCPhysicsMath.lerp(boundingBox.getMin().y, boundingBox.getMax().y, random.nextDouble(0.1, 0.9)), + NPCPhysicsMath.lerp(boundingBox.getMin().z, boundingBox.getMax().z, random.nextDouble(0.1, 0.9)) + ); } this.aimingData.setHaveAttacked(false); } - x += this.spreadX; - y += this.spreadY; - z += this.spreadZ; + this.targetPosition.add(this.spreadOffset); + this.targetPosition.add(this.targetOffset); + this.startPosition.add(this.startOffset); + } else { + this.aimingData.setDepthOffset(0.0, false); } - float pitch; - float yaw; - if (this.aimingData.computeSolution(x, y, z, vx, vy, vz)) { - yaw = this.aimingData.getYaw(); - pitch = this.aimingData.getPitch(); + double x = this.targetPosition.getX() - this.startPosition.getX(); + double y = this.targetPosition.getY() - this.startPosition.getY(); + double z = this.targetPosition.getZ() - this.startPosition.getZ(); + if (isNearTarget && ballisticData != null) { + float yaw = lookRotation.getYaw(); + float pitch = lookRotation.getPitch(); + double dotXZ = x * x + z * z; + if (dotXZ >= 1.0E-4) { + yaw = PhysicsMath.normalizeTurnAngle(PhysicsMath.headingFromDirection(x, z)); + double invLen = 1.0 / Math.sqrt(dotXZ); + double hOffset = ballisticData.getHorizontalCenterShot(); + if (ballisticData.getDepthShot() != 0.0 && !ballisticData.isPitchAdjustShot()) { + hOffset += ballisticData.getDepthShot(); + } + + double dx = hOffset * x * invLen; + double dy = -ballisticData.getVerticalCenterShot(); + double dz = -(hOffset * z * invLen); + this.startPosition.add(dx, dy, dz); + x -= dx; + y -= dy; + z -= dz; + } + + double dotXYZ = dotXZ + y * y; + if (dotXYZ >= 1.0E-4) { + pitch = PhysicsMath.pitchFromDirection(x, y, z); + } + + this.aimingData.setOrientation(yaw, pitch); + this.aimingData.setTarget(targetRef); + } else if (this.aimingData.computeSolution(x, y, z, this.relativeVelocity.getX(), this.relativeVelocity.getY(), this.relativeVelocity.getZ())) { this.aimingData.setTarget(targetRef); } else { - HeadRotation headRotationComponent = componentAccessor.getComponent(ref, HeadRotation.getComponentType()); - - assert headRotationComponent != null; - - double xxzz = x * x + z * z; - double xxyyzz = xxzz + y * y; - Vector3f headRotation = headRotationComponent.getRotation(); - yaw = xxzz >= 1.0E-4 ? PhysicsMath.normalizeTurnAngle(PhysicsMath.headingFromDirection(x, z)) : headRotation.getYaw(); - pitch = xxyyzz >= 1.0E-4 ? PhysicsMath.pitchFromDirection(x, y, z) : headRotation.getPitch(); - this.aimingData.setOrientation(yaw, pitch); + double dotXZx = x * x + z * z; + double dotXYZ = dotXZx + y * y; + float yawx = dotXZx >= 1.0E-4 ? PhysicsMath.normalizeTurnAngle(PhysicsMath.headingFromDirection(x, z)) : lookRotation.getYaw(); + float pitchx = dotXYZ >= 1.0E-4 ? PhysicsMath.pitchFromDirection(x, y, z) : lookRotation.getPitch(); + this.aimingData.setOrientation(yawx, pitchx); this.aimingData.setTarget(null); } + if (this.debugAiming) { + Vector3f color = DebugUtils.COLOR_WHITE; + if (this.aimingData.haveOrientation()) { + color = DebugUtils.COLOR_GREEN; + } + + World world = ref.getStore().getExternalData().getWorld(); + DebugUtils.addSphere(world, this.targetPosition, color, 0.5, 0.1F); + if (this.startPosition.distanceTo(this.targetPosition) > 1.0E-4) { + DebugUtils.addArrow(world, this.startPosition, this.targetPosition.clone().subtract(this.startPosition).setLength(1.0), color, 0.1F, true); + } + } + desiredSteering.clearTranslation(); - desiredSteering.setYaw(yaw); - desiredSteering.setPitch(pitch); + desiredSteering.setYaw(this.aimingData.getYaw()); + desiredSteering.setPitch(this.aimingData.getPitch()); desiredSteering.setRelativeTurnSpeed(this.relativeTurnSpeed); return true; } else { @@ -187,4 +236,15 @@ public class HeadMotionAim extends HeadMotionBase { return true; } } + + @Override + public void registerWithSupport(Role role) { + super.registerWithSupport(role); + role.getDebugSupport().registerDebugFlagsListener(this); + } + + @Override + public void onDebugFlagsChanged(EnumSet newFlags) { + this.debugAiming = newFlags.contains(RoleDebugFlags.VisAiming); + } } diff --git a/src/com/hypixel/hytale/server/npc/corecomponents/entity/SensorEntityBase.java b/src/com/hypixel/hytale/server/npc/corecomponents/entity/SensorEntityBase.java index 5b228774..afb8fdc5 100644 --- a/src/com/hypixel/hytale/server/npc/corecomponents/entity/SensorEntityBase.java +++ b/src/com/hypixel/hytale/server/npc/corecomponents/entity/SensorEntityBase.java @@ -22,6 +22,7 @@ import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSenso import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.movement.controllers.MotionController; import com.hypixel.hytale.server.npc.role.Role; +import com.hypixel.hytale.server.npc.role.support.DebugSupport; import com.hypixel.hytale.server.npc.sensorinfo.EntityPositionProvider; import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider; import com.hypixel.hytale.server.npc.util.IEntityByPriorityFilter; @@ -50,6 +51,8 @@ public abstract class SensorEntityBase extends SensorWithEntityFilters { protected final ISensorEntityCollector collector; protected int ownRole; protected final EntityPositionProvider positionProvider = new EntityPositionProvider(); + protected int currentVisSensorColorIndex = -1; + protected final float visViewAngle; public SensorEntityBase(@Nonnull BuilderSensorEntityBase builder, ISensorEntityPrioritiser prioritiser, @Nonnull BuilderSupport builderSupport) { super(builder, builder.getFilters(builderSupport, prioritiser, ComponentContext.SensorEntity)); @@ -63,12 +66,14 @@ public abstract class SensorEntityBase extends SensorWithEntityFilters { this.ignoredTargetSlot = builder.getIgnoredTargetSlot(builderSupport); this.prioritiser = prioritiser; this.collector = builder.getCollector(builderSupport); + this.visViewAngle = this.findViewAngleFromFilters(); } @Override public boolean matches(@Nonnull Ref ref, @Nonnull Role role, double dt, @Nonnull Store store) { if (!super.matches(ref, role, dt, store)) { this.positionProvider.clear(); + this.currentVisSensorColorIndex = -1; return false; } else { TransformComponent transformComponent = store.getComponent(ref, TRANSFORM_COMPONENT_TYPE); @@ -77,6 +82,13 @@ public abstract class SensorEntityBase extends SensorWithEntityFilters { Vector3d position = transformComponent.getPosition(); this.ownRole = role.getRoleIndex(); + DebugSupport debugSupport = role.getDebugSupport(); + if (debugSupport.isVisSensorRanges()) { + this.currentVisSensorColorIndex = debugSupport.recordSensorRange(this.range, this.minRange, this.visViewAngle); + } else { + this.currentVisSensorColorIndex = -1; + } + if (this.ignoredTargetSlot == Integer.MIN_VALUE || this.ignoredTargetSlot != this.lockedTargetSlot) { Ref targetRef = this.filterLockedEntity(ref, position, role, store); if (targetRef != null) { @@ -281,23 +293,32 @@ public abstract class SensorEntityBase extends SensorWithEntityFilters { @Nonnull Ref targetRef, @Nonnull Role role, @Nonnull Store store, - @Nonnull IEntityByPriorityFilter playerPrioritiser + @Nonnull IEntityByPriorityFilter entityPrioritiser ) { - if (!this.filterEntity(ref, targetRef, role, store)) { + boolean filterMatch = this.filterEntity(ref, targetRef, role, store); + if (!filterMatch) { this.collector.collectNonMatching(targetRef, store); + this.recordEntityVisData(targetRef, role, false); return false; } else { - boolean match = playerPrioritiser.test(ref, targetRef, store); + boolean match = entityPrioritiser.test(ref, targetRef, store); if (match) { this.collector.collectMatching(ref, targetRef, store); } else { this.collector.collectNonMatching(targetRef, store); } + this.recordEntityVisData(targetRef, role, match); return this.collector.terminateOnFirstMatch() && match; } } + private void recordEntityVisData(@Nonnull Ref targetRef, @Nonnull Role role, boolean matched) { + if (this.currentVisSensorColorIndex >= 0) { + role.getDebugSupport().recordEntityCheck(targetRef, this.currentVisSensorColorIndex, matched); + } + } + @Nullable protected Ref findPlayerOrEntity( @Nonnull Ref ref, @Nonnull Vector3d position, @Nonnull Role role, @Nonnull Store store diff --git a/src/com/hypixel/hytale/server/npc/corecomponents/entity/filters/EntityFilterViewSector.java b/src/com/hypixel/hytale/server/npc/corecomponents/entity/filters/EntityFilterViewSector.java index 9ea73764..af3af7e3 100644 --- a/src/com/hypixel/hytale/server/npc/corecomponents/entity/filters/EntityFilterViewSector.java +++ b/src/com/hypixel/hytale/server/npc/corecomponents/entity/filters/EntityFilterViewSector.java @@ -48,4 +48,8 @@ public class EntityFilterViewSector extends EntityFilterBase { public int cost() { return 300; } + + public float getViewAngle() { + return this.viewCone; + } } diff --git a/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/Condition.java b/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/Condition.java index 93d3272c..534f86d4 100644 --- a/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/Condition.java +++ b/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/Condition.java @@ -42,20 +42,26 @@ public abstract class Condition implements JsonAssetWithMap CODEC = new AssetCodecMapCodec<>( Codec.STRING, (t, k) -> t.id = k, t -> t.id, (t, data) -> t.data = data, t -> t.data ); + @Nonnull public static final BuilderCodec BASE_CODEC = BuilderCodec.abstractBuilder(Condition.class) .afterDecode(condition -> condition.reference = new WeakReference<>(condition)) .build(); + @Nonnull public static final Codec CHILD_ASSET_CODEC = new ContainedAssetCodec<>(Condition.class, CODEC); + @Nonnull public static final Codec CHILD_ASSET_CODEC_ARRAY = new ArrayCodec<>(CHILD_ASSET_CODEC, String[]::new); + @Nonnull public static final ValidatorCache VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(Condition::getAssetStore)); private static AssetStore> ASSET_STORE; protected AssetExtraInfo.Data data; protected String id; protected WeakReference reference; + @Nonnull public static AssetStore> getAssetStore() { if (ASSET_STORE == null) { ASSET_STORE = AssetRegistry.getAssetStore(Condition.class); diff --git a/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/ScaledCurveCondition.java b/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/ScaledCurveCondition.java index c7cdd435..8884712f 100644 --- a/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/ScaledCurveCondition.java +++ b/src/com/hypixel/hytale/server/npc/decisionmaker/core/conditions/base/ScaledCurveCondition.java @@ -12,6 +12,7 @@ import com.hypixel.hytale.server.npc.decisionmaker.core.EvaluationContext; import javax.annotation.Nonnull; public abstract class ScaledCurveCondition extends Condition { + @Nonnull public static final BuilderCodec ABSTRACT_CODEC = BuilderCodec.abstractBuilder(ScaledCurveCondition.class, BASE_CODEC) .appendInherited( new KeyedCodec<>("Curve", ScaledResponseCurve.CODEC), diff --git a/src/com/hypixel/hytale/server/npc/instructions/Instruction.java b/src/com/hypixel/hytale/server/npc/instructions/Instruction.java index 56198a0d..c75171a3 100644 --- a/src/com/hypixel/hytale/server/npc/instructions/Instruction.java +++ b/src/com/hypixel/hytale/server/npc/instructions/Instruction.java @@ -321,7 +321,7 @@ public class Instruction implements RoleStateChange, IAnnotatedComponentCollecti } if (this.sensor.matches(ref, role, dt, store)) { - if (!this.treeMode && !this.continueAfter) { + if (!this.treeMode && !this.continueAfter && !this.invertTreeModeResult) { role.notifySensorMatch(); } @@ -406,14 +406,16 @@ public class Instruction implements RoleStateChange, IAnnotatedComponentCollecti } public void onMatched(@Nonnull Role role) { - if (this.treeMode) { + if (this.treeMode || this.invertTreeModeResult) { this.parentTreeModeStep = role.swapTreeModeSteps(this); - this.continueAfter = true; + if (this.treeMode) { + this.continueAfter = true; + } } } public void onCompleted(@Nonnull Role role) { - if (this.treeMode) { + if (this.treeMode || this.invertTreeModeResult) { role.swapTreeModeSteps(this.parentTreeModeStep); if (this.parentTreeModeStep != null) { if (this.continueAfter == this.invertTreeModeResult) { diff --git a/src/com/hypixel/hytale/server/npc/movement/controllers/MotionController.java b/src/com/hypixel/hytale/server/npc/movement/controllers/MotionController.java index 2e97cece..650287f5 100644 --- a/src/com/hypixel/hytale/server/npc/movement/controllers/MotionController.java +++ b/src/com/hypixel/hytale/server/npc/movement/controllers/MotionController.java @@ -16,10 +16,13 @@ import com.hypixel.hytale.server.npc.movement.MovementState; import com.hypixel.hytale.server.npc.movement.NavState; import com.hypixel.hytale.server.npc.movement.Steering; import com.hypixel.hytale.server.npc.role.Role; +import com.hypixel.hytale.server.npc.role.RoleDebugFlags; +import com.hypixel.hytale.server.npc.role.support.DebugSupport; +import java.util.EnumSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; -public interface MotionController { +public interface MotionController extends DebugSupport.DebugFlagsChangeListener { String getType(); Role getRole(); @@ -216,6 +219,10 @@ public interface MotionController { } } + @Override + default void onDebugFlagsChanged(EnumSet newFlags) { + } + static { if (.$assertionsDisabled) { } diff --git a/src/com/hypixel/hytale/server/npc/movement/controllers/MotionControllerBase.java b/src/com/hypixel/hytale/server/npc/movement/controllers/MotionControllerBase.java index 1cca3a83..2063de61 100644 --- a/src/com/hypixel/hytale/server/npc/movement/controllers/MotionControllerBase.java +++ b/src/com/hypixel/hytale/server/npc/movement/controllers/MotionControllerBase.java @@ -49,6 +49,7 @@ import com.hypixel.hytale.server.npc.role.Role; import com.hypixel.hytale.server.npc.role.RoleDebugFlags; import com.hypixel.hytale.server.npc.util.NPCPhysicsMath; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.function.BiPredicate; @@ -1040,10 +1041,6 @@ public abstract class MotionControllerBase implements MotionController { } } - protected boolean isDebugMode(RoleDebugFlags mode) { - return this.getRole() != null && this.getRole().getDebugSupport().getDebugFlags().contains(mode); - } - public boolean isProcessTriggersHasMoved() { return this.processTriggersHasMoved; } @@ -1052,16 +1049,21 @@ public abstract class MotionControllerBase implements MotionController { return !componentAccessor.getArchetype(ref).contains(DeathComponent.getComponentType()); } + @Override + public void onDebugFlagsChanged(EnumSet newFlags) { + MotionController.super.onDebugFlagsChanged(newFlags); + this.debugModeSteer = newFlags.contains(RoleDebugFlags.MotionControllerSteer); + this.debugModeMove = newFlags.contains(RoleDebugFlags.MotionControllerMove); + this.debugModeCollisions = newFlags.contains(RoleDebugFlags.Collisions); + this.debugModeBlockCollisions = newFlags.contains(RoleDebugFlags.BlockCollisions); + this.debugModeProbeBlockCollisions = newFlags.contains(RoleDebugFlags.ProbeBlockCollisions); + this.debugModeValidatePositions = newFlags.contains(RoleDebugFlags.ValidatePositions); + this.debugModeOverlaps = newFlags.contains(RoleDebugFlags.Overlaps); + this.debugModeValidateMath = newFlags.contains(RoleDebugFlags.ValidateMath); + } + @Override public void activate() { - this.debugModeSteer = this.isDebugMode(RoleDebugFlags.MotionControllerSteer); - this.debugModeMove = this.isDebugMode(RoleDebugFlags.MotionControllerMove); - this.debugModeCollisions = this.isDebugMode(RoleDebugFlags.Collisions); - this.debugModeBlockCollisions = this.isDebugMode(RoleDebugFlags.BlockCollisions); - this.debugModeProbeBlockCollisions = this.isDebugMode(RoleDebugFlags.ProbeBlockCollisions); - this.debugModeValidatePositions = this.isDebugMode(RoleDebugFlags.ValidatePositions); - this.debugModeOverlaps = this.isDebugMode(RoleDebugFlags.Overlaps); - this.debugModeValidateMath = this.isDebugMode(RoleDebugFlags.ValidateMath); this.resetObstructedFlags(); this.resetNavState(); } diff --git a/src/com/hypixel/hytale/server/npc/role/Role.java b/src/com/hypixel/hytale/server/npc/role/Role.java index 024db349..dc07df82 100644 --- a/src/com/hypixel/hytale/server/npc/role/Role.java +++ b/src/com/hypixel/hytale/server/npc/role/Role.java @@ -54,6 +54,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import java.util.function.Supplier; import java.util.logging.Level; import javax.annotation.Nonnull; @@ -562,6 +563,11 @@ public class Role implements IAnnotatedComponentCollection { @Nonnull NPCEntity npcComponent, @Nonnull Map motionControllers, @Nullable String initialMotionController ) { this.motionControllers = motionControllers; + + for (Entry entry : this.motionControllers.entrySet()) { + this.debugSupport.registerDebugFlagsListener(entry.getValue()); + } + this.updateMotionControllers(null, null, null, null); if (!this.motionControllers.isEmpty()) { if (initialMotionController != null && this.setActiveMotionController(null, npcComponent, initialMotionController, null)) { @@ -620,6 +626,10 @@ public class Role implements IAnnotatedComponentCollection { protected void computeActionsAndSteering( @Nonnull Ref ref, double tickTime, @Nonnull Steering bodySteering, @Nonnull Steering headSteering, @Nonnull Store store ) { + if (this.debugSupport.isVisSensorRanges()) { + this.debugSupport.beginSensorVisualization(); + } + boolean isDead = store.getArchetype(ref).contains(DeathComponent.getComponentType()); if (isDead) { if (this.deathInstruction != null) { diff --git a/src/com/hypixel/hytale/server/npc/role/RoleDebugDisplay.java b/src/com/hypixel/hytale/server/npc/role/RoleDebugDisplay.java index 81e80a8f..fa35da9b 100644 --- a/src/com/hypixel/hytale/server/npc/role/RoleDebugDisplay.java +++ b/src/com/hypixel/hytale/server/npc/role/RoleDebugDisplay.java @@ -11,6 +11,7 @@ import com.hypixel.hytale.protocol.MovementStates; import com.hypixel.hytale.server.core.entity.movement.MovementStatesComponent; import com.hypixel.hytale.server.core.entity.nameplate.Nameplate; import com.hypixel.hytale.server.core.inventory.Inventory; +import com.hypixel.hytale.server.core.modules.debug.DebugUtils; import com.hypixel.hytale.server.core.modules.entity.component.ActiveAnimationComponent; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap; @@ -48,6 +49,7 @@ public class RoleDebugDisplay { protected boolean debugDisplaySpeed; protected boolean debugDisplayInternalId; protected boolean debugDisplayName; + protected boolean debugVisMarkedTargets; @Nonnull protected StringBuilder debugDisplay = new StringBuilder(20); @@ -233,6 +235,24 @@ public class RoleDebugDisplay { this.debugDisplay.append(" SPD:").append(MathUtil.round(velocityComponent.getSpeed(), 1)); } + if (this.debugVisMarkedTargets) { + MarkedEntitySupport markedEntitySupport = role.getMarkedEntitySupport(); + Ref[] entityTargets = markedEntitySupport.getEntityTargets(); + + for (int slotIndex = 0; slotIndex < entityTargets.length; slotIndex++) { + Ref targetRef = entityTargets[slotIndex]; + if (targetRef != null && targetRef.isValid()) { + String colorName = DebugUtils.INDEXED_COLOR_NAMES[slotIndex % DebugUtils.INDEXED_COLOR_NAMES.length]; + String slotName = markedEntitySupport.getSlotName(slotIndex); + if (!this.debugDisplay.isEmpty()) { + this.debugDisplay.append(' '); + } + + this.debugDisplay.append(colorName).append('(').append(slotName).append(')'); + } + } + } + if (!this.debugDisplay.isEmpty()) { Nameplate nameplateComponent = archetypeChunk.getComponent(index, Nameplate.getComponentType()); if (nameplateComponent != null) { @@ -247,7 +267,7 @@ public class RoleDebugDisplay { } @Nullable - public static RoleDebugDisplay create(@Nonnull EnumSet debugFlags) { + public static RoleDebugDisplay create(@Nonnull EnumSet debugFlags, @Nullable RoleDebugDisplay existingDisplay) { boolean debugDisplayState = debugFlags.contains(RoleDebugFlags.DisplayState); boolean debugDisplayTime = debugFlags.contains(RoleDebugFlags.DisplayTime); boolean debugDisplayFlock = debugFlags.contains(RoleDebugFlags.DisplayFlock); @@ -262,6 +282,7 @@ public class RoleDebugDisplay { boolean debugDisplaySpeed = debugFlags.contains(RoleDebugFlags.DisplaySpeed); boolean debugDisplayName = debugFlags.contains(RoleDebugFlags.DisplayName); boolean debugDisplayInternalId = debugFlags.contains(RoleDebugFlags.DisplayInternalId); + boolean debugVisMarkedTargets = debugFlags.contains(RoleDebugFlags.VisMarkedTargets); if (!debugDisplayInternalId && !debugDisplayState && !debugDisplayFlock @@ -275,10 +296,11 @@ public class RoleDebugDisplay { && !debugDisplayHP && !debugDisplaySpeed && !debugDisplayName - && !debugDisplayStamina) { + && !debugDisplayStamina + && !debugVisMarkedTargets) { return null; } else { - RoleDebugDisplay debugDisplay = new RoleDebugDisplay(); + RoleDebugDisplay debugDisplay = existingDisplay != null ? existingDisplay : new RoleDebugDisplay(); debugDisplay.debugDisplayState = debugDisplayState; debugDisplay.debugDisplayTime = debugDisplayTime; debugDisplay.debugDisplayFlock = debugDisplayFlock; @@ -293,6 +315,7 @@ public class RoleDebugDisplay { debugDisplay.debugDisplaySpeed = debugDisplaySpeed; debugDisplay.debugDisplayInternalId = debugDisplayInternalId; debugDisplay.debugDisplayName = debugDisplayName; + debugDisplay.debugVisMarkedTargets = debugVisMarkedTargets; return debugDisplay; } } diff --git a/src/com/hypixel/hytale/server/npc/role/RoleDebugFlags.java b/src/com/hypixel/hytale/server/npc/role/RoleDebugFlags.java index b831ca85..6dd395f2 100644 --- a/src/com/hypixel/hytale/server/npc/role/RoleDebugFlags.java +++ b/src/com/hypixel/hytale/server/npc/role/RoleDebugFlags.java @@ -37,6 +37,9 @@ public enum RoleDebugFlags implements Supplier { ValidateMath("Validate (some) math computations in movement"), VisAvoidance("Visualize avoidance vectors"), VisSeparation("Visualize separation vector"), + VisAiming("Visualize aiming"), + VisMarkedTargets("Visualize arrows to marked targets"), + VisSensorRanges("Visualize entity sensor detection ranges"), BeaconMessages("Enable debugging of beacon message sending and receiving"); private static final RoleDebugFlags.RoleDebugPreset[] presets = new RoleDebugFlags.RoleDebugPreset[]{ @@ -47,6 +50,7 @@ public enum RoleDebugFlags implements Supplier { new RoleDebugFlags.RoleDebugPreset("valid", EnumSet.of(MotionControllerMove, MotionControllerSteer, Collisions, ValidatePositions)), new RoleDebugFlags.RoleDebugPreset("block", EnumSet.of(MotionControllerMove, MotionControllerSteer, Collisions, BlockCollisions)), new RoleDebugFlags.RoleDebugPreset("visDist", EnumSet.of(VisAvoidance, VisSeparation)), + new RoleDebugFlags.RoleDebugPreset("visSensorInfo", EnumSet.of(VisMarkedTargets, VisSensorRanges)), new RoleDebugFlags.RoleDebugPreset( "display", EnumSet.of( diff --git a/src/com/hypixel/hytale/server/npc/role/support/DebugSupport.java b/src/com/hypixel/hytale/server/npc/role/support/DebugSupport.java index 20d7ee02..49a1e5c9 100644 --- a/src/com/hypixel/hytale/server/npc/role/support/DebugSupport.java +++ b/src/com/hypixel/hytale/server/npc/role/support/DebugSupport.java @@ -1,11 +1,17 @@ package com.hypixel.hytale.server.npc.role.support; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.instructions.Sensor; import com.hypixel.hytale.server.npc.role.RoleDebugDisplay; import com.hypixel.hytale.server.npc.role.RoleDebugFlags; import com.hypixel.hytale.server.npc.role.builders.BuilderRole; +import java.util.ArrayList; import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -24,6 +30,13 @@ public class DebugSupport { protected boolean traceFail; protected boolean traceSensorFails; protected Sensor lastFailingSensor; + protected List debugFlagsChangeListeners = new ArrayList<>(); + protected boolean visSensorRanges; + protected int currentSensorColorIndex; + @Nullable + protected List sensorVisDataList; + @Nullable + protected Map, List> entityVisDataMap; public DebugSupport(NPCEntity parent, @Nonnull BuilderRole builder) { this.parent = parent; @@ -91,7 +104,8 @@ public class DebugSupport { public void setDebugFlags(EnumSet debugFlags) { this.debugFlags = debugFlags; - this.activate(); + this.onDebugFlagsChanged(); + this.notifyDebugFlagsListeners(debugFlags); } public boolean isDebugFlagSet(RoleDebugFlags flag) { @@ -108,12 +122,88 @@ public class DebugSupport { return false; } - public void activate() { + protected void onDebugFlagsChanged() { this.debugRoleSteering = this.isDebugFlagSet(RoleDebugFlags.SteeringRole); this.debugMotionSteering = this.isDebugFlagSet(RoleDebugFlags.MotionControllerSteer); this.traceFail = this.isDebugFlagSet(RoleDebugFlags.TraceFail); this.traceSuccess = this.isDebugFlagSet(RoleDebugFlags.TraceSuccess); this.traceSensorFails = this.isDebugFlagSet(RoleDebugFlags.TraceSensorFailures); - this.debugDisplay = RoleDebugDisplay.create(this.debugFlags); + this.visSensorRanges = this.isDebugFlagSet(RoleDebugFlags.VisSensorRanges); + this.debugDisplay = RoleDebugDisplay.create(this.debugFlags, this.debugDisplay); + } + + public void registerDebugFlagsListener(DebugSupport.DebugFlagsChangeListener listener) { + this.debugFlagsChangeListeners.add(listener); + } + + public void notifyDebugFlagsListeners(EnumSet flags) { + for (DebugSupport.DebugFlagsChangeListener listener : this.debugFlagsChangeListeners) { + listener.onDebugFlagsChanged(flags); + } + } + + public boolean isVisSensorRanges() { + return this.visSensorRanges; + } + + public void beginSensorVisualization() { + this.currentSensorColorIndex = 0; + if (this.sensorVisDataList != null) { + this.sensorVisDataList.clear(); + } + + if (this.entityVisDataMap != null) { + for (List list : this.entityVisDataMap.values()) { + list.clear(); + } + } + } + + public int recordSensorRange(double range, double minRange, double viewAngle) { + if (this.sensorVisDataList == null) { + this.sensorVisDataList = new ArrayList<>(); + } + + int colorIndex = this.currentSensorColorIndex++; + this.sensorVisDataList.add(new DebugSupport.SensorVisData(range, minRange, colorIndex, viewAngle)); + return colorIndex; + } + + public void recordEntityCheck(@Nonnull Ref entityRef, int sensorColorIndex, boolean matched) { + if (this.entityVisDataMap == null) { + this.entityVisDataMap = new HashMap<>(); + } + + this.entityVisDataMap.computeIfAbsent(entityRef, k -> new ArrayList<>()).add(new DebugSupport.EntityVisData(sensorColorIndex, matched)); + } + + @Nullable + public List getSensorVisData() { + return this.sensorVisDataList; + } + + @Nullable + public Map, List> getEntityVisData() { + return this.entityVisDataMap; + } + + public boolean hasSensorVisData() { + return this.sensorVisDataList != null && !this.sensorVisDataList.isEmpty(); + } + + public void clearSensorVisData() { + if (this.sensorVisDataList != null) { + this.sensorVisDataList.clear(); + } + } + + public interface DebugFlagsChangeListener { + void onDebugFlagsChanged(EnumSet var1); + } + + public record EntityVisData(int sensorColorIndex, boolean matched) { + } + + public record SensorVisData(double range, double minRange, int colorIndex, double viewAngle) { } } diff --git a/src/com/hypixel/hytale/server/npc/role/support/StateSupport.java b/src/com/hypixel/hytale/server/npc/role/support/StateSupport.java index 28b486de..93db22b1 100644 --- a/src/com/hypixel/hytale/server/npc/role/support/StateSupport.java +++ b/src/com/hypixel/hytale/server/npc/role/support/StateSupport.java @@ -51,6 +51,7 @@ public class StateSupport { protected Set> interactablePlayers; protected Set> interactedPlayers; protected Map, String> contextualInteractions; + protected String lastHint; @Nullable protected Ref interactionIterationTarget; @Nullable @@ -318,7 +319,7 @@ public class StateSupport { if (showPrompt) { boolean hasComponent = store.getArchetype(entityRef).contains(Interactable.getComponentType()); if (interactable) { - boolean needsHint = !wasInteractable && hint != null; + boolean needsHint = hint != null && !hint.equals(this.lastHint); if (!hasComponent) { store.ensureComponent(entityRef, Interactable.getComponentType()); needsHint = hint != null; @@ -326,6 +327,7 @@ public class StateSupport { if (needsHint) { this.sendInteractionHintToPlayer(entityRef, playerReference, hint, store); + this.lastHint = hint; } } else if (hasComponent && this.interactablePlayers.isEmpty()) { store.removeComponent(entityRef, Interactable.getComponentType()); diff --git a/src/com/hypixel/hytale/server/npc/systems/RoleSystems.java b/src/com/hypixel/hytale/server/npc/systems/RoleSystems.java index c25c6bd2..3ea5417e 100644 --- a/src/com/hypixel/hytale/server/npc/systems/RoleSystems.java +++ b/src/com/hypixel/hytale/server/npc/systems/RoleSystems.java @@ -15,10 +15,15 @@ import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.HolderSystem; import com.hypixel.hytale.component.system.tick.EntityTickingSystem; import com.hypixel.hytale.component.system.tick.TickingSystem; +import com.hypixel.hytale.math.vector.Transform; +import com.hypixel.hytale.math.vector.Vector3d; +import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.protocol.GameMode; import com.hypixel.hytale.server.core.entity.Frozen; import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.modules.debug.DebugUtils; import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox; +import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; import com.hypixel.hytale.server.core.modules.entity.component.NewSpawnComponent; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; @@ -29,17 +34,22 @@ import com.hypixel.hytale.server.core.modules.entity.system.TransformSystems; import com.hypixel.hytale.server.core.modules.interaction.InteractionModule; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import com.hypixel.hytale.server.core.util.TargetUtil; import com.hypixel.hytale.server.npc.NPCPlugin; import com.hypixel.hytale.server.npc.components.StepComponent; import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.movement.controllers.MotionController; import com.hypixel.hytale.server.npc.role.Role; import com.hypixel.hytale.server.npc.role.RoleDebugDisplay; +import com.hypixel.hytale.server.npc.role.RoleDebugFlags; +import com.hypixel.hytale.server.npc.role.support.DebugSupport; import com.hypixel.hytale.server.npc.role.support.EntitySupport; import com.hypixel.hytale.server.npc.role.support.MarkedEntitySupport; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import java.util.logging.Level; import javax.annotation.Nonnull; @@ -308,7 +318,7 @@ public class RoleSystems { Role role = npcComponent.getRole(); role.getStateSupport().activate(); - role.getDebugSupport().activate(); + role.getDebugSupport().notifyDebugFlagsListeners(role.getDebugSupport().getDebugFlags()); ModelComponent modelComponent = holder.getComponent(this.modelComponentType); assert modelComponent != null; @@ -336,6 +346,9 @@ public class RoleSystems { } public static class RoleDebugSystem extends SteppableTickingSystem { + private static final float DEBUG_SHAPE_TIME = 0.1F; + private static final float SENSOR_VIS_OPACITY = 0.4F; + private static final double FULL_CIRCLE_EPSILON = 0.01; @Nonnull private final ComponentType npcComponentType; @Nonnull @@ -360,7 +373,7 @@ public class RoleSystems { @Nonnull @Override public Query getQuery() { - return this.npcComponentType; + return Query.and(this.npcComponentType, TransformComponent.getComponentType(), BoundingBox.getComponentType()); } @Override @@ -376,9 +389,153 @@ public class RoleSystems { assert npcComponent != null; Role role = npcComponent.getRole(); - RoleDebugDisplay debugDisplay = role.getDebugSupport().getDebugDisplay(); - if (debugDisplay != null) { - debugDisplay.display(role, index, archetypeChunk, commandBuffer); + if (role != null) { + DebugSupport debugSupport = role.getDebugSupport(); + RoleDebugDisplay debugDisplay = debugSupport.getDebugDisplay(); + if (debugDisplay != null) { + debugDisplay.display(role, index, archetypeChunk, commandBuffer); + } + + if (debugSupport.isDebugFlagSet(RoleDebugFlags.VisMarkedTargets)) { + renderMarkedTargetArrows(role, index, archetypeChunk, commandBuffer); + } + + if (debugSupport.hasSensorVisData()) { + Ref npcRef = archetypeChunk.getReferenceTo(index); + renderSensorVisualization(debugSupport, npcRef, commandBuffer); + } + } + } + + private static void renderMarkedTargetArrows( + @Nonnull Role role, int index, @Nonnull ArchetypeChunk archetypeChunk, @Nonnull CommandBuffer commandBuffer + ) { + Ref npcRef = archetypeChunk.getReferenceTo(index); + Transform npcLook = TargetUtil.getLook(npcRef, commandBuffer); + Vector3d npcEyePosition = npcLook.getPosition(); + World world = commandBuffer.getExternalData().getWorld(); + MarkedEntitySupport markedEntitySupport = role.getMarkedEntitySupport(); + Ref[] entityTargets = markedEntitySupport.getEntityTargets(); + + for (int slotIndex = 0; slotIndex < entityTargets.length; slotIndex++) { + Ref targetRef = entityTargets[slotIndex]; + if (targetRef != null && targetRef.isValid()) { + Transform targetLook = TargetUtil.getLook(targetRef, commandBuffer); + Vector3d targetEyePosition = targetLook.getPosition(); + Vector3d direction = new Vector3d( + targetEyePosition.x - npcEyePosition.x, targetEyePosition.y - npcEyePosition.y, targetEyePosition.z - npcEyePosition.z + ); + Vector3f color = DebugUtils.INDEXED_COLORS[slotIndex % DebugUtils.INDEXED_COLORS.length]; + DebugUtils.addArrow(world, npcEyePosition, direction, color, 0.1F, false); + } + } + } + + private static void renderSensorVisualization( + @Nonnull DebugSupport debugSupport, @Nonnull Ref npcRef, @Nonnull CommandBuffer commandBuffer + ) { + List sensorDataList = debugSupport.getSensorVisData(); + if (sensorDataList != null) { + TransformComponent transformComponent = commandBuffer.getComponent(npcRef, TransformComponent.getComponentType()); + + assert transformComponent != null; + + Vector3d npcPosition = transformComponent.getPosition(); + BoundingBox boundingBoxComponent = commandBuffer.getComponent(npcRef, BoundingBox.getComponentType()); + + assert boundingBoxComponent != null; + + double npcMidHeight = boundingBoxComponent.getBoundingBox().max.y / 2.0; + HeadRotation headRotation = commandBuffer.getComponent(npcRef, HeadRotation.getComponentType()); + double heading = headRotation != null ? headRotation.getRotation().getYaw() : transformComponent.getRotation().getYaw(); + sensorDataList.sort((a, b) -> Double.compare(b.range(), a.range())); + World world = commandBuffer.getExternalData().getWorld(); + double discStackOffset = 0.1; + + for (int i = 0; i < sensorDataList.size(); i++) { + DebugSupport.SensorVisData sensorData = sensorDataList.get(i); + Vector3f color = DebugUtils.INDEXED_COLORS[sensorData.colorIndex() % DebugUtils.INDEXED_COLORS.length]; + double height = npcPosition.y + npcMidHeight + i * 0.1; + if (sensorData.viewAngle() > 0.0 && sensorData.viewAngle() < 6.273185482025147) { + double sectorHeading = -heading + Math.PI; + DebugUtils.addSector( + world, + npcPosition.x, + height, + npcPosition.z, + sectorHeading, + sensorData.range(), + sensorData.viewAngle(), + sensorData.minRange(), + color, + 0.4F, + 0.1F, + false + ); + } else { + DebugUtils.addDisc(world, npcPosition.x, height, npcPosition.z, sensorData.range(), sensorData.minRange(), color, 0.4F, 0.1F, false); + } + } + + Map, List> entityDataMap = debugSupport.getEntityVisData(); + if (entityDataMap != null) { + double markerOffset = 0.3; + double sphereStackOffset = 0.3; + double defaultEntityHeight = 2.0; + + for (Entry, List> entry : entityDataMap.entrySet()) { + Ref entityRef = entry.getKey(); + List checks = entry.getValue(); + if (!checks.isEmpty() && entityRef.isValid()) { + TransformComponent entityTransform = commandBuffer.getComponent(entityRef, TransformComponent.getComponentType()); + if (entityTransform != null) { + Vector3d entityPosition = entityTransform.getPosition(); + BoundingBox entityBoundingBox = commandBuffer.getComponent(entityRef, BoundingBox.getComponentType()); + double entityHeight = entityBoundingBox != null ? entityBoundingBox.getBoundingBox().max.y : 2.0; + double markerBaseHeight = entityHeight + 0.3; + boolean anyMatched = false; + + for (DebugSupport.EntityVisData check : checks) { + if (check.matched()) { + anyMatched = true; + break; + } + } + + int sphereCount = 0; + + for (DebugSupport.EntityVisData checkx : checks) { + if (checkx.matched()) { + Vector3f sensorColor = DebugUtils.INDEXED_COLORS[checkx.sensorColorIndex() % DebugUtils.INDEXED_COLORS.length]; + double sphereHeight = markerBaseHeight + sphereCount * 0.3; + DebugUtils.addSphere(world, entityPosition.x, entityPosition.y + sphereHeight, entityPosition.z, sensorColor, 0.2, 0.1F); + sphereCount++; + } + } + + if (!anyMatched) { + DebugUtils.addCube(world, entityPosition.x, entityPosition.y + markerBaseHeight, entityPosition.z, DebugUtils.COLOR_GRAY, 0.2, 0.1F); + } + + DebugUtils.addLine( + world, + npcPosition.x, + npcPosition.y + npcMidHeight, + npcPosition.z, + entityPosition.x, + entityPosition.y + markerBaseHeight, + entityPosition.z, + DebugUtils.COLOR_GRAY, + 0.03, + 0.1F, + false + ); + } + } + } + } + + debugSupport.clearSensorVisData(); } } } diff --git a/src/com/hypixel/hytale/server/npc/util/AimingData.java b/src/com/hypixel/hytale/server/npc/util/AimingData.java index 03ccb410..b460d804 100644 --- a/src/com/hypixel/hytale/server/npc/util/AimingData.java +++ b/src/com/hypixel/hytale/server/npc/util/AimingData.java @@ -69,10 +69,6 @@ public class AimingData implements ExtraInfoProvider { return this.yaw[flatTrajectory ? 0 : 1]; } - public boolean isBallistic() { - return this.ballisticData != null; - } - @Nullable public BallisticData getBallisticData() { return this.ballisticData; @@ -121,7 +117,7 @@ public class AimingData implements ExtraInfoProvider { } } - public void setTarget(Ref ref) { + public void setTarget(@Nullable Ref ref) { this.target = ref; } @@ -146,7 +142,7 @@ public class AimingData implements ExtraInfoProvider { double d2 = xxzz + y * y; if (d2 < 0.01) { return this.haveSolution = false; - } else if (!this.isBallistic()) { + } else if (this.ballisticData == null) { this.yaw[0] = this.yaw[1] = PhysicsMath.normalizeTurnAngle(PhysicsMath.headingFromDirection(x, z)); this.pitch[0] = this.pitch[1] = PhysicsMath.pitchFromDirection(x, y, z); return this.haveSolution = true; @@ -163,7 +159,10 @@ public class AimingData implements ExtraInfoProvider { double v2 = NPCPhysicsMath.dotProduct(vx, vy, vz); if (v2 < 1.0E-4) { - if (this.haveSolution = this.computeStaticSolution(Math.sqrt(xxzz), y)) { + this.haveSolution = AimingHelper.computePitch( + Math.sqrt(xxzz), y, this.ballisticData.getMuzzleVelocity(), this.ballisticData.getGravity(), this.pitch + ); + if (this.haveSolution) { this.yaw[0] = this.yaw[1] = PhysicsMath.normalizeTurnAngle(PhysicsMath.headingFromDirection(x, z)); } @@ -233,7 +232,7 @@ public class AimingData implements ExtraInfoProvider { return false; } else { double differenceYaw = NPCPhysicsMath.turnAngle(yaw, this.getYaw()); - if (!this.isBallistic()) { + if (this.ballisticData == null) { return -hitAngle <= differenceYaw && differenceYaw <= hitAngle; } else { double differencePitch = NPCPhysicsMath.turnAngle(pitch, this.getPitch()); @@ -265,8 +264,4 @@ public class AimingData implements ExtraInfoProvider { this.pitchAdjustOffset = false; this.haveAttacked = false; } - - protected boolean computeStaticSolution(double dx, double dy) { - return this.haveSolution = AimingHelper.computePitch(dx, dy, this.ballisticData.getMuzzleVelocity(), this.ballisticData.getGravity(), this.pitch); - } } diff --git a/src/com/hypixel/hytale/server/spawning/commands/SpawnBeaconsCommand.java b/src/com/hypixel/hytale/server/spawning/commands/SpawnBeaconsCommand.java index 870e2375..6aa628d2 100644 --- a/src/com/hypixel/hytale/server/spawning/commands/SpawnBeaconsCommand.java +++ b/src/com/hypixel/hytale/server/spawning/commands/SpawnBeaconsCommand.java @@ -15,7 +15,7 @@ import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredAr import com.hypixel.hytale.server.core.command.system.arguments.types.AssetArgumentType; import com.hypixel.hytale.server.core.command.system.basecommands.AbstractCommandCollection; import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; -import com.hypixel.hytale.server.core.command.system.exceptions.GeneralCommandException; +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractTargetEntityCommand; import com.hypixel.hytale.server.core.entity.UUIDComponent; import com.hypixel.hytale.server.core.entity.nameplate.Nameplate; import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent; @@ -31,6 +31,7 @@ import com.hypixel.hytale.server.spawning.beacons.LegacySpawnBeaconEntity; import com.hypixel.hytale.server.spawning.beacons.SpawnBeacon; import com.hypixel.hytale.server.spawning.util.FloodFillPositionSelector; import com.hypixel.hytale.server.spawning.wrappers.BeaconSpawnWrapper; +import it.unimi.dsi.fastutil.objects.ObjectList; import javax.annotation.Nonnull; public class SpawnBeaconsCommand extends AbstractCommandCollection { @@ -103,11 +104,10 @@ public class SpawnBeaconsCommand extends AbstractCommandCollection { } } - private static class ManualTrigger extends AbstractPlayerCommand { - private static final Message MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NOT_BEACON = Message.translation( - "server.commands.spawning.beacons.trigger.notBeacon" + private static class ManualTrigger extends AbstractTargetEntityCommand { + private static final Message MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NO_BEACONS = Message.translation( + "server.commands.spawning.beacons.trigger.no_beacons" ); - private static final Message MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NO_SPOTS = Message.translation("server.commands.spawning.beacons.trigger.no_spots"); public ManualTrigger() { super("trigger", "server.commands.spawning.beacons.trigger.desc"); @@ -115,22 +115,40 @@ public class SpawnBeaconsCommand extends AbstractCommandCollection { @Override protected void execute( - @Nonnull CommandContext context, @Nonnull Store store, @Nonnull Ref ref, @Nonnull PlayerRef playerRef, @Nonnull World world + @Nonnull CommandContext context, @Nonnull ObjectList> entities, @Nonnull World world, @Nonnull Store store ) { - FloodFillPositionSelector positionSelectorComponent = store.getComponent(ref, FloodFillPositionSelector.getComponentType()); - if (positionSelectorComponent == null) { - throw new GeneralCommandException(MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NOT_BEACON); + if (entities.isEmpty()) { + context.sendMessage(MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NO_BEACONS); } else { - SpawnBeacon spawnBeaconComponent = store.getComponent(ref, SpawnBeacon.getComponentType()); - if (spawnBeaconComponent == null) { - throw new GeneralCommandException(MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NOT_BEACON); - } else { - if (!spawnBeaconComponent.manualTrigger(ref, positionSelectorComponent, ref, store)) { - context.sendMessage(MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NO_SPOTS); - } else { - context.sendMessage(Message.translation("server.commands.spawning.beacons.trigger.success")); + int count = 0; + + for (Ref ref : entities) { + if (ref != null && ref.isValid()) { + UUIDComponent uuid = store.getComponent(ref, UUIDComponent.getComponentType()); + if (uuid != null) { + FloodFillPositionSelector positionSelectorComponent = store.getComponent(ref, FloodFillPositionSelector.getComponentType()); + if (positionSelectorComponent != null) { + SpawnBeacon spawnBeaconComponent = store.getComponent(ref, SpawnBeacon.getComponentType()); + if (spawnBeaconComponent != null) { + if (!spawnBeaconComponent.manualTrigger(ref, positionSelectorComponent, ref, store)) { + Message message = Message.translation("server.commands.spawning.beacons.trigger.no_spots"); + message.param("id", uuid.getUuid().toString()); + context.sendMessage(message); + } else { + Message message = Message.translation("server.commands.spawning.beacons.trigger.success"); + message.param("id", uuid.getUuid().toString()); + context.sendMessage(message); + count++; + } + } + } + } } } + + if (count == 0) { + context.sendMessage(MESSAGE_COMMANDS_SPAWNING_BEACONS_TRIGGER_NO_BEACONS); + } } } } diff --git a/src/com/hypixel/hytale/server/worldgen/HytaleWorldGenProvider.java b/src/com/hypixel/hytale/server/worldgen/HytaleWorldGenProvider.java index 9b0b612a..c315d0a3 100644 --- a/src/com/hypixel/hytale/server/worldgen/HytaleWorldGenProvider.java +++ b/src/com/hypixel/hytale/server/worldgen/HytaleWorldGenProvider.java @@ -1,6 +1,5 @@ package com.hypixel.hytale.server.worldgen; -import com.hypixel.hytale.builtin.worldgen.WorldGenPlugin; import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.ExtraInfo; import com.hypixel.hytale.codec.KeyedCodec; @@ -14,8 +13,10 @@ import com.hypixel.hytale.server.core.universe.world.worldgen.WorldGenLoadExcept import com.hypixel.hytale.server.core.universe.world.worldgen.provider.IWorldGenProvider; import com.hypixel.hytale.server.worldgen.loader.ChunkGeneratorJsonLoader; import com.hypixel.hytale.server.worldgen.prefab.PrefabStoreRoot; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -23,7 +24,7 @@ public class HytaleWorldGenProvider implements IWorldGenProvider { public static final String ID = "Hytale"; public static final String DEFAULT_NAME = "Default"; public static final Semver MIN_VERSION = new Semver(0L, 0L, 0L); - public static final BuilderCodec CODEC = new HytaleWorldGenProvider.DefaultBuilderCodec( + public static final HytaleWorldGenProvider.WorldGenBuilderCodec CODEC = new HytaleWorldGenProvider.WorldGenBuilderCodec( BuilderCodec.builder(HytaleWorldGenProvider.class, HytaleWorldGenProvider::new) .documentation("The standard generator for Hytale.") .append(new KeyedCodec<>("Name", Codec.STRING), (config, s) -> config.name = s, config -> config.name) @@ -43,18 +44,31 @@ public class HytaleWorldGenProvider implements IWorldGenProvider { @Nullable private String path; + @Nonnull + public Semver getVersion() { + return this.version; + } + @Nonnull @Override public IWorldGen getGenerator() throws WorldGenLoadException { Path worldGenPath; if (this.path != null) { - worldGenPath = PathUtil.get(this.path); + worldGenPath = Path.of(this.path); + if (!PathUtil.isInTrustedRoot(worldGenPath)) { + throw new WorldGenLoadException("World gen path must be within a trusted directory: " + this.path); + } } else { worldGenPath = Universe.getWorldGenPath(); } if (!"Default".equals(this.name) || !Files.exists(worldGenPath.resolve("World.json"))) { - worldGenPath = worldGenPath.resolve(this.name); + Path resolved = PathUtil.resolvePathWithinDir(worldGenPath, this.name); + if (resolved == null) { + throw new WorldGenLoadException("Invalid world gen name: " + this.name); + } + + worldGenPath = resolved; } try { @@ -70,16 +84,29 @@ public class HytaleWorldGenProvider implements IWorldGenProvider { return "HytaleWorldGenProvider{name='" + this.name + "', version=" + this.version + ", path='" + this.path + "'}"; } - private static class DefaultBuilderCodec extends BuilderCodec { - protected DefaultBuilderCodec(@Nonnull BuilderCodec.BuilderBase builder) { + public static class WorldGenBuilderCodec extends BuilderCodec { + private final Object lock = new Object(); + private final Map versions = new Object2ObjectOpenHashMap<>(); + + protected WorldGenBuilderCodec(@Nonnull BuilderCodec.BuilderBase builder) { super(builder); } public HytaleWorldGenProvider getDefaultValue(ExtraInfo extraInfo) { HytaleWorldGenProvider value = new HytaleWorldGenProvider(); - value.version = WorldGenPlugin.get().getLatestVersion("Default", HytaleWorldGenProvider.MIN_VERSION); + synchronized (this.lock) { + value.version = this.versions.getOrDefault("Default", HytaleWorldGenProvider.MIN_VERSION); + } + this.afterDecode(value, extraInfo); return value; } + + public void setVersions(@Nonnull Map versions) { + synchronized (this.lock) { + this.versions.clear(); + this.versions.putAll(versions); + } + } } } diff --git a/src/com/hypixel/hytale/server/worldgen/loader/ChunkGeneratorJsonLoader.java b/src/com/hypixel/hytale/server/worldgen/loader/ChunkGeneratorJsonLoader.java index 2f54a052..1debbb98 100644 --- a/src/com/hypixel/hytale/server/worldgen/loader/ChunkGeneratorJsonLoader.java +++ b/src/com/hypixel/hytale/server/worldgen/loader/ChunkGeneratorJsonLoader.java @@ -6,6 +6,7 @@ import com.google.gson.JsonObject; import com.hypixel.hytale.common.map.IWeightedMap; import com.hypixel.hytale.common.map.WeightedMap; import com.hypixel.hytale.common.util.ArrayUtil; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.math.util.FastRandom; import com.hypixel.hytale.math.vector.Vector2i; import com.hypixel.hytale.procedurallib.file.FileIO; @@ -149,10 +150,15 @@ public class ChunkGeneratorJsonLoader extends Loader weightedMap = builder.build(); - Path maskFile = this.dataFolder.resolve(weightedMap.get(new FastRandom(this.seed.hashCode()))); - return (MaskProvider)(maskFile.getFileName().endsWith("Mask.json") - ? new ClimateMaskJsonLoader<>(this.seed, this.dataFolder, maskFile).load() - : new MaskProviderJsonLoader(this.seed, this.dataFolder, worldJson.get("Randomizer"), maskFile, worldSize, worldOffset).load()); + String maskName = weightedMap.get(new FastRandom(this.seed.hashCode())); + Path maskFile = PathUtil.resolvePathWithinDir(this.dataFolder, maskName); + if (maskFile == null) { + throw new Error("Invalid mask file path: " + maskName); + } else { + return (MaskProvider)(maskFile.getFileName().toString().endsWith("Mask.json") + ? new ClimateMaskJsonLoader<>(this.seed, this.dataFolder, maskFile).load() + : new MaskProviderJsonLoader(this.seed, this.dataFolder, worldJson.get("Randomizer"), maskFile, worldSize, worldOffset).load()); + } } @Nonnull diff --git a/src/com/hypixel/hytale/server/worldgen/loader/cave/CaveNodeTypeStorage.java b/src/com/hypixel/hytale/server/worldgen/loader/cave/CaveNodeTypeStorage.java index 7ba7b708..3942a67d 100644 --- a/src/com/hypixel/hytale/server/worldgen/loader/cave/CaveNodeTypeStorage.java +++ b/src/com/hypixel/hytale/server/worldgen/loader/cave/CaveNodeTypeStorage.java @@ -1,6 +1,7 @@ package com.hypixel.hytale.server.worldgen.loader.cave; import com.google.gson.JsonObject; +import com.hypixel.hytale.common.util.PathUtil; import com.hypixel.hytale.procedurallib.file.FileIO; import com.hypixel.hytale.procedurallib.json.JsonLoader; import com.hypixel.hytale.procedurallib.json.SeedString; @@ -57,13 +58,17 @@ public class CaveNodeTypeStorage { @Nonnull public CaveNodeType loadCaveNodeType(@Nonnull String name) { - Path file = this.caveFolder.resolve(String.format("%s.node.json", name.replace(".", File.separator))); - - try { - JsonObject caveNodeJson = FileIO.load(file, JsonLoader.JSON_OBJ_LOADER); - return this.loadCaveNodeType(name, caveNodeJson); - } catch (Throwable var4) { - throw new Error(String.format("Error while loading CaveNodeType %s for world generator from %s", name, file.toString()), var4); + String relativePath = String.format("%s.node.json", name.replace(".", File.separator)); + Path file = PathUtil.resolvePathWithinDir(this.caveFolder, relativePath); + if (file == null) { + throw new Error(String.format("Invalid cave node type name: %s", name)); + } else { + try { + JsonObject caveNodeJson = FileIO.load(file, JsonLoader.JSON_OBJ_LOADER); + return this.loadCaveNodeType(name, caveNodeJson); + } catch (Throwable var5) { + throw new Error(String.format("Error while loading CaveNodeType %s for world generator from %s", name, file.toString()), var5); + } } }