2026.02.06-0baf7c5aa

This commit is contained in:
Intege-rs
2026-02-06 23:08:15 -05:00
parent 72c1df79ca
commit 8988b1dc65
666 changed files with 10538 additions and 4740 deletions

View File

@@ -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 -> {

View File

@@ -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<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ComponentType<EntityStore, EntityStatMap> entityStatMapComponentType = EntityStatMap.getComponentType();
this.getEntityStoreRegistry().registerSystem(new CameraEffectSystem(playerRefComponentType, entityStatMapComponentType));
}
}

View File

@@ -23,10 +23,19 @@ import javax.annotation.Nullable;
public class CameraEffectSystem extends DamageEventSystem {
@Nonnull
private static final ComponentType<EntityStore, PlayerRef> PLAYER_REF_COMPONENT_TYPE = PlayerRef.getComponentType();
private static final ComponentType<EntityStore, EntityStatMap> ENTITY_STAT_MAP_COMPONENT_TYPE = EntityStatMap.getComponentType();
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private static final Query<EntityStore> QUERY = Query.and(PLAYER_REF_COMPONENT_TYPE, ENTITY_STAT_MAP_COMPONENT_TYPE);
private final ComponentType<EntityStore, EntityStatMap> entityStatMapComponentType;
@Nonnull
private final Query<EntityStore> query;
public CameraEffectSystem(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType, @Nonnull ComponentType<EntityStore, EntityStatMap> 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<EntityStore> getQuery() {
return QUERY;
return this.query;
}
public void handle(
@@ -47,7 +56,7 @@ public class CameraEffectSystem extends DamageEventSystem {
@Nonnull CommandBuffer<EntityStore> 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;

View File

@@ -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<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType = BlockModule.BlockStateInfo.getComponentType();
ComponentType<ChunkStore, BlockSection> blockSectionComponentType = BlockSection.getComponentType();
ComponentType<ChunkStore, ChunkSection> chunkSectionComponentType = ChunkSection.getComponentType();
ComponentType<EntityStore, UUIDComponent> 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);
}

View File

@@ -99,11 +99,23 @@ public class FarmingSystems {
}
public static class CoopResidentEntitySystem extends RefSystem<EntityStore> {
private static final ComponentType<EntityStore, CoopResidentComponent> COMPONENT_TYPE_COOP_RESIDENT = CoopResidentComponent.getComponentType();
@Nonnull
private final ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType;
@Nonnull
private final ComponentType<EntityStore, UUIDComponent> uuidComponentType;
public CoopResidentEntitySystem(
@Nonnull ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType,
@Nonnull ComponentType<EntityStore, UUIDComponent> uuidComponentType
) {
this.coopResidentComponentType = coopResidentComponentType;
this.uuidComponentType = uuidComponentType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return COMPONENT_TYPE_COOP_RESIDENT;
return this.coopResidentComponentType;
}
@Override
@@ -117,10 +129,10 @@ public class FarmingSystems {
@Nonnull Ref<EntityStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> 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<EntityStore> {
private static final ComponentType<EntityStore, CoopResidentComponent> COMPONENT_TYPE_COOP_RESIDENT = CoopResidentComponent.getComponentType();
@Nonnull
private final ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType;
public CoopResidentTicking(@Nonnull ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType) {
this.coopResidentComponentType = coopResidentComponentType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return COMPONENT_TYPE_COOP_RESIDENT;
return this.coopResidentComponentType;
}
@Override
@@ -174,11 +192,12 @@ public class FarmingSystems {
@Nonnull Store<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> 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<ChunkStore> {
@Nonnull
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), CoopBlock.getComponentType());
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<ChunkStore, CoopBlock> coopBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public OnCoopAdded(
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<ChunkStore, CoopBlock> coopBlockComponentType
) {
this.blockStateInfoComponentType = blockStateInfoComponentType;
this.coopBlockComponentType = coopBlockComponentType;
this.query = Query.and(blockStateInfoComponentType, coopBlockComponentType);
}
@Override
public void onEntityAdded(
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> getQuery() {
return QUERY;
return this.query;
}
}
public static class OnFarmBlockAdded extends RefSystem<ChunkStore> {
@Nonnull
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), FarmingBlock.getComponentType());
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public OnFarmBlockAdded(
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType
) {
this.blockStateInfoComponentType = blockStateInfoComponentType;
this.farmingBlockComponentType = farmingBlockComponentType;
this.query = Query.and(blockStateInfoComponentType, farmingBlockComponentType);
}
@Override
public void onEntityAdded(
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> getQuery() {
return QUERY;
return this.query;
}
}
public static class OnSoilAdded extends RefSystem<ChunkStore> {
@Nonnull
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), TilledSoilBlock.getComponentType());
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public OnSoilAdded(
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType
) {
this.blockStateInfoComponentType = blockStateInfoComponentType;
this.tilledSoilBlockComponentType = tilledSoilBlockComponentType;
this.query = Query.and(blockStateInfoComponentType, tilledSoilBlockComponentType);
}
@Override
public void onEntityAdded(
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> getQuery() {
return QUERY;
return this.query;
}
}
public static class Ticking extends EntityTickingSystem<ChunkStore> {
@Nonnull
private static final Query<ChunkStore> QUERY = Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType());
private final ComponentType<ChunkStore, BlockSection> blockSectionComponentType;
@Nonnull
private final ComponentType<ChunkStore, ChunkSection> chunkSectionComponentType;
@Nonnull
private final ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType;
@Nonnull
private final ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType;
@Nonnull
private final ComponentType<ChunkStore, CoopBlock> coopBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public Ticking(
@Nonnull ComponentType<ChunkStore, BlockSection> blockSectionComponentType,
@Nonnull ComponentType<ChunkStore, ChunkSection> chunkSectionComponentType,
@Nonnull ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType,
@Nonnull ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType,
@Nonnull ComponentType<ChunkStore, CoopBlock> 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<ChunkStore> store,
@Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> getQuery() {
return QUERY;
return this.query;
}
}
}

View File

@@ -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

View File

@@ -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<EntityStore, Player> playerComponentType = Player.getComponentType();
ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ComponentType<EntityStore, TransformComponent> 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<? extends Memory> codec = (BuilderCodec<? extends Memory>)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<Dependency<EntityStore>> dependencies = Set.of(new SystemDependency<>(Order.AFTER, PlayerSystems.PlayerSpawnedSystem.class));
@Nonnull
private final Query<EntityStore> query = Query.and(Player.getComponentType(), PlayerRef.getComponentType());
private final ComponentType<EntityStore, Player> playerComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType;
@Nonnull
private final Query<EntityStore> query;
public PlayerAddedSystem(
@Nonnull ComponentType<EntityStore, Player> playerComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, PlayerMemories> 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<EntityStore> ref, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> 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));

View File

@@ -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<EntityStore> {
@Nonnull
public static final Query<EntityStore> QUERY = Query.and(
TransformComponent.getComponentType(), Player.getComponentType(), PlayerRef.getComponentType(), PlayerMemories.getComponentType()
);
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final ComponentType<EntityStore, Player> playerComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType;
@Nonnull
private final Query<EntityStore> query;
private final double radius;
public GatherMemoriesSystem(double radius) {
public GatherMemoriesSystem(
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, Player> playerComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, PlayerMemories> 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<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> 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<Ref<EntityStore>> 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<EntityStore> 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<EntityStore> getQuery() {
return QUERY;
return this.query;
}
}
}

View File

@@ -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<EntityStore> {
@Nonnull
public static final Query<EntityStore> QUERY = Query.and(PlayerRef.getComponentType(), TransformComponent.getComponentType());
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final Query<EntityStore> query;
public TempleRespawnPlayersSystem() {
public TempleRespawnPlayersSystem(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType, @Nonnull ComponentType<EntityStore, TransformComponent> 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<EntityStore>
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<EntityStore>
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<EntityStore> getQuery() {
return QUERY;
return this.query;
}
}

View File

@@ -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<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType = LegacySpawnBeaconEntity.getComponentType();
ComponentType<EntityStore, NPCEntity> 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)

View File

@@ -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<EntityStore, NPCEntity> npcEntityComponentType;
@Nonnull
private final ResourceType<EntityStore, KillTrackerResource> killTrackerResourceType;
public KillTrackerSystem(
@Nonnull ComponentType<EntityStore, NPCEntity> npcEntityComponentType, @Nonnull ResourceType<EntityStore, KillTrackerResource> killTrackerResourceType
) {
this.npcEntityComponentType = npcEntityComponentType;
this.killTrackerResourceType = killTrackerResourceType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return NPCEntity.getComponentType();
return this.npcEntityComponentType;
}
public void onComponentAdded(
@Nonnull Ref<EntityStore> ref, @Nonnull DeathComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> 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<KillTaskTransaction> killTasks = killTrackerResource.getKillTasks();
Damage deathInfo = component.getDeathInfo();
if (deathInfo != null) {

View File

@@ -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<EntityStore> {
@Nullable
@Nonnull
private final ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType;
public SpawnBeaconCheckRemovalSystem(@Nonnull ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType) {
this.legacySpawnBeaconEntityComponentType = legacySpawnBeaconEntityComponentType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return LegacySpawnBeaconEntity.getComponentType();
return this.legacySpawnBeaconEntityComponentType;
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(LegacySpawnBeaconEntity.getComponentType());
LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(this.legacySpawnBeaconEntityComponentType);
assert spawnBeaconComponent != null;

View File

@@ -19,12 +19,14 @@ import javax.annotation.Nonnull;
public class NPCReputationHolderSystem extends HolderSystem<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType;
@Nonnull
private final ComponentType<EntityStore, NPCEntity> npcEntityComponentType;
@Nonnull
private final Query<EntityStore> query;
public NPCReputationHolderSystem(
@Nonnull ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType, ComponentType<EntityStore, NPCEntity> npcEntityComponentType
@Nonnull ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType,
@Nonnull ComponentType<EntityStore, NPCEntity> npcEntityComponentType
) {
this.reputationGroupComponentType = reputationGroupComponentType;
this.npcEntityComponentType = npcEntityComponentType;

View File

@@ -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<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
entityStoreRegistry.registerSystem(new ReputationAttitudeSystem());
entityStoreRegistry.registerSystem(new NPCReputationHolderSystem(ReputationGroupComponent.getComponentType(), NPCEntity.getComponentType()));
ResourceType<EntityStore, Blackboard> blackboardResourceType = Blackboard.getResourceType();
ComponentType<EntityStore, Player> playerComponentType = Player.getComponentType();
ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType = ReputationGroupComponent.getComponentType();
ComponentType<EntityStore, NPCEntity> npcEntityComponentType = NPCEntity.getComponentType();
entityStoreRegistry.registerSystem(new ReputationAttitudeSystem(blackboardResourceType, playerComponentType));
entityStoreRegistry.registerSystem(new NPCReputationHolderSystem(reputationGroupComponentType, npcEntityComponentType));
}
}

View File

@@ -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<EntityStore> {
@Nonnull
private final ResourceType<EntityStore, Blackboard> resourceType = Blackboard.getResourceType();
private final ResourceType<EntityStore, Blackboard> blackboardResourceType;
@Nonnull
private final ComponentType<EntityStore, Player> playerComponentType;
public ReputationAttitudeSystem(
@Nonnull ResourceType<EntityStore, Blackboard> blackboardResourceType, @Nonnull ComponentType<EntityStore, Player> playerComponentType
) {
this.blackboardResourceType = blackboardResourceType;
this.playerComponentType = playerComponentType;
}
@Override
public void onSystemAddedToStore(@Nonnull Store<EntityStore> 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);
});
}

View File

@@ -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<EntityStore, ObjectiveHistoryComponent> objectiveHistoryComponentType;
private ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponentType;
private ComponentType<EntityStore, ObjectiveLocationMarker> 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<EntityStore> 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<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, 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<EntityStore, NetworkId> networkIdComponentType = NetworkId.getComponentType();
ComponentType<EntityStore, TransformComponent> transformComponentType = TransformComponent.getComponentType();
ComponentType<EntityStore, UUIDComponent> uuidComponentType = UUIDComponent.getComponentType();
ComponentType<EntityStore, WeatherTracker> weatherTrackerComponentType = WeatherTracker.getComponentType();
ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
ComponentType<EntityStore, PrefabCopyableComponent> 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<EntityStore, ReachLocationMarker> getReachLocationMarkerComponentType() {
@@ -309,10 +339,12 @@ public class ObjectivePlugin extends JavaPlugin {
Codec<U> implementationCodec,
TriFunction<T, Integer, Integer, U> 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 <T extends ObjectiveCompletionAsset, U extends ObjectiveCompletion> void registerCompletion(
@@ -346,78 +378,90 @@ public class ObjectivePlugin extends JavaPlugin {
@Nullable UUID markerUUID,
@Nonnull Store<EntityStore> 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<UUID> 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<UUID> 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<UUID> 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<UUID> 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<UUID> 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<UUID> 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<EntityStore> 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<EntityStore> 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<UUID> activeObjectiveUUIDs = new HashSet<>(player.getPlayerConfigData().getActiveObjectiveUUIDs());
activeObjectiveUUIDs.remove(objectiveUUID);
player.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs);
playerRef.getPacketHandler().writeNoCache(new UntrackObjective(objectiveUUID));
}
}
public void addPlayerToExistingObjective(@Nonnull Store<EntityStore> 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<EntityStore> 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<UUID> 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<EntityStore> 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<UUID> 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<EntityStore> playerReference = playerRef.getReference();
if (playerReference != null && playerReference.isValid()) {
Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
assert playerComponent != null;
HashSet<UUID> 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<EntityStore> 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<EntityStore> ref = playerRef.getReference();
if (ref != null) {
Store<EntityStore> 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<UUID> 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<EntityStore> ref = playerRef.getReference();
if (ref != null) {
Store<EntityStore> 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<UUID> 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<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> 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<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
if (!activeObjectiveUUIDs.isEmpty()) {
Set<UUID> inventoryItemObjectiveUUIDs = null;
CombinedItemContainer inventory = entity.getInventory().getCombinedHotbarFirst();
if (this.objectiveDataStore != null) {
if (event.getEntity() instanceof Player player) {
Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
if (!activeObjectiveUUIDs.isEmpty()) {
Set<UUID> 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<EntityStore> reference = entity.getReference();
Store<EntityStore> store = reference.getStore();
World world = store.getExternalData().getWorld();
world.execute(() -> {
UUIDComponent uuidComponent = store.getComponent(reference, UUIDComponent.getComponentType());
Ref<EntityStore> reference = player.getReference();
if (reference != null && reference.isValid()) {
Store<EntityStore> 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();

View File

@@ -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) {

View File

@@ -57,11 +57,21 @@ import javax.annotation.Nullable;
public class ObjectiveLocationMarkerSystems {
public static class EnsureNetworkSendableSystem extends HolderSystem<EntityStore> {
@Nonnull
private final Query<EntityStore> query = Query.and(ObjectiveLocationMarker.getComponentType(), Query.not(NetworkId.getComponentType()));
private final ComponentType<EntityStore, NetworkId> networkIdComponentType;
@Nonnull
private final Query<EntityStore> query;
public EnsureNetworkSendableSystem(
@Nonnull ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponentType,
@Nonnull ComponentType<EntityStore, NetworkId> networkIdComponentType
) {
this.networkIdComponentType = networkIdComponentType;
this.query = Query.and(objectiveLocationMarkerComponentType, Query.not(networkIdComponentType));
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> 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<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final ComponentType<EntityStore, PrefabCopyableComponent> prefabCopyableComponentType;
@Nonnull
private final Query<EntityStore> query;
public InitSystem(@Nonnull ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponent) {
public InitSystem(
@Nonnull ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponent,
@Nonnull ComponentType<EntityStore, ModelComponent> modelComponentType,
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, PrefabCopyableComponent> 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<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType = TransformComponent.getComponentType();
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final ComponentType<EntityStore, WeatherTracker> weatherTrackerComponentType = WeatherTracker.getComponentType();
private final ComponentType<EntityStore, WeatherTracker> weatherTrackerComponentType;
@Nonnull
private final ComponentType<EntityStore, UUIDComponent> uuidComponentType = UUIDComponent.getComponentType();
private final ComponentType<EntityStore, UUIDComponent> uuidComponentType;
@Nonnull
private final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent;
@Nonnull
@@ -216,12 +234,18 @@ public class ObjectiveLocationMarkerSystems {
public TickingSystem(
@Nonnull ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent
@Nonnull ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent,
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, WeatherTracker> weatherTrackerComponentType,
@Nonnull ComponentType<EntityStore, UUIDComponent> 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<Ref<EntityStore>, EntityStore> spatialResource = store.getResource(this.playerSpatialComponent);
ObjectList<Ref<EntityStore>> playerReferences = SpatialResource.getThreadLocalReferenceList();
objectiveLocationMarkerComponent.area.getPlayersInExitArea(spatialResource, playerReferences, position);
HashSet<UUID> playersInExitArea = new HashSet<>(playerReferences.size());
PlayerRef[] playersInEntryArea = new PlayerRef[playerReferences.size()];
ObjectList<Ref<EntityStore>> playerRefs = SpatialResource.getThreadLocalReferenceList();
objectiveLocationMarkerComponent.area.getPlayersInExitArea(spatialResource, playerRefs, position);
HashSet<UUID> playersInExitArea = new HashSet<>(playerRefs.size());
PlayerRef[] playersInEntryArea = new PlayerRef[playerRefs.size()];
int playersInEntryAreaSize = 0;
for (Ref<EntityStore> playerReference : playerReferences) {
PlayerRef playerRefComponent = commandBuffer.getComponent(playerReference, this.playerRefComponentType);
for (Ref<EntityStore> 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<EntityStore> 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);
}
}

View File

@@ -45,11 +45,22 @@ public class ReachLocationMarkerSystems {
public static class EnsureNetworkSendable extends HolderSystem<EntityStore> {
@Nonnull
private final Query<EntityStore> query = Query.and(ReachLocationMarker.getComponentType(), Query.not(NetworkId.getComponentType()));
private final ComponentType<EntityStore, NetworkId> networkIdComponentType;
@Nonnull
private final Query<EntityStore> query;
public EnsureNetworkSendable(
@Nonnull ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponentType,
@Nonnull ComponentType<EntityStore, NetworkId> networkIdComponentType
) {
this.networkIdComponentType = networkIdComponentType;
this.query = Query.and(reachLocationMarkerComponentType, Query.not(networkIdComponentType));
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> 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<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponent;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final Query<EntityStore> query;
public EntityAdded(ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponent) {
public EntityAdded(
@Nonnull ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponent,
@Nonnull ComponentType<EntityStore, TransformComponent> 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<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponent;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent;
@Nonnull
private final ComponentType<EntityStore, UUIDComponent> uuidComponentType = UUIDComponent.getComponentType();
private final ComponentType<EntityStore, UUIDComponent> uuidComponentType;
@Nonnull
private final Query<EntityStore> query;
@Nonnull
private final Set<Dependency<EntityStore>> dependencies;
public Ticking(
ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponent,
ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent
@Nonnull ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponent,
@Nonnull ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent,
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, UUIDComponent> 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));
}

View File

@@ -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<StashGameplayConfig> CODEC = BuilderCodec.builder(StashGameplayConfig.class, StashGameplayConfig::new)
.appendInherited(
new KeyedCodec<>("ClearContainerDropList", Codec.BOOLEAN),

View File

@@ -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<ChunkStore> {
private final ComponentType<ChunkStore, ItemContainerState> componentType;
@Nonnull
private final ComponentType<ChunkStore, ItemContainerState> itemContainerStateComponentType;
@Nonnull
private final Set<Dependency<ChunkStore>> dependencies;
public StashSystem(ComponentType<ChunkStore, ItemContainerState> componentType) {
this.componentType = componentType;
public StashSystem(@Nonnull ComponentType<ChunkStore, ItemContainerState> itemContainerStateComponentType) {
this.itemContainerStateComponentType = itemContainerStateComponentType;
this.dependencies = Set.of(new SystemDependency<>(Order.AFTER, BlockStateModule.LegacyBlockStateRefSystem.class));
}
@Override
public Query<ChunkStore> 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);
}
}

View File

@@ -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<ChunkStore> chunkStoreRegistry = this.getChunkStoreRegistry();
ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
this.teleporterComponentType = chunkStoreRegistry.registerComponent(Teleporter.class, "Teleporter", Teleporter.CODEC);
ComponentType<ChunkStore, PlacedByInteractionComponent> placedByInteractionComponentType = PlacedByInteractionComponent.getComponentType();
ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType = BlockModule.BlockStateInfo.getComponentType();
ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ComponentType<EntityStore, TransformComponent> transformComponentType = TransformComponent.getComponentType();
ComponentType<EntityStore, TeleportRecord> teleportRecordComponentType = TeleportRecord.getComponentType();
ComponentType<EntityStore, Teleport> teleportComponentType = Teleport.getComponentType();
ComponentType<EntityStore, PendingTeleport> 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<ChunkStore, Teleporter> {
@Nonnull
private final ComponentType<ChunkStore, Teleporter> teleporterComponentType;
public TeleporterOwnedWarpRefChangeSystem(@Nonnull ComponentType<ChunkStore, Teleporter> teleporterComponentType) {
this.teleporterComponentType = teleporterComponentType;
}
@Nonnull
@Override
public ComponentType<ChunkStore, Teleporter> componentType() {
return Teleporter.getComponentType();
return this.teleporterComponentType;
}
public void onComponentAdded(
@@ -79,11 +111,13 @@ public class TeleporterPlugin extends JavaPlugin {
@Nonnull Store<ChunkStore> store,
@Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> {
public static final ComponentType<ChunkStore, Teleporter> COMPONENT_TYPE = Teleporter.getComponentType();
@Nonnull
private final ComponentType<ChunkStore, Teleporter> teleporterComponentType;
public TeleporterOwnedWarpRefSystem(@Nonnull ComponentType<ChunkStore, Teleporter> 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<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> getQuery() {
return COMPONENT_TYPE;
return this.teleporterComponentType;
}
}
}

View File

@@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Teleporter implements Component<ChunkStore> {
@Nonnull
public static final BuilderCodec<Teleporter> 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<ChunkStore> {
@Nullable
private String warp;
@Deprecated
@Nullable
private String ownedWarp;
private boolean isCustomName;
private String warpNameWordListKey;
@@ -94,11 +96,12 @@ public class Teleporter implements Component<ChunkStore> {
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;
}

View File

@@ -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<EntityStore> 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<ChunkStore> 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<ChunkStore> 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<EntityStore> ref = context.getEntity();
Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType());
if (playerComponent == null || !playerComponent.isWaitingForClientReady()) {
if (playerComponent != null && playerComponent.isWaitingForClientReady()) {
return false;
} else {
Archetype<EntityStore> 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<Ref<EntityStore>, EntityStore> playerSpatialResource = commandBuffer.getResource(
EntityModule.get().getPlayerSpatialResourceType()
);
ObjectList<Ref<EntityStore>> 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<Ref<EntityStore>, EntityStore> playerSpatialResource = commandBuffer.getResource(
EntityModule.get().getPlayerSpatialResourceType()
);
ObjectList<Ref<EntityStore>> 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;
}
}
}

View File

@@ -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<TeleporterSettingsPage.PageEventData> {
@Nonnull
@@ -103,16 +103,7 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage<TeleporterSe
commandBuilder.set("#WorldDropdown.Entries", worlds);
UUID worldUuid = teleporter.getWorldUuid();
commandBuilder.set("#WorldDropdown.Value", worldUuid != null ? worldUuid.toString() : "");
ObjectArrayList<DropdownEntryInfo> 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<TeleporterSe
);
break;
case WARP:
List<DropdownEntryInfo> 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<TeleporterSe
}
}
static List<DropdownEntryInfo> getWarpsSortedById(@NullableDecl String ownedWarpId, @NullableDecl String worldNameToFilter) {
List<DropdownEntryInfo> warps = new ObjectArrayList<>();
warps.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.teleporter.noWarp"), ""));
ObjectArrayList<Warp> 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<EntityStore> ref, @Nonnull Store<EntityStore> 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<ChunkStore> 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<ChunkStore> 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<TeleporterSe
FULL,
WARP;
@Nonnull
public static final Codec<TeleporterSettingsPage.Mode> 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<TeleporterSettingsPage.PageEventData> CODEC = BuilderCodec.builder(
TeleporterSettingsPage.PageEventData.class, TeleporterSettingsPage.PageEventData::new
)
@@ -355,7 +383,7 @@ public class TeleporterSettingsPage extends InteractiveCustomUIPage<TeleporterSe
.add()
.append(new KeyedCodec<>("@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<TeleporterSe
public String world;
public String warp;
@Nullable
public String ownedWarp;
public String warpName;
}
}

View File

@@ -24,6 +24,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class TeleporterSettingsPageSupplier implements OpenCustomUIInteraction.CustomPageSupplier {
@Nonnull
public static final BuilderCodec<TeleporterSettingsPageSupplier> CODEC = BuilderCodec.builder(
TeleporterSettingsPageSupplier.class, TeleporterSettingsPageSupplier::new
)

View File

@@ -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<EntityStore> {
@Nonnull
public static final Duration TELEPORTER_GLOBAL_COOLDOWN = Duration.ofMillis(100L);
@Nonnull
private static final Set<Dependency<EntityStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, TeleportSystems.PlayerMoveSystem.class));
@Nonnull
private final ComponentType<EntityStore, UsedTeleporter> usedTeleporterComponentType;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final ComponentType<EntityStore, TeleportRecord> teleportRecordComponentType;
@Nonnull
private final ComponentType<EntityStore, Teleport> teleportComponentType;
@Nonnull
private final ComponentType<EntityStore, PendingTeleport> pendingTeleportComponentType;
public ClearUsedTeleporterSystem(
@Nonnull ComponentType<EntityStore, UsedTeleporter> usedTeleporterComponentType,
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, TeleportRecord> teleportRecordComponentType,
@Nonnull ComponentType<EntityStore, Teleport> teleportComponentType,
@Nonnull ComponentType<EntityStore, PendingTeleport> pendingTeleportComponentType
) {
this.usedTeleporterComponentType = usedTeleporterComponentType;
this.transformComponentType = transformComponentType;
this.teleportRecordComponentType = teleportRecordComponentType;
this.teleportComponentType = teleportComponentType;
this.pendingTeleportComponentType = pendingTeleportComponentType;
}
@Nonnull
@Override
public Set<Dependency<EntityStore>> getDependencies() {
return DEPENDENCIES;
}
@Override
public void tick(
float dt,
int index,
@NonNullDecl ArchetypeChunk<EntityStore> archetypeChunk,
@NonNullDecl Store<EntityStore> store,
@NonNullDecl CommandBuffer<EntityStore> commandBuffer
@Nonnull ArchetypeChunk<EntityStore> archetypeChunk,
@Nonnull Store<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> 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<EntityStore> 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<EntityStore> 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<EntityStore> 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<EntityStore> getQuery() {
return UsedTeleporter.getComponentType();
return this.usedTeleporterComponentType;
}
}

View File

@@ -31,6 +31,30 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class CreateWarpWhenTeleporterPlacedSystem extends RefChangeSystem<ChunkStore, PlacedByInteractionComponent> {
@Nonnull
private final ComponentType<ChunkStore, PlacedByInteractionComponent> placedByInteractionComponentType;
@Nonnull
private final ComponentType<ChunkStore, Teleporter> teleporterComponentType;
@Nonnull
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final Query<ChunkStore> query;
public CreateWarpWhenTeleporterPlacedSystem(
@Nonnull ComponentType<ChunkStore, PlacedByInteractionComponent> placedByInteractionComponentType,
@Nonnull ComponentType<ChunkStore, Teleporter> teleporterComponentType,
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> 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<ChunkStore> ref,
@Nonnull PlacedByInteractionComponent placedBy,
@@ -42,21 +66,21 @@ public class CreateWarpWhenTeleporterPlacedSystem extends RefChangeSystem<ChunkS
UUID whoPlacedUuid = placedBy.getWhoPlacedUuid();
Ref<EntityStore> 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<ChunkStore> 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<ChunkS
int y = ChunkUtil.yFromBlockInColumn(index);
int z = chunkBlockZ + ChunkUtil.zFromBlockInColumn(index);
BlockChunk blockChunkComponent = worldChunk.getBlockChunk();
assert blockChunkComponent != null;
BlockSection section = blockChunkComponent.getSectionAtBlockY(y);
int rotationIndex = section.getRotationIndex(x, y, z);
RotationTuple rotationTuple = RotationTuple.get(rotationIndex);
Rotation rotationYaw = rotationTuple.yaw();
float warpRotationYaw = (float)rotationYaw.getRadians() + (float)Math.toRadians(180.0);
Vector3d warpPosition = new Vector3d(x, y, z).add(0.5, 0.65, 0.5);
Transform warpTransform = new Transform(warpPosition, new Vector3f(Float.NaN, warpRotationYaw, Float.NaN));
String warpId = name.toLowerCase();
Warp warp = new Warp(warpTransform, name, worldChunk.getWorld(), "*Teleporter", Instant.now());
TeleportPlugin teleportPlugin = TeleportPlugin.get();
teleportPlugin.getWarps().put(warpId, warp);
teleportPlugin.saveWarps();
if (blockChunkComponent != null) {
BlockSection section = blockChunkComponent.getSectionAtBlockY(y);
int rotationIndex = section.getRotationIndex(x, y, z);
RotationTuple rotationTuple = RotationTuple.get(rotationIndex);
Rotation rotationYaw = rotationTuple.yaw();
float warpRotationYaw = (float)rotationYaw.getRadians() + (float)Math.toRadians(180.0);
Vector3d warpPosition = new Vector3d(x, y, z).add(0.5, 0.65, 0.5);
Transform warpTransform = new Transform(warpPosition, new Vector3f(Float.NaN, warpRotationYaw, Float.NaN));
String warpId = name.toLowerCase();
Warp warp = new Warp(warpTransform, name, worldChunk.getWorld(), "*Teleporter", Instant.now());
TeleportPlugin teleportPlugin = TeleportPlugin.get();
teleportPlugin.getWarps().put(warpId, warp);
teleportPlugin.saveWarps();
}
}
public void onComponentSet(
@@ -113,12 +136,12 @@ public class CreateWarpWhenTeleporterPlacedSystem extends RefChangeSystem<ChunkS
@Nonnull
@Override
public ComponentType<ChunkStore, PlacedByInteractionComponent> componentType() {
return PlacedByInteractionComponent.getComponentType();
return this.placedByInteractionComponentType;
}
@Nullable
@Nonnull
@Override
public Query<ChunkStore> getQuery() {
return Query.and(PlacedByInteractionComponent.getComponentType(), Teleporter.getComponentType(), BlockModule.BlockStateInfo.getComponentType());
return this.query;
}
}

View File

@@ -21,23 +21,23 @@ public final class CannedWarpNames {
}
@Nullable
public static String generateCannedWarpName(Ref<ChunkStore> blockRef, String language) {
public static String generateCannedWarpName(@Nonnull Ref<ChunkStore> blockRef, @Nonnull String language) {
String translationKey = generateCannedWarpNameKey(blockRef, language);
return translationKey == null ? null : I18nModule.get().getMessage(language, translationKey);
}
@Nullable
public static String generateCannedWarpNameKey(Ref<ChunkStore> blockRef, String language) {
public static String generateCannedWarpNameKey(@Nonnull Ref<ChunkStore> blockRef, @Nonnull String language) {
Store<ChunkStore> 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<String> 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<String> getWarpNamesInWorld(World world) {
private static Set<String> getWarpNamesInWorld(@Nonnull World world) {
Set<String> existingNames = new HashSet<>();
for (Warp warp : TeleportPlugin.get().getWarps().values()) {

View File

@@ -21,6 +21,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class NeighbourBlockTagsLocationCondition extends WorldLocationCondition {
@Nonnull
public static final BuilderCodec<NeighbourBlockTagsLocationCondition> 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;

View File

@@ -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<EntityStore, AmbienceTracker> ambienceTrackerComponentType;
private ComponentType<EntityStore, AmbientEmitterComponent> ambientEmitterComponentType;
private ResourceType<EntityStore, AmbienceResource> ambienceResourceType;
@Nonnull
private final Config<AmbiencePlugin.AmbiencePluginConfig> 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<EntityStore> 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<EntityStore, TransformComponent> transformComponentType = TransformComponent.getComponentType();
ComponentType<EntityStore, NetworkId> networkIdComponentType = NetworkId.getComponentType();
ComponentType<EntityStore, Intangible> intangibleComponentType = Intangible.getComponentType();
ComponentType<EntityStore, PrefabCopyableComponent> prefabCopyableComponentType = PrefabCopyableComponent.getComponentType();
ComponentType<EntityStore, AudioComponent> audioComponentType = AudioComponent.getComponentType();
ComponentType<EntityStore, Player> playerComponentType = Player.getComponentType();
ComponentType<EntityStore, PlayerRef> 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<AmbiencePlugin.AmbiencePluginConfig> CODEC = BuilderCodec.builder(
AmbiencePlugin.AmbiencePluginConfig.class, AmbiencePlugin.AmbiencePluginConfig::new
)

View File

@@ -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<EntityStore> 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);
}
}

View File

@@ -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<SoundEvent> 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<EntityStore> store, @Nonnull Ref<EntityStore> 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<EntityStore> holder = EntityStore.REGISTRY.newHolder();
SoundEvent soundEvent = this.soundEventArg.get(context);
boolean looping = false;
assert transformComponent != null;
Holder<EntityStore> 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<EntityStore> 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<EntityStore> 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()));
}
}
}
}

View File

@@ -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<AmbienceFX> 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<EntityStore> 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()));
}
}

View File

@@ -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<EntityStore> {
@Nonnull
private final UpdateEnvironmentMusic musicPacket = new UpdateEnvironmentMusic(0);
private int forcedMusicIndex;
@@ -23,6 +25,7 @@ public class AmbienceTracker implements Component<EntityStore> {
return this.forcedMusicIndex;
}
@Nonnull
public UpdateEnvironmentMusic getMusicPacket() {
return this.musicPacket;
}

View File

@@ -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<EntityStore> {
@Nonnull
public static final BuilderCodec<AmbientEmitterComponent> CODEC = BuilderCodec.builder(AmbientEmitterComponent.class, AmbientEmitterComponent::new)
.append(new KeyedCodec<>("SoundEventId", Codec.STRING), (emitter, s) -> emitter.soundEventId = s, emitter -> emitter.soundEventId)
.add()

View File

@@ -29,18 +29,37 @@ import javax.annotation.Nonnull;
public class AmbientEmitterSystems {
public static class EntityAdded extends HolderSystem<EntityStore> {
@Nonnull
private final Query<EntityStore> query = Query.and(AmbientEmitterComponent.getComponentType(), TransformComponent.getComponentType());
private final ComponentType<EntityStore, NetworkId> networkIdComponentType;
@Nonnull
private final ComponentType<EntityStore, Intangible> intangibleComponentType;
@Nonnull
private final ComponentType<EntityStore, PrefabCopyableComponent> prefabCopyableComponentType;
@Nonnull
private final Query<EntityStore> query;
public EntityAdded(
@Nonnull ComponentType<EntityStore, AmbientEmitterComponent> ambientEmitterComponentType,
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, NetworkId> networkIdComponentType,
@Nonnull ComponentType<EntityStore, Intangible> intangibleComponentType,
@Nonnull ComponentType<EntityStore, PrefabCopyableComponent> prefabCopyableComponentType
) {
this.networkIdComponentType = networkIdComponentType;
this.intangibleComponentType = intangibleComponentType;
this.prefabCopyableComponentType = prefabCopyableComponentType;
this.query = Query.and(ambientEmitterComponentType, transformComponentType);
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
Archetype<EntityStore> archetype = holder.getArchetype();
ComponentType<EntityStore, NetworkId> 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<EntityStore> {
@Nonnull
private final Query<EntityStore> query = Query.and(AmbientEmitterComponent.getComponentType(), TransformComponent.getComponentType());
private final ComponentType<EntityStore, AmbientEmitterComponent> ambientEmitterComponentType;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final ComponentType<EntityStore, AudioComponent> audioComponentType;
@Nonnull
private final ComponentType<EntityStore, NetworkId> networkIdComponentType;
@Nonnull
private final ComponentType<EntityStore, Intangible> intangibleComponentType;
@Nonnull
private final Query<EntityStore> query;
public EntityRefAdded(
@Nonnull ComponentType<EntityStore, AmbientEmitterComponent> ambientEmitterComponentType,
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, AudioComponent> audioComponentType,
@Nonnull ComponentType<EntityStore, NetworkId> networkIdComponentType,
@Nonnull ComponentType<EntityStore, Intangible> 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<EntityStore> ref, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> 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<EntityStore> 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<EntityStore> emitterRef = commandBuffer.addEntity(emitterHolder, AddReason.SPAWN);
emitterComponent.setSpawnedEmitter(emitterRef);
}
@Override
@@ -86,7 +132,7 @@ public class AmbientEmitterSystems {
@Nonnull Ref<EntityStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> 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<EntityStore> {
@Nonnull
private final Query<EntityStore> query = Query.and(AmbientEmitterComponent.getComponentType(), TransformComponent.getComponentType());
private final ComponentType<EntityStore, AmbientEmitterComponent> ambientEmitterComponentType;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final Query<EntityStore> query;
public Ticking(
@Nonnull ComponentType<EntityStore, AmbientEmitterComponent> ambientEmitterComponentType,
@Nonnull ComponentType<EntityStore, TransformComponent> 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<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> 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<EntityStore> 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());

View File

@@ -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<EntityStore> TICK_QUERY = Archetype.of(
Player.getComponentType(), PlayerRef.getComponentType(), AmbienceTracker.getComponentType()
);
public static class PlayerAdded extends HolderSystem<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, AmbienceTracker> ambienceTrackerComponentType;
@Nonnull
private final Query<EntityStore> query;
public PlayerAdded(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, AmbienceTracker> ambienceTrackerComponentType
) {
this.playerRefComponentType = playerRefComponentType;
this.ambienceTrackerComponentType = ambienceTrackerComponentType;
this.query = Query.and(playerRefComponentType, ambienceTrackerComponentType);
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
holder.ensureComponent(AmbienceTracker.getComponentType());
holder.ensureComponent(this.ambienceTrackerComponentType);
}
@Override
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> 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<EntityStore> getQuery() {
return Query.and(PlayerRef.getComponentType(), AmbienceTracker.getComponentType());
return this.query;
}
}
public static class Tick extends EntityTickingSystem<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, AmbienceTracker> ambienceTrackerComponentType;
@Nonnull
private final ResourceType<EntityStore, AmbienceResource> ambienceResourceType;
@Nonnull
private final Query<EntityStore> query;
public Tick(
@Nonnull ComponentType<EntityStore, Player> playerComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, AmbienceTracker> ambienceTrackerComponentType,
@Nonnull ResourceType<EntityStore, AmbienceResource> 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<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> 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<EntityStore> getQuery() {
return ForcedMusicSystems.TICK_QUERY;
return this.query;
}
}
}

View File

@@ -65,22 +65,28 @@ public class AssetEditorGamePacketHandler implements SubPacketHandler {
if (ref != null && ref.isValid()) {
Store<EntityStore> 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;

View File

@@ -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;

View File

@@ -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<UUID, Set<EditorClient>> uuidToEditorClients = new ConcurrentHashMap<>();
@Nonnull
private final Map<EditorClient, AssetPath> clientOpenAssetPathMapping = new ConcurrentHashMap<>();
@Nonnull
private final Set<EditorClient> clientsSubscribedToModifiedAssetsChanges = ConcurrentHashMap.newKeySet();
@Nonnull
private Map<String, Schema> schemas = new Object2ObjectOpenHashMap<>();
private AssetEditorSetupSchemas setupSchemasPacket;
@Nonnull
private final StampedLock initLock = new StampedLock();
@Nonnull
private final Set<EditorClient> initQueue = new HashSet<>();
@Nonnull
private AssetEditorPlugin.InitState initState = AssetEditorPlugin.InitState.NOT_INITIALIZED;
@Nullable
private ScheduledFuture<?> scheduledReinitFuture;
@Nonnull
private final Map<String, DataSource> 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<DataSource> 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<EditorClient, AssetPath> getClientOpenAssetPathMapping() {
return this.clientOpenAssetPathMapping;
}
public Set<EditorClient> getEditorClients(UUID uuid) {
@Nullable
public Set<EditorClient> getEditorClients(@Nonnull UUID uuid) {
return this.uuidToEditorClients.get(uuid);
}
@@ -259,7 +282,7 @@ public class AssetEditorPlugin extends JavaPlugin {
}
@Nonnull
private List<EditorClient> getClientsWithOpenAssetPath(AssetPath path) {
private List<EditorClient> 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<AssetEditorClientDisconnectEvent, AssetEditorClientDisconnectEvent> 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<PluginIdentifier, HytaleServerConfig.ModConfig> 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<com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo> 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<EditorClient> 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<String> 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<EditorClient, AssetPath> 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<EditorClient, AssetPath> connectedPlayer : this.clientOpenAssetPathMapping.entrySet()) {
@@ -1810,7 +1848,7 @@ public class AssetEditorPlugin extends JavaPlugin {
@Nonnull
private AssetEditorLastModifiedAssets buildAssetEditorLastModifiedAssetsPacket() {
ArrayList<AssetInfo> allAssets = new ArrayList<>();
List<AssetInfo> allAssets = new ObjectArrayList<>();
for (Entry<String, DataSource> dataSource : this.assetPackDataSources.entrySet()) {
if (dataSource.getValue() instanceof StandardDataSource standardDataSource) {

View File

@@ -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");
}

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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<EntityStore> 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<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ComponentType<EntityStore, MountedComponent> mountedComponentType = MountedComponent.getComponentType();
ResourceType<EntityStore, WorldTimeResource> 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);
}

View File

@@ -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<EntityStore> ref = context.getEntity();
Player player = commandBuffer.getComponent(ref, Player.getComponentType());
if (player != null) {
Player playerComponent = commandBuffer.getComponent(ref, Player.getComponentType());
if (playerComponent != null) {
Store<EntityStore> 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<ChunkStore> chunkReference = world.getChunkStore().getChunkReference(ChunkUtil.indexChunkFromBlock(pos.x, pos.z));
if (chunkReference != null) {
Store<ChunkStore> chunkStore = chunkReference.getStore();
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkReference, BlockComponentChunk.getComponentType());
assert blockComponentChunk != null;
int blockIndex = ChunkUtil.indexBlockInColumn(pos.x, pos.y, pos.z);
Ref<ChunkStore> blockRef = blockComponentChunk.getEntityReference(blockIndex);
if (blockRef == null || !blockRef.isValid()) {
Holder<ChunkStore> 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<ChunkStore> chunkRef = world.getChunkStore().getChunkReference(chunkIndex);
if (chunkRef != null && chunkRef.isValid()) {
Store<ChunkStore> chunkStore = chunkRef.getStore();
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkRef, BlockComponentChunk.getComponentType());
if (blockComponentChunk != null) {
int blockIndex = ChunkUtil.indexBlockInColumn(pos.x, pos.y, pos.z);
Ref<ChunkStore> blockRef = blockComponentChunk.getEntityReference(blockIndex);
if (blockRef == null || !blockRef.isValid()) {
Holder<ChunkStore> 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));
}
}
}
}
}
}

View File

@@ -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<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull RespawnPointPage.RespawnPointEventData data) {

View File

@@ -65,48 +65,47 @@ public abstract class RespawnPointPage extends InteractiveCustomUIPage<RespawnPo
respawnBlock.setOwnerUUID(this.playerRef.getUuid());
World world = store.getExternalData().getWorld();
Player playerComponent = store.getComponent(ref, Player.getComponentType());
if (playerComponent != null) {
long chunkIndex = ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z);
WorldChunk chunk = world.getChunkIfInMemory(chunkIndex);
if (chunk != null) {
chunk.markNeedsSaving();
BlockType blockType = chunk.getBlockType(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
if (blockType != null) {
int rotationIndex = chunk.getRotationIndex(blockPosition.x, blockPosition.y, blockPosition.z);
BlockBoundingBoxes blockBoundingBoxAsset = BlockBoundingBoxes.getAssetMap().getAsset(blockType.getHitboxTypeIndex());
if (blockBoundingBoxAsset != null) {
Box hitbox = blockBoundingBoxAsset.get(rotationIndex).getBoundingBox();
double blockCenterWidthOffset = hitbox.min.x + hitbox.width() / 2.0;
double blockCenterDepthOffset = hitbox.min.z + hitbox.depth() / 2.0;
Vector3d respawnPosition = new Vector3d(
blockPosition.getX() + blockCenterWidthOffset, blockPosition.getY() + hitbox.height(), blockPosition.getZ() + blockCenterDepthOffset
);
PlayerRespawnPointData respawnPointData = new PlayerRespawnPointData(blockPosition, respawnPosition, respawnPointName);
PlayerWorldData perWorldData = playerComponent.getPlayerConfigData().getPerWorldData(world.getName());
PlayerRespawnPointData[] respawnPoints = handleRespawnPointsToRemove(world, perWorldData.getRespawnPoints(), respawnPointsToRemove);
if (respawnPoints != null) {
if (ArrayUtil.contains(respawnPoints, respawnPointData)) {
return;
}
assert playerComponent != null;
long chunkIndex = ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z);
WorldChunk chunk = world.getChunkIfInMemory(chunkIndex);
if (chunk != null) {
chunk.markNeedsSaving();
BlockType blockType = chunk.getBlockType(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
if (blockType != null) {
int rotationIndex = chunk.getRotationIndex(blockPosition.x, blockPosition.y, blockPosition.z);
BlockBoundingBoxes blockBoundingBoxAsset = BlockBoundingBoxes.getAssetMap().getAsset(blockType.getHitboxTypeIndex());
if (blockBoundingBoxAsset != null) {
Box hitbox = blockBoundingBoxAsset.get(rotationIndex).getBoundingBox();
double blockCenterWidthOffset = hitbox.min.x + hitbox.width() / 2.0;
double blockCenterDepthOffset = hitbox.min.z + hitbox.depth() / 2.0;
Vector3d respawnPosition = new Vector3d(
blockPosition.getX() + blockCenterWidthOffset, blockPosition.getY() + hitbox.height(), blockPosition.getZ() + blockCenterDepthOffset
);
PlayerRespawnPointData respawnPointData = new PlayerRespawnPointData(blockPosition, respawnPosition, respawnPointName);
PlayerWorldData perWorldData = playerComponent.getPlayerConfigData().getPerWorldData(world.getName());
PlayerRespawnPointData[] respawnPoints = handleRespawnPointsToRemove(world, perWorldData.getRespawnPoints(), respawnPointsToRemove);
if (respawnPoints != null) {
if (ArrayUtil.contains(respawnPoints, respawnPointData)) {
return;
}
if (respawnPointsToRemove == null || respawnPointsToRemove.length == 0) {
for (int i = 0; i < respawnPoints.length; i++) {
PlayerRespawnPointData savedRespawnPointData = respawnPoints[i];
if (savedRespawnPointData.getBlockPosition().equals(blockPosition)) {
savedRespawnPointData.setName(respawnPointName);
this.playerRef.sendMessage(Message.translation("server.customUI.updatedRespawnPointName").param("name", respawnPointName));
playerComponent.getPageManager().setPage(ref, store, Page.None);
return;
if (respawnPointsToRemove == null || respawnPointsToRemove.length == 0) {
for (int i = 0; i < respawnPoints.length; i++) {
PlayerRespawnPointData savedRespawnPointData = respawnPoints[i];
if (savedRespawnPointData.getBlockPosition().equals(blockPosition)) {
savedRespawnPointData.setName(respawnPointName);
this.playerRef.sendMessage(Message.translation("server.customUI.updatedRespawnPointName").param("name", respawnPointName));
playerComponent.getPageManager().setPage(ref, store, Page.None);
return;
}
}
}
}
}
perWorldData.setRespawnPoints(ArrayUtil.append(respawnPoints, respawnPointData));
this.playerRef.sendMessage(Message.translation("server.customUI.respawnPointSet").param("name", respawnPointName));
playerComponent.getPageManager().setPage(ref, store, Page.None);
perWorldData.setRespawnPoints(ArrayUtil.append(respawnPoints, respawnPointData));
this.playerRef.sendMessage(Message.translation("server.customUI.respawnPointSet").param("name", respawnPointName));
playerComponent.getPageManager().setPage(ref, store, Page.None);
}
}
}
}

View File

@@ -56,32 +56,32 @@ public class SelectOverrideRespawnPointPage extends RespawnPointPage {
commandBuilder.append("Pages/SelectOverrideRespawnPointPage.ui");
commandBuilder.clear("#RespawnPointList");
PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType());
if (playerRefComponent != null) {
HeadRotation rotationComponent = store.getComponent(ref, HeadRotation.getComponentType());
if (rotationComponent != null) {
float lookYaw = rotationComponent.getRotation().getYaw();
double direction = Math.toDegrees(lookYaw);
assert playerRefComponent != null;
for (int i = 0; i < this.respawnPoints.length; i++) {
String selector = "#RespawnPointList[" + i + "]";
PlayerRespawnPointData respawnPoint = this.respawnPoints[i];
commandBuilder.append("#RespawnPointList", "Pages/OverrideRespawnPointButton.ui");
commandBuilder.set(selector + " #Name.Text", respawnPoint.getName());
Vector3i respawnPointPosition = respawnPoint.getBlockPosition();
int distance = (int)this.respawnPointToAddPosition.distanceTo(respawnPointPosition.x, this.respawnPointToAddPosition.y, respawnPointPosition.z);
commandBuilder.set(selector + " #Distance.Text", Message.translation("server.customUI.respawnPointDistance").param("distance", distance));
double angle = Math.atan2(respawnPointPosition.z - this.respawnPointToAddPosition.z, respawnPointPosition.x - this.respawnPointToAddPosition.x);
commandBuilder.set(selector + " #Icon.Angle", Math.toDegrees(angle) + direction + 90.0);
eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, selector, EventData.of("Index", Integer.toString(i)), false);
}
HeadRotation rotationComponent = store.getComponent(ref, HeadRotation.getComponentType());
assert rotationComponent != null;
float lookYaw = rotationComponent.getRotation().getYaw();
double direction = Math.toDegrees(lookYaw);
for (int i = 0; i < this.respawnPoints.length; i++) {
String selector = "#RespawnPointList[" + i + "]";
PlayerRespawnPointData respawnPoint = this.respawnPoints[i];
commandBuilder.append("#RespawnPointList", "Pages/OverrideRespawnPointButton.ui");
commandBuilder.set(selector + " #Name.Text", respawnPoint.getName());
Vector3i respawnPointPosition = respawnPoint.getBlockPosition();
int distance = (int)this.respawnPointToAddPosition.distanceTo(respawnPointPosition.x, this.respawnPointToAddPosition.y, respawnPointPosition.z);
commandBuilder.set(selector + " #Distance.Text", Message.translation("server.customUI.respawnPointDistance").param("distance", distance));
double angle = Math.atan2(respawnPointPosition.z - this.respawnPointToAddPosition.z, respawnPointPosition.x - this.respawnPointToAddPosition.x);
commandBuilder.set(selector + " #Icon.Angle", Math.toDegrees(angle) + direction + 90.0);
eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, selector, EventData.of("Index", Integer.toString(i)), false);
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<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull RespawnPointPage.RespawnPointEventData data) {

View File

@@ -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<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull RespawnPointPage.RespawnPointEventData data) {

View File

@@ -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 {

View File

@@ -10,6 +10,7 @@ import javax.annotation.Nullable;
public class WorldSomnolence implements Resource<EntityStore> {
@Nonnull
private WorldSleep state = WorldSleep.Awake.INSTANCE;
private long lastSleepNotification;
public static ResourceType<EntityStore, WorldSomnolence> getResourceType() {
return BedsPlugin.getInstance().getWorldSomnolenceResourceType();
@@ -24,6 +25,21 @@ public class WorldSomnolence implements Resource<EntityStore> {
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<EntityStore> clone() {

View File

@@ -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<EntityStore, MountedComponen
@Nonnull
private static final Message MESSAGE_SERVER_INTERACTIONS_SLEEP_DISABLED = Message.translation("server.interactions.sleep.disabled");
@Nonnull
private static final Query<EntityStore> QUERY = Query.and(MountedComponent.getComponentType(), PlayerRef.getComponentType());
private final ComponentType<EntityStore, MountedComponent> mountedComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final Query<EntityStore> query;
public EnterBedSystem(
@Nonnull ComponentType<EntityStore, MountedComponent> mountedComponentType, @Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType
) {
this.mountedComponentType = mountedComponentType;
this.playerRefComponentType = playerRefComponentType;
this.query = Query.and(mountedComponentType, playerRefComponentType);
}
@Nonnull
@Override
public ComponentType<EntityStore, MountedComponent> componentType() {
return MountedComponent.getComponentType();
return this.mountedComponentType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return QUERY;
return this.query;
}
public void onComponentAdded(
@Nonnull Ref<EntityStore> ref, @Nonnull MountedComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer
) {
check(ref, component, store);
check(ref, component, store, this.playerRefComponentType);
}
public void onComponentSet(
@@ -54,7 +69,7 @@ public class EnterBedSystem extends RefChangeSystem<EntityStore, MountedComponen
@Nonnull Store<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> commandBuffer
) {
check(ref, newComponent, store);
check(ref, newComponent, store, this.playerRefComponentType);
}
public void onComponentRemoved(
@@ -62,30 +77,38 @@ public class EnterBedSystem extends RefChangeSystem<EntityStore, MountedComponen
) {
}
public static void check(@Nonnull Ref<EntityStore> ref, @Nonnull MountedComponent component, @Nonnull Store<EntityStore> store) {
private static void check(
@Nonnull Ref<EntityStore> ref,
@Nonnull MountedComponent component,
@Nonnull Store<EntityStore> store,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType
) {
if (component.getBlockMountType() == BlockMountType.Bed) {
onEnterBed(ref, store);
onEnterBed(ref, store, playerRefComponentType);
}
}
public static void onEnterBed(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store) {
private static void onEnterBed(
@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull ComponentType<EntityStore, PlayerRef> 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);
}
}
}

View File

@@ -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<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, SleepTracker> sleepTrackerComponentType;
@Nonnull
private final Query<EntityStore> query;
public RegisterTrackerSystem(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType, @Nonnull ComponentType<EntityStore, SleepTracker> sleepTrackerComponentType
) {
this.sleepTrackerComponentType = sleepTrackerComponentType;
this.query = playerRefComponentType;
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
holder.ensureComponent(SleepTracker.getComponentType());
holder.ensureComponent(this.sleepTrackerComponentType);
}
@Override
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
}
@Nullable
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return PlayerRef.getComponentType();
return this.query;
}
}

View File

@@ -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<EntityStore> {
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<EntityStore> store) {
World world = store.getExternalData().getWorld();
SleepSoundsConfig sleepSounds = world.getGameplayConfig().getWorldConfig().getSleepConfig().getSounds();
if (sleepSounds.isNotificationLoopEnabled()) {
maybeDoNotification(store, true);
}
}
public static void maybeDoNotification(Store<EntityStore> 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<PlayerRef> playerRefs = world.getPlayerRefs();
for (PlayerRef playerRef : playerRefs) {
Ref<EntityStore> 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<EntityStore>)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<EntityStore> store = world.getEntityStore().getStore();
WorldSleep worldSleep = store.getResource(WorldSomnolence.getResourceType()).getState();
if (worldSleep instanceof WorldSlumber) {
return SleepNotificationSystem.NotReady.INSTANCE;
} else {
List<Ref<EntityStore>> 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<Ref<EntityStore>> playerRefs, ComponentAccessor<EntityStore> store) {
int count = 0;
for (Ref<EntityStore> 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<EntityStore> ref) {
if (ref != null && ref.isValid()) {
Store<EntityStore> 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 {
}
}

View File

@@ -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<EntityStore> {
private static final int MAX_SAMPLE_COUNT = 5;
private static final float SYSTEM_INTERVAL_S = 0.25F;
@Nonnull
public static final Query<EntityStore> 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<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType;
@Nonnull
private final ComponentType<EntityStore, SleepTracker> sleepTrackerComponentType;
@Nonnull
private final ResourceType<EntityStore, WorldSomnolence> worldSomnolenceResourceType;
@Nonnull
private final ResourceType<EntityStore, WorldTimeResource> worldTimeResourceType;
@Nonnull
private final Query<EntityStore> query;
@Override
public Query<EntityStore> getQuery() {
return QUERY;
public UpdateSleepPacketSystem(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType,
@Nonnull ComponentType<EntityStore, SleepTracker> sleepTrackerComponentType,
@Nonnull ResourceType<EntityStore, WorldSomnolence> worldSomnolenceResourceType,
@Nonnull ResourceType<EntityStore, WorldTimeResource> 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<EntityStore> getQuery() {
return this.query;
}
@Override
@@ -58,13 +85,13 @@ public class UpdateSleepPacketSystem extends DelayedEntitySystem<EntityStore> {
@Nonnull CommandBuffer<EntityStore> 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<EntityStore> {
@Nonnull
private UpdateSleepState createSleepPacket(@Nonnull Store<EntityStore> store, int index, @Nonnull ArchetypeChunk<EntityStore> 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<EntityStore> {
for (PlayerRef playerRef : playerRefs) {
Ref<EntityStore> 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());
}
}
}

View File

@@ -15,14 +15,28 @@ import javax.annotation.Nullable;
public class WakeUpOnDismountSystem extends RefChangeSystem<EntityStore, MountedComponent> {
@Nonnull
@Override
public ComponentType<EntityStore, MountedComponent> componentType() {
return MountedComponent.getComponentType();
private final ComponentType<EntityStore, MountedComponent> mountedComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType;
public WakeUpOnDismountSystem(
@Nonnull ComponentType<EntityStore, MountedComponent> mountedComponentType,
@Nonnull ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType
) {
this.mountedComponentType = mountedComponentType;
this.playerSomnolenceComponentType = playerSomnolenceComponentType;
}
@Nonnull
@Override
public ComponentType<EntityStore, MountedComponent> componentType() {
return this.mountedComponentType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return MountedComponent.getComponentType();
return this.mountedComponentType;
}
public void onComponentAdded(
@@ -43,7 +57,7 @@ public class WakeUpOnDismountSystem extends RefChangeSystem<EntityStore, Mounted
@Nonnull Ref<EntityStore> ref, @Nonnull MountedComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer
) {
if (component.getBlockMountType() == BlockMountType.Bed) {
commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSomnolence.AWAKE);
commandBuffer.putComponent(ref, this.playerSomnolenceComponentType, PlayerSomnolence.AWAKE);
}
}
}

View File

@@ -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;

View File

@@ -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<EntityStore> {
@Nonnull
@@ -27,9 +33,22 @@ public class StartSlumberSystem extends DelayedSystem<EntityStore> {
@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<EntityStore, PlayerSomnolence> playerSomnolenceComponentType;
@Nonnull
private final ResourceType<EntityStore, WorldSomnolence> worldSomnolenceResourceType;
@Nonnull
private final ResourceType<EntityStore, WorldTimeResource> worldTimeResourceType;
public StartSlumberSystem() {
public StartSlumberSystem(
@Nonnull ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType,
@Nonnull ResourceType<EntityStore, WorldSomnolence> worldSomnolenceResourceType,
@Nonnull ResourceType<EntityStore, WorldTimeResource> worldTimeResourceType
) {
super(0.3F);
this.playerSomnolenceComponentType = playerSomnolenceComponentType;
this.worldSomnolenceResourceType = worldSomnolenceResourceType;
this.worldTimeResourceType = worldTimeResourceType;
}
@Override
@@ -42,20 +61,26 @@ public class StartSlumberSystem extends DelayedSystem<EntityStore> {
Collection<PlayerRef> 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<EntityStore> 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<EntityStore> {
return (float)Math.ceil(seconds);
}
private static boolean isEveryoneReadyToSleep(@Nonnull ComponentAccessor<EntityStore> store) {
private boolean isEveryoneReadyToSleep(@Nonnull ComponentAccessor<EntityStore> store) {
World world = store.getExternalData().getWorld();
Collection<PlayerRef> playerRefs = world.getPlayerRefs();
if (playerRefs.isEmpty()) {
@@ -98,31 +123,54 @@ public class StartSlumberSystem extends DelayedSystem<EntityStore> {
}
}
public static boolean isReadyToSleep(@Nonnull ComponentAccessor<EntityStore> store, @Nonnull Ref<EntityStore> ref) {
if (!ref.isValid()) {
return true;
} else {
PlayerSomnolence somnolence = store.getComponent(ref, PlayerSomnolence.getComponentType());
if (somnolence == null) {
public static boolean isReadyToSleep(@Nonnull ComponentAccessor<EntityStore> store, @Nullable Ref<EntityStore> 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<EntityStore> store, @Nullable Ref<EntityStore> 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;
}
}
}

View File

@@ -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<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType;
@Nonnull
private final ResourceType<EntityStore, WorldSomnolence> worldSomnolenceResourceType;
@Nonnull
private final ResourceType<EntityStore, WorldTimeResource> worldTimeResourceType;
public UpdateWorldSlumberSystem(
@Nonnull ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType,
@Nonnull ResourceType<EntityStore, WorldSomnolence> worldSomnolenceResourceType,
@Nonnull ResourceType<EntityStore, WorldTimeResource> worldTimeResourceType
) {
this.playerSomnolenceComponentType = playerSomnolenceComponentType;
this.worldSomnolenceResourceType = worldSomnolenceResourceType;
this.worldTimeResourceType = worldTimeResourceType;
}
@Override
public void tick(float dt, int systemIndex, @Nonnull Store<EntityStore> 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<EntityStore> 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<EntityStore> {
return slumber.getStartInstant().plusNanos(progressNanos);
}
private static boolean isSomeoneAwake(@Nonnull ComponentAccessor<EntityStore> store) {
private static boolean isSomeoneAwake(
@Nonnull ComponentAccessor<EntityStore> store, @Nonnull ComponentType<EntityStore, PlayerSomnolence> playerSomnolenceComponentType
) {
World world = store.getExternalData().getWorld();
Collection<PlayerRef> playerRefs = world.getPlayerRefs();
if (playerRefs.isEmpty()) {
@@ -62,7 +87,7 @@ public class UpdateWorldSlumberSystem extends TickingSystem<EntityStore> {
for (PlayerRef playerRef : playerRefs) {
Ref<EntityStore> 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;
}

View File

@@ -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<BlockPhysicsSystems.CachedAccessor> 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<ChunkStore> implements DisableProcessingAssert {
@Nonnull
private static final Query<ChunkStore> QUERY = Query.and(
ChunkSection.getComponentType(), BlockSection.getComponentType(), BlockPhysics.getComponentType(), FluidSection.getComponentType()
);
@Nonnull
private static final Set<Dependency<ChunkStore>> 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<ChunkStore> 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);
}
}
}

View File

@@ -34,7 +34,7 @@ public class BlockPhysicsUtil {
@Nonnull
public static BlockPhysicsUtil.Result applyBlockPhysics(
@Nullable ComponentAccessor<EntityStore> commandBuffer,
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
@Nonnull Ref<ChunkStore> 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> 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,

View File

@@ -31,16 +31,17 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class PrefabBufferValidator {
@Nonnull
private static final FillerBlockUtil.FillerFetcher<IPrefabBuffer, Void> FILLER_FETCHER = new FillerBlockUtil.FillerFetcher<IPrefabBuffer, Void>() {
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);
}
};

View File

@@ -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<ChunkStore> blockComponents;
@@ -63,6 +64,7 @@ public class BlockSpawnerEntry implements IWeightedElement {
RANDOM,
INHERIT;
@Nonnull
public static final Codec<BlockSpawnerEntry.RotationMode> CODEC = new EnumCodec<>(BlockSpawnerEntry.RotationMode.class);
}
}

View File

@@ -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<ChunkStore, BlockSpawner> 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<ChunkStore> 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<ChunkStore> {
@Nonnull
private static final ComponentType<ChunkStore, BlockSpawner> COMPONENT_TYPE = BlockSpawner.getComponentType();
@Nonnull
private static final ComponentType<ChunkStore, BlockModule.BlockStateInfo> BLOCK_INFO_COMPONENT_TYPE = BlockModule.BlockStateInfo.getComponentType();
@Nonnull
private static final Query<ChunkStore> 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<ChunkStore> 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<ChunkStore> 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<ChunkStore> holder = entry.getBlockComponents();
commandBuffer.removeEntity(ref, RemoveReason.REMOVE);
commandBuffer.run(_store -> {
int flags = 4;
if (holder != null) {
flags |= 2;
}
}
};
Holder<ChunkStore> 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());
}
});
}
}
}
}

View File

@@ -16,6 +16,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockSpawnerTable implements JsonAssetWithMap<String, DefaultAssetMap<String, BlockSpawnerTable>> {
@Nonnull
public static final AssetBuilderCodec<String, BlockSpawnerTable> CODEC = AssetBuilderCodec.builder(
BlockSpawnerTable.class,
BlockSpawnerTable::new,

View File

@@ -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<RelativeIntPosition> positionArg = this.withOptionalArg(
@@ -47,6 +49,10 @@ public class BlockSpawnerGetCommand extends AbstractWorldCommand {
}
Ref<EntityStore> 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<ChunkStore> 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()));

View File

@@ -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<BlockSpawnerTable> 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<EntityStore> 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<ChunkStore> 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<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(position.x, position.y, position.z);
if (blockRef != null && blockRef.isValid()) {
Store<ChunkStore> 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()));
}
}
}

View File

@@ -11,6 +11,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockSpawner implements Component<ChunkStore> {
@Nonnull
public static final BuilderCodec<BlockSpawner> CODEC = BuilderCodec.builder(BlockSpawner.class, BlockSpawner::new)
.addField(new KeyedCodec<>("BlockSpawnerId", Codec.STRING), (state, s) -> state.blockSpawnerId = s, state -> state.blockSpawnerId)
.build();

View File

@@ -55,19 +55,17 @@ public class BlockTickPlugin extends JavaPlugin implements IBlockTickProvider {
}
}
public int discoverTickingBlocks(@Nonnull Holder<ChunkStore> holder, @Nonnull WorldChunk chunk) {
public int discoverTickingBlocks(@Nonnull Holder<ChunkStore> 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<ChunkStore>[] sections = column.getSectionHolders();
Holder<ChunkStore>[] 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<ChunkStore> 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;
}
}
}

View File

@@ -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<BasicChanceBlockGrowthProcedure> CODEC = BuilderCodec.builder(
BasicChanceBlockGrowthProcedure.class, BasicChanceBlockGrowthProcedure::new, TickProcedure.BASE_CODEC
)

View File

@@ -14,6 +14,7 @@ import org.bson.BsonDocument;
import org.bson.BsonValue;
public class SplitChanceBlockGrowthProcedure extends BasicChanceBlockGrowthProcedure {
@Nonnull
public static final BuilderCodec<SplitChanceBlockGrowthProcedure> CODEC = BuilderCodec.builder(
SplitChanceBlockGrowthProcedure.class, SplitChanceBlockGrowthProcedure::new, TickProcedure.BASE_CODEC
)

View File

@@ -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<ChunkStore> {
private static final ComponentType<ChunkStore, BlockChunk> COMPONENT_TYPE = BlockChunk.getComponentType();
@Nonnull
private static final ComponentType<ChunkStore, BlockChunk> COMPONENT_TYPE_WORLD_CHUNK = BlockChunk.getComponentType();
@Override
public Query<ChunkStore> getQuery() {
return COMPONENT_TYPE;
return COMPONENT_TYPE_WORLD_CHUNK;
}
@Override
@@ -50,26 +53,30 @@ public class ChunkBlockTickSystem {
@Nonnull Store<ChunkStore> store,
@Nonnull CommandBuffer<ChunkStore> 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> 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<ChunkStore> {
private static final ComponentType<ChunkStore, WorldChunk> COMPONENT_TYPE = WorldChunk.getComponentType();
@Nonnull
private static final ComponentType<ChunkStore, WorldChunk> COMPONENT_TYPE_WORLD_CHUNK = WorldChunk.getComponentType();
@Nonnull
private static final Set<Dependency<ChunkStore>> DEPENDENCIES = Set.of(new SystemDependency<>(Order.AFTER, ChunkBlockTickSystem.PreTick.class));
@Override
public Query<ChunkStore> getQuery() {
return COMPONENT_TYPE;
return COMPONENT_TYPE_WORLD_CHUNK;
}
@Nonnull
@@ -87,24 +94,33 @@ public class ChunkBlockTickSystem {
@Nonnull CommandBuffer<ChunkStore> commandBuffer
) {
Ref<ChunkStore> 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<ChunkStore> 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<ChunkStore> 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());
}
}
}

View File

@@ -15,6 +15,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import javax.annotation.Nonnull;
public class MergeWaitingBlocksSystem extends RefSystem<ChunkStore> {
@Nonnull
private static final ComponentType<ChunkStore, WorldChunk> COMPONENT_TYPE = WorldChunk.getComponentType();
@Override
@@ -27,9 +28,12 @@ public class MergeWaitingBlocksSystem extends RefSystem<ChunkStore> {
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> 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<ChunkStore> {
}
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();
}
}
}

View File

@@ -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<Pair<Integer, String>> 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<Pair<Integer, String>> layers, Vector3i direction, ComponentAccessor<EntityStore> 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<Integer, String> 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<Pair<Integer, String>> layers, WorldChunk chunk, BlockSelection before, BlockSelection after
) {
int currentDepth = 0;
for (Pair<Integer, String> layer : layers) {
currentDepth += layer.left();
if (depth < currentDepth) {
int currentBlock = chunk.getBlock(x, y, z);
int currentBlockFiller = chunk.getFiller(x, y, z);
Holder<ChunkStore> 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<ChunkStore> 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<EntityStore> ref, int x, int y, int z, @Nonnull ComponentAccessor<EntityStore> componentAccessor) {
return this.paste(ref, x, y, z, false, componentAccessor);
}

View File

@@ -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<String, Vector3i> 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<String> layerDirectionArg = this.withRequiredArg("direction", "server.commands.layer.direction.desc", ArgTypes.STRING);
@Nonnull
private final RequiredArg<List<Pair<Integer, String>>> 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<EntityStore> store, @Nonnull Ref<EntityStore> 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<Pair<Integer, String>> 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()));
}
}
}
}

View File

@@ -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<ImageImportPage.Pag
this.setError("Please enter a path to an image file");
} else {
Path path = Paths.get(this.imagePath);
if (!Files.exists(path)) {
if (!AssetModule.get().isWithinPackSubDir(path, "Server/Imports/Images")) {
this.setError("File must be within an asset pack's imports directory");
} else if (!Files.exists(path)) {
this.setError("File not found: " + this.imagePath);
} else {
this.isProcessing = true;

View File

@@ -9,15 +9,12 @@ import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.protocol.InteractionState;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.entity.InteractionContext;
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.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.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInstantInteraction;
@@ -59,29 +56,29 @@ public class PickupItemInteraction extends SimpleInstantInteraction {
context.getState().state = InteractionState.Failed;
} else {
ItemStack itemStack = itemComponent.getItemStack();
Item item = itemStack.getItem();
Vector3d itemEntityPosition = transformComponent.getPosition();
PlayerSettings playerSettings = commandBuffer.getComponent(ref, PlayerSettings.getComponentType());
if (playerSettings == null) {
playerSettings = PlayerSettings.defaults();
}
if (!ItemStack.isEmpty(itemStack)) {
Vector3d itemEntityPosition = transformComponent.getPosition();
ItemStackTransaction transaction = playerComponent.giveItem(itemStack, ref, commandBuffer);
ItemStack remainder = transaction.getRemainder();
if (ItemStack.isEmpty(remainder)) {
itemComponent.setRemovedByPlayerPickup(true);
commandBuffer.removeEntity(targetRef, RemoveReason.REMOVE);
playerComponent.notifyPickupItem(ref, itemStack, itemEntityPosition, commandBuffer);
Holder<EntityStore> 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<EntityStore> 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<EntityStore> 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<EntityStore> 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);
}
}
}
}

View File

@@ -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<ObjImportPage.PageDat
private void performImport(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> 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<ObjImportPage.WeightedBlock> blocks = this.parseBlockPattern(this.blockPattern);
if (blocks == null) {
@@ -577,8 +581,8 @@ public class ObjImportPage extends InteractiveCustomUIPage<ObjImportPage.PageDat
boolean autoDetectTextures
) throws IOException {
if (mesh.mtlLib() != null) {
Path mtlPath = objPath.getParent().resolve(mesh.mtlLib());
if (Files.exists(mtlPath)) {
Path mtlPath = PathUtil.resolvePathWithinDir(objPath.getParent(), mesh.mtlLib());
if (mtlPath != null && Files.exists(mtlPath)) {
Map<String, MtlParser.MtlMaterial> materials = MtlParser.parse(mtlPath);
Path textureDir = mtlPath.getParent();
@@ -591,7 +595,11 @@ public class ObjImportPage extends InteractiveCustomUIPage<ObjImportPage.PageDat
}
if (texturePath != null) {
Path resolvedPath = textureDir.resolve(texturePath);
Path resolvedPath = PathUtil.resolvePathWithinDir(textureDir, texturePath);
if (resolvedPath == null) {
continue;
}
BufferedImage texture = TextureSampler.loadTexture(resolvedPath);
if (texture != null) {
materialTextures.put(materialName, texture);

View File

@@ -5,6 +5,7 @@ import com.hypixel.hytale.builtin.buildertools.prefabeditor.PrefabEditorCreation
import com.hypixel.hytale.builtin.buildertools.prefabeditor.enums.PrefabRootDirectory;
import com.hypixel.hytale.builtin.buildertools.prefabeditor.enums.WorldGenType;
import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.common.util.PathUtil;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.Message;
@@ -72,11 +73,8 @@ public class PrefabEditCreateNewCommand extends AbstractAsyncPlayerCommand {
prefabName = prefabName + ".prefab.json";
}
Path prefabPath = prefabBaseDirectory.resolve(prefabName);
if (prefabPath.toString().endsWith("/")) {
context.sendMessage(MESSAGE_COMMANDS_EDIT_PREFAB_NEW_ERRORS_NOT_A_FILE);
return CompletableFuture.completedFuture(null);
} else {
Path prefabPath = PathUtil.resolvePathWithinDir(prefabBaseDirectory, prefabName);
if (prefabPath != null && !prefabPath.toString().endsWith("/")) {
PrefabEditorCreationSettings prefabEditorLoadCommandSettings = new PrefabEditorCreationSettings(
this.prefabPathArg.get(context),
List.of(prefabName),
@@ -98,6 +96,9 @@ public class PrefabEditCreateNewCommand extends AbstractAsyncPlayerCommand {
return BuilderToolsPlugin.get()
.getPrefabEditSessionManager()
.createEditSessionForNewPrefab(ref, playerComponent, prefabEditorLoadCommandSettings, store);
} else {
context.sendMessage(MESSAGE_COMMANDS_EDIT_PREFAB_NEW_ERRORS_NOT_A_FILE);
return CompletableFuture.completedFuture(null);
}
}
}

View File

@@ -10,6 +10,7 @@ import com.hypixel.hytale.common.util.PathUtil;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.asset.AssetModule;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractAsyncPlayerCommand;
@@ -44,9 +45,14 @@ public class PrefabEditSaveCommand extends AbstractAsyncPlayerCommand {
private static boolean isPathInAllowedPrefabDirectory(@Nonnull Path path) {
PrefabStore prefabStore = PrefabStore.get();
return PathUtil.isChildOf(prefabStore.getServerPrefabsPath(), path)
|| PathUtil.isChildOf(prefabStore.getAssetPrefabsPath(), path)
|| PathUtil.isChildOf(prefabStore.getWorldGenPrefabsPath(), path);
if (PathUtil.isChildOf(prefabStore.getServerPrefabsPath(), path)) {
return true;
} else if (PathUtil.isChildOf(prefabStore.getWorldGenPrefabsPath(), path)) {
return true;
} else {
AssetModule assetModule = AssetModule.get();
return assetModule.isWithinPackSubDir(path, "Server/Prefabs") && !assetModule.isAssetPathImmutable(path);
}
}
public PrefabEditSaveCommand() {

View File

@@ -627,7 +627,7 @@ public class PrefabEditorLoadSettingsPage extends InteractiveCustomUIPage<Prefab
private void handleRegularNavigation(@Nonnull String fileName) {
Path file = this.browserRoot.resolve(this.browserCurrent).resolve(fileName);
if (!file.normalize().startsWith(this.browserRoot.normalize())) {
if (!PathUtil.isChildOf(this.browserRoot, file)) {
this.sendUpdate();
} else {
if (Files.isDirectory(file)) {

View File

@@ -1,5 +1,6 @@
package com.hypixel.hytale.builtin.buildertools.prefablist;
import com.hypixel.hytale.common.util.PathUtil;
import com.hypixel.hytale.common.util.StringCompareUtil;
import com.hypixel.hytale.server.core.prefab.PrefabStore;
import com.hypixel.hytale.server.core.ui.browser.FileListProvider;
@@ -67,7 +68,10 @@ public class AssetPrefabFileProvider implements FileListProvider {
} else {
Path targetPath = packPath.prefabsPath();
if (!subPath.isEmpty()) {
targetPath = targetPath.resolve(subPath);
targetPath = PathUtil.resolvePathWithinDir(targetPath, subPath);
if (targetPath == null) {
return entries;
}
}
if (!Files.isDirectory(targetPath)) {
@@ -116,7 +120,10 @@ public class AssetPrefabFileProvider implements FileListProvider {
if (packPath != null) {
Path searchRoot = packPath.prefabsPath();
if (!subPath.isEmpty()) {
searchRoot = searchRoot.resolve(subPath);
searchRoot = PathUtil.resolvePathWithinDir(searchRoot, subPath);
if (searchRoot == null) {
return List.of();
}
}
this.searchInDirectory(searchRoot, packKey, subPath, lowerQuery, allResults);
@@ -203,7 +210,7 @@ public class AssetPrefabFileProvider implements FileListProvider {
if (packPath == null) {
return null;
} else {
return subPath.isEmpty() ? packPath.prefabsPath() : packPath.prefabsPath().resolve(subPath);
return subPath.isEmpty() ? packPath.prefabsPath() : PathUtil.resolvePathWithinDir(packPath.prefabsPath(), subPath);
}
}
}

View File

@@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.buildertools.prefablist;
import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin;
import com.hypixel.hytale.builtin.buildertools.utils.PasteToolUtil;
import com.hypixel.hytale.common.util.PathUtil;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.protocol.GameMode;
@@ -161,13 +162,8 @@ public class PrefabPage extends InteractiveCustomUIPage<FileBrowserEventData> {
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 {

View File

@@ -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<EntityStore> 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<String, Object> toolArgs = this.getToolArgs(ref, componentAccessor);
List<Pair<Integer, String>> 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<String, Object> toolArgs, BrushConfig brushConfig) {
private String resolveBlockPattern(LayerEntryCodec entry, @Nullable Map<String, Object> 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();
}
}

View File

@@ -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<Pair<Integer, String>> layers;
public LayersOperation(
@Nonnull Ref<EntityStore> 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;
}
}
}

View File

@@ -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<String> messageArg = this.withRequiredArg("message", "server.commands.echos.message.desc", ArgTypes.STRING);
public EchoCommand() {

View File

@@ -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<String, Argument<?, ?>> arguments = new Object2ObjectOpenHashMap<>();
@Nonnull
private final List<Pair<String, List<MacroCommandReplacement>>> commandReplacements = new ObjectArrayList<>();
private final Map<String, String> 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));
}

View File

@@ -12,6 +12,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class MacroCommandBuilder implements JsonAssetWithMap<String, DefaultAssetMap<String, MacroCommandBuilder>> {
@Nonnull
public static final AssetBuilderCodec<String, MacroCommandBuilder> CODEC = AssetBuilderCodec.builder(
MacroCommandBuilder.class,
MacroCommandBuilder::new,

View File

@@ -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<MacroCommandParameter> CODEC = BuilderCodec.builder(MacroCommandParameter.class, MacroCommandParameter::new)
.append(new KeyedCodec<>("Name", Codec.STRING, true), (macroParameter, name) -> macroParameter.name = name, macroParameter -> macroParameter.name)
.add()

View File

@@ -13,6 +13,7 @@ import javax.annotation.Nonnull;
public class MacroCommandPlugin extends JavaPlugin {
private static MacroCommandPlugin instance;
@Nonnull
private final Map<String, CommandRegistration> macroCommandRegistrations = new Object2ObjectOpenHashMap<>();
public static MacroCommandPlugin get() {

View File

@@ -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<Float> 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() {

View File

@@ -19,16 +19,22 @@ import javax.annotation.Nullable;
public class BenchRecipeRegistry {
private final String benchId;
@Nonnull
private final Map<String, Set<String>> categoryMap = new Object2ObjectOpenHashMap<>();
@Nonnull
private final Map<String, Set<String>> itemToIncomingRecipe = new Object2ObjectOpenHashMap<>();
@Nonnull
private final Set<String> uncategorizedRecipes = new ObjectOpenHashSet<>();
@Nonnull
private final Set<String> allMaterialIds = new ObjectOpenHashSet<>();
@Nonnull
private final Set<String> allMaterialResourceType = new ObjectOpenHashSet<>();
public BenchRecipeRegistry(String benchId) {
this.benchId = benchId;
}
@Nonnull
public Iterable<String> getIncomingRecipesForItem(@Nonnull String itemId) {
Set<String> 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<String> recipes) {
private void extractMaterialFromRecipes(@Nonnull Set<String> 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='"

View File

@@ -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<String, BenchRecipeRegistry> registries = new Object2ObjectOpenHashMap<>();
@Nonnull
private static final Map<String, String[]> itemGeneratedRecipes = new Object2ObjectOpenHashMap<>();
private ComponentType<EntityStore, CraftingManager> craftingManagerComponentType;
@@ -69,17 +72,17 @@ public class CraftingPlugin extends JavaPlugin {
}
@Nullable
public static Set<String> getAvailableRecipesForCategory(String benchId, String benchCategoryId) {
public static Set<String> 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<EntityStore> 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<EntityStore, Player> playerComponentType = Player.getComponentType();
ComponentType<EntityStore, PlayerRef> 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<String, Item, DefaultAssetMap<String, Item>> event) {
private static void onItemAssetLoad(@Nonnull LoadedAssetsEvent<String, Item, DefaultAssetMap<String, Item>> event) {
List<CraftingRecipe> recipesToLoad = new ObjectArrayList<>();
for (Item item : event.getLoadedAssets().values()) {
@@ -174,7 +180,7 @@ public class CraftingPlugin extends JavaPlugin {
}
}
private static void onRecipeLoad(LoadedAssetsEvent<String, CraftingRecipe, DefaultAssetMap<String, CraftingRecipe>> event) {
private static void onRecipeLoad(@Nonnull LoadedAssetsEvent<String, CraftingRecipe, DefaultAssetMap<String, CraftingRecipe>> 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<String, CraftingRecipe, DefaultAssetMap<String, CraftingRecipe>> event) {
private static void onRecipeRemove(@Nonnull RemovedAssetsEvent<String, CraftingRecipe, DefaultAssetMap<String, CraftingRecipe>> 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<EntityStore> {
private static final Query<EntityStore> QUERY = Archetype.of(Player.getComponentType(), PlayerRef.getComponentType());
@Nonnull
private final Query<EntityStore> query;
public PlayerAddedSystem(
@Nonnull ComponentType<EntityStore, Player> playerComponentType, @Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType
) {
this.query = Archetype.of(playerComponentType, playerRefComponentType);
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return QUERY;
return this.query;
}
@Override

View File

@@ -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<EntityStore> {
} else {
List<ItemStack> 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<EntityStore> {
this.timeSeconds = timeSeconds;
}
@Nonnull
@Override
public String toString() {
return "BenchUpgradingJob{window=" + this.window + ", timeSeconds=" + this.timeSeconds + "}";

View File

@@ -24,6 +24,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class LearnRecipeInteraction extends SimpleInstantInteraction {
@Nonnull
public static final KeyedCodec<String> ITEM_ID = new KeyedCodec<>("ItemId", Codec.STRING);
@Nonnull
public static final BuilderCodec<LearnRecipeInteraction> 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;

View File

@@ -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<OpenBenchPageInteraction> CODEC = BuilderCodec.builder(

View File

@@ -33,6 +33,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class OpenProcessingBenchInteraction extends SimpleBlockInteraction {
@Nonnull
public static final BuilderCodec<OpenProcessingBenchInteraction> 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();

View File

@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
public class BenchState extends BlockState implements DestroyableBlockState {
@Nonnull
public static BuilderCodec<BenchState> 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<UUID, BenchWindow> windows = new ConcurrentHashMap<>();
public int getTierLevel() {
@@ -71,7 +73,7 @@ public class BenchState extends BlockState implements DestroyableBlockState {
}
}
public void addUpgradeItems(List<ItemStack> consumed) {
public void addUpgradeItems(@Nonnull List<ItemStack> 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";
}

View File

@@ -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<ProcessingBenchState> 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<Short> processingSlots = new HashSet<>();
@Nonnull
private final Set<Short> 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<EntityStore> 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);
}
}

Some files were not shown because too many files have changed in this diff Show More