2026.02.06-0baf7c5aa
This commit is contained in:
@@ -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 -> {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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='"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 + "}";
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user