2026.02.17-255364b8e
This commit is contained in:
@@ -13,7 +13,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
implementation(files("${System.getenv("APPDATA")}/Hytale/install/release/package/game/latest/Server/HytaleServer.jar"))
|
||||
implementation(files("${System.getenv("APPDATA")}/Hytale/install/pre-release/package/game/latest/Server/HytaleServer.jar"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,16 +10,21 @@ 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 {
|
||||
@Nonnull
|
||||
private static final String CODEC_CAMERA_SHAKE = "CameraShake";
|
||||
|
||||
public CameraPlugin(@Nonnull JavaPluginInit init) {
|
||||
@@ -54,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale.protocol.CameraShakeConfig> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CameraShakeConfig> CODEC = BuilderCodec.builder(CameraShakeConfig.class, CameraShakeConfig::new)
|
||||
.appendInherited(new KeyedCodec<>("Duration", Codec.FLOAT), (o, v) -> o.duration = v, o -> o.duration, (o, p) -> o.duration = p.duration)
|
||||
.documentation("The time period that the camera will shake at full intensity for")
|
||||
@@ -73,6 +74,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
}
|
||||
|
||||
public static class OffsetNoise implements NetworkSerializable<com.hypixel.hytale.protocol.OffsetNoise> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CameraShakeConfig.OffsetNoise> CODEC = BuilderCodec.builder(
|
||||
CameraShakeConfig.OffsetNoise.class, CameraShakeConfig.OffsetNoise::new
|
||||
)
|
||||
@@ -89,6 +91,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
.documentation("The noise used to vary the camera z-offset")
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final CameraShakeConfig.OffsetNoise NONE = new CameraShakeConfig.OffsetNoise();
|
||||
protected NoiseConfig[] x;
|
||||
protected NoiseConfig[] y;
|
||||
@@ -113,6 +116,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
}
|
||||
|
||||
public static class RotationNoise implements NetworkSerializable<com.hypixel.hytale.protocol.RotationNoise> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CameraShakeConfig.RotationNoise> CODEC = BuilderCodec.builder(
|
||||
CameraShakeConfig.RotationNoise.class, CameraShakeConfig.RotationNoise::new
|
||||
)
|
||||
@@ -129,6 +133,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
.documentation("The noise used to vary the camera roll")
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final CameraShakeConfig.RotationNoise NONE = new CameraShakeConfig.RotationNoise();
|
||||
protected NoiseConfig[] pitch;
|
||||
protected NoiseConfig[] yaw;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.hypixel.hytale.builtin.adventure.camera.asset.camerashake;
|
||||
|
||||
import com.hypixel.hytale.assetstore.map.IndexedAssetMap;
|
||||
import com.hypixel.hytale.protocol.CachedPacket;
|
||||
import com.hypixel.hytale.protocol.Packet;
|
||||
import com.hypixel.hytale.protocol.ToClientPacket;
|
||||
import com.hypixel.hytale.protocol.UpdateType;
|
||||
import com.hypixel.hytale.protocol.packets.assets.UpdateCameraShake;
|
||||
import com.hypixel.hytale.server.core.asset.packet.SimpleAssetPacketGenerator;
|
||||
@@ -14,17 +14,17 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<String, CameraShake, IndexedAssetMap<String, CameraShake>> {
|
||||
@Nonnull
|
||||
public Packet generateInitPacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) {
|
||||
public ToClientPacket generateInitPacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) {
|
||||
return toCachedPacket(UpdateType.Init, assetMap, assets);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected Packet generateUpdatePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> loadedAssets) {
|
||||
protected ToClientPacket generateUpdatePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> loadedAssets) {
|
||||
return toCachedPacket(UpdateType.AddOrUpdate, assetMap, loadedAssets);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected Packet generateRemovePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Set<String> removed) {
|
||||
protected ToClientPacket generateRemovePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Set<String> removed) {
|
||||
Int2ObjectOpenHashMap<com.hypixel.hytale.protocol.CameraShake> profiles = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
for (String key : removed) {
|
||||
@@ -39,7 +39,9 @@ public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<Strin
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected static Packet toCachedPacket(UpdateType type, @Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) {
|
||||
protected static ToClientPacket toCachedPacket(
|
||||
@Nonnull UpdateType type, @Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets
|
||||
) {
|
||||
Int2ObjectOpenHashMap<com.hypixel.hytale.protocol.CameraShake> profiles = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
for (Entry<String, CameraShake> entry : assets.entrySet()) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.hypixel.hytale.builtin.adventure.camera.asset.viewbobbing;
|
||||
import com.hypixel.hytale.assetstore.AssetMap;
|
||||
import com.hypixel.hytale.protocol.CachedPacket;
|
||||
import com.hypixel.hytale.protocol.MovementType;
|
||||
import com.hypixel.hytale.protocol.Packet;
|
||||
import com.hypixel.hytale.protocol.ToClientPacket;
|
||||
import com.hypixel.hytale.protocol.UpdateType;
|
||||
import com.hypixel.hytale.protocol.packets.assets.UpdateViewBobbing;
|
||||
import com.hypixel.hytale.server.core.asset.packet.SimpleAssetPacketGenerator;
|
||||
@@ -16,19 +16,19 @@ import javax.annotation.Nonnull;
|
||||
public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<MovementType, ViewBobbing, AssetMap<MovementType, ViewBobbing>> {
|
||||
@Nonnull
|
||||
@Override
|
||||
public Packet generateInitPacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> assets) {
|
||||
public ToClientPacket generateInitPacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> assets) {
|
||||
return toCachedPacket(UpdateType.Init, assets);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Packet generateUpdatePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> loadedAssets) {
|
||||
protected ToClientPacket generateUpdatePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> loadedAssets) {
|
||||
return toCachedPacket(UpdateType.AddOrUpdate, loadedAssets);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Packet generateRemovePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Set<MovementType> removed) {
|
||||
protected ToClientPacket generateRemovePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Set<MovementType> removed) {
|
||||
UpdateViewBobbing packet = new UpdateViewBobbing();
|
||||
packet.type = UpdateType.Remove;
|
||||
packet.profiles = new EnumMap<>(MovementType.class);
|
||||
@@ -41,7 +41,7 @@ public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<Movem
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected static Packet toCachedPacket(UpdateType type, @Nonnull Map<MovementType, ViewBobbing> assets) {
|
||||
protected static ToClientPacket toCachedPacket(@Nonnull UpdateType type, @Nonnull Map<MovementType, ViewBobbing> assets) {
|
||||
UpdateViewBobbing packet = new UpdateViewBobbing();
|
||||
packet.type = type;
|
||||
packet.profiles = new EnumMap<>(MovementType.class);
|
||||
|
||||
@@ -80,7 +80,6 @@ public class CameraEffectCommand extends AbstractCommandCollection {
|
||||
}
|
||||
|
||||
protected static class DebugCommand extends AbstractTargetPlayerCommand {
|
||||
private static final String MESSAGE_SUCCESS = "server.commands.camshake.debug.success";
|
||||
@Nonnull
|
||||
protected final RequiredArg<CameraEffect> effectArg = this.withRequiredArg(
|
||||
"effect", "server.commands.camshake.effect.desc", CameraEffectCommand.CAMERA_EFFECT_ARGUMENT_TYPE
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlock;
|
||||
import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlockState;
|
||||
import com.hypixel.hytale.builtin.adventure.farming.states.TilledSoilBlock;
|
||||
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.Holder;
|
||||
import com.hypixel.hytale.event.EventPriority;
|
||||
@@ -31,10 +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;
|
||||
@@ -60,28 +66,29 @@ public class FarmingPlugin extends JavaPlugin {
|
||||
@Override
|
||||
protected void setup() {
|
||||
instance = this;
|
||||
this.getAssetRegistry()
|
||||
.register(
|
||||
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
|
||||
GrowthModifierAsset.class, new DefaultAssetMap()
|
||||
)
|
||||
.setPath("Farming/Modifiers"))
|
||||
.setCodec(GrowthModifierAsset.CODEC))
|
||||
.loadsAfter(Weather.class))
|
||||
.setKeyFunction(GrowthModifierAsset::getId))
|
||||
.build()
|
||||
);
|
||||
this.getAssetRegistry()
|
||||
.register(
|
||||
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
|
||||
FarmingCoopAsset.class, new DefaultAssetMap()
|
||||
)
|
||||
.setPath("Farming/Coops"))
|
||||
.setCodec(FarmingCoopAsset.CODEC))
|
||||
.loadsAfter(ItemDropList.class, NPCGroup.class))
|
||||
.setKeyFunction(FarmingCoopAsset::getId))
|
||||
.build()
|
||||
);
|
||||
AssetRegistry assetRegistry = this.getAssetRegistry();
|
||||
ComponentRegistryProxy<ChunkStore> chunkStoreRegistry = this.getChunkStoreRegistry();
|
||||
ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
|
||||
assetRegistry.register(
|
||||
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
|
||||
GrowthModifierAsset.class, new DefaultAssetMap()
|
||||
)
|
||||
.setPath("Farming/Modifiers"))
|
||||
.setCodec(GrowthModifierAsset.CODEC))
|
||||
.loadsAfter(Weather.class))
|
||||
.setKeyFunction(GrowthModifierAsset::getId))
|
||||
.build()
|
||||
);
|
||||
assetRegistry.register(
|
||||
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
|
||||
FarmingCoopAsset.class, new DefaultAssetMap()
|
||||
)
|
||||
.setPath("Farming/Coops"))
|
||||
.setCodec(FarmingCoopAsset.CODEC))
|
||||
.loadsAfter(ItemDropList.class, NPCGroup.class))
|
||||
.setKeyFunction(FarmingCoopAsset::getId))
|
||||
.build()
|
||||
);
|
||||
this.getCodecRegistry(Interaction.CODEC)
|
||||
.register("HarvestCrop", HarvestCropInteraction.class, HarvestCropInteraction.CODEC)
|
||||
.register("FertilizeSoil", FertilizeSoilInteraction.class, FertilizeSoilInteraction.CODEC)
|
||||
@@ -97,23 +104,34 @@ public class FarmingPlugin extends JavaPlugin {
|
||||
this.getCodecRegistry(FarmingStageData.CODEC).register("Prefab", PrefabFarmingStageData.class, PrefabFarmingStageData.CODEC);
|
||||
this.getCodecRegistry(FarmingStageData.CODEC).register("Spread", SpreadFarmingStageData.class, SpreadFarmingStageData.CODEC);
|
||||
this.getCodecRegistry(SpreadGrowthBehaviour.CODEC).register("Directional", DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour.CODEC);
|
||||
this.tiledSoilBlockComponentType = this.getChunkStoreRegistry().registerComponent(TilledSoilBlock.class, "TilledSoil", TilledSoilBlock.CODEC);
|
||||
this.farmingBlockComponentType = this.getChunkStoreRegistry().registerComponent(FarmingBlock.class, "FarmingBlock", FarmingBlock.CODEC);
|
||||
this.farmingBlockStateComponentType = this.getChunkStoreRegistry().registerComponent(FarmingBlockState.class, "Farming", FarmingBlockState.CODEC);
|
||||
this.coopBlockStateComponentType = this.getChunkStoreRegistry().registerComponent(CoopBlock.class, "Coop", CoopBlock.CODEC);
|
||||
this.coopResidentComponentType = this.getEntityStoreRegistry()
|
||||
.registerComponent(CoopResidentComponent.class, "CoopResident", CoopResidentComponent.CODEC);
|
||||
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.OnSoilAdded());
|
||||
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.OnFarmBlockAdded());
|
||||
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.Ticking());
|
||||
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.MigrateFarming());
|
||||
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.OnCoopAdded());
|
||||
this.getEntityStoreRegistry().registerSystem(new FarmingSystems.CoopResidentEntitySystem());
|
||||
this.getEntityStoreRegistry().registerSystem(new FarmingSystems.CoopResidentTicking());
|
||||
this.tiledSoilBlockComponentType = chunkStoreRegistry.registerComponent(TilledSoilBlock.class, "TilledSoil", TilledSoilBlock.CODEC);
|
||||
this.farmingBlockComponentType = chunkStoreRegistry.registerComponent(FarmingBlock.class, "FarmingBlock", FarmingBlock.CODEC);
|
||||
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);
|
||||
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(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);
|
||||
}
|
||||
|
||||
private static void preventSpreadOnNew(ChunkPreLoadProcessEvent event) {
|
||||
private static void preventSpreadOnNew(@Nonnull ChunkPreLoadProcessEvent event) {
|
||||
if (event.isNewlyGenerated()) {
|
||||
BlockComponentChunk components = event.getHolder().getComponent(BlockComponentChunk.getComponentType());
|
||||
if (components != null) {
|
||||
|
||||
@@ -42,13 +42,14 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.core.util.TargetUtil;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FarmingSystems {
|
||||
private static boolean hasCropAbove(BlockChunk blockChunk, int x, int y, int z) {
|
||||
private static boolean hasCropAbove(@Nonnull BlockChunk blockChunk, int x, int y, int z) {
|
||||
if (y + 1 >= 320) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -67,35 +68,54 @@ public class FarmingSystems {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean updateSoilDecayTime(CommandBuffer<ChunkStore> commandBuffer, TilledSoilBlock soilBlock, BlockType blockType) {
|
||||
if (blockType != null && blockType.getFarming() != null && blockType.getFarming().getSoilConfig() != null) {
|
||||
FarmingData.SoilConfig soilConfig = blockType.getFarming().getSoilConfig();
|
||||
Rangef range = soilConfig.getLifetime();
|
||||
if (range == null) {
|
||||
return false;
|
||||
} else {
|
||||
double baseDuration = range.min + (range.max - range.min) * ThreadLocalRandom.current().nextDouble();
|
||||
Instant currentTime = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType())
|
||||
.getGameTime();
|
||||
Instant endTime = currentTime.plus(Math.round(baseDuration), ChronoUnit.SECONDS);
|
||||
soilBlock.setDecayTime(endTime);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
private static boolean updateSoilDecayTime(
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull TilledSoilBlock soilBlock, @Nullable BlockType blockType
|
||||
) {
|
||||
if (blockType == null) {
|
||||
return false;
|
||||
} else {
|
||||
FarmingData farming = blockType.getFarming();
|
||||
if (farming != null && farming.getSoilConfig() != null) {
|
||||
FarmingData.SoilConfig soilConfig = farming.getSoilConfig();
|
||||
Rangef range = soilConfig.getLifetime();
|
||||
if (range == null) {
|
||||
return false;
|
||||
} else {
|
||||
double baseDuration = range.min + (range.max - range.min) * ThreadLocalRandom.current().nextDouble();
|
||||
Instant currentTime = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType())
|
||||
.getGameTime();
|
||||
Instant endTime = currentTime.plus(Math.round(baseDuration), ChronoUnit.SECONDS);
|
||||
soilBlock.setDecayTime(endTime);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CoopResidentEntitySystem extends RefSystem<EntityStore> {
|
||||
private static final ComponentType<EntityStore, CoopResidentComponent> componentType = 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 componentType;
|
||||
return this.coopResidentComponentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,26 +129,26 @@ 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, componentType);
|
||||
CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, this.coopResidentComponentType);
|
||||
if (coopResidentComponent != null) {
|
||||
Vector3i coopPosition = coopResidentComponent.getCoopLocation();
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(coopPosition.x, coopPosition.z);
|
||||
WorldChunk chunk = world.getChunkIfLoaded(chunkIndex);
|
||||
if (chunk != null) {
|
||||
Ref<ChunkStore> chunkReference = world.getChunkStore().getChunkReference(chunkIndex);
|
||||
if (chunkReference != null && chunkReference.isValid()) {
|
||||
WorldChunk worldChunkComponent = world.getChunkIfLoaded(chunkIndex);
|
||||
if (worldChunkComponent != null) {
|
||||
Ref<ChunkStore> chunkRef = world.getChunkStore().getChunkReference(chunkIndex);
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkReference, ChunkColumn.getComponentType());
|
||||
ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkRef, ChunkColumn.getComponentType());
|
||||
if (chunkColumnComponent != null) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(coopPosition.y));
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkReference, BlockComponentChunk.getComponentType());
|
||||
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
if (blockComponentChunk != null) {
|
||||
int blockIndexColumn = ChunkUtil.indexBlockInColumn(coopPosition.x, coopPosition.y, coopPosition.z);
|
||||
Ref<ChunkStore> coopEntityReference = blockComponentChunk.getEntityReference(blockIndexColumn);
|
||||
@@ -151,11 +171,17 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class CoopResidentTicking extends EntityTickingSystem<EntityStore> {
|
||||
private static final ComponentType<EntityStore, CoopResidentComponent> componentType = 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 componentType;
|
||||
return this.coopResidentComponentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,32 +227,47 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class OnCoopAdded extends RefSystem<ChunkStore> {
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), CoopBlock.getComponentType());
|
||||
@Nonnull
|
||||
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 coopBlock = commandBuffer.getComponent(ref, CoopBlock.getComponentType());
|
||||
if (coopBlock != null) {
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType());
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, this.coopBlockComponentType);
|
||||
|
||||
assert info != null;
|
||||
assert coopBlockComponent != null;
|
||||
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
|
||||
|
||||
assert blockChunk != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
BlockSection blockSection = blockChunk.getSectionAtBlockY(y);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), coopBlock.getNextScheduledTick(worldTimeResource));
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
|
||||
int x = ChunkUtil.xFromBlockInColumn(blockStateInfoComponent.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(blockStateInfoComponent.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(blockStateInfoComponent.getIndex());
|
||||
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
|
||||
if (chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), coopBlockComponent.getNextScheduledTick(worldTimeResource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,147 +276,188 @@ public class FarmingSystems {
|
||||
@Nonnull Ref<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||
) {
|
||||
if (reason != RemoveReason.UNLOAD) {
|
||||
CoopBlock coop = commandBuffer.getComponent(ref, CoopBlock.getComponentType());
|
||||
if (coop != null) {
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, this.coopBlockComponentType);
|
||||
|
||||
assert info != null;
|
||||
assert coopBlockComponent != null;
|
||||
|
||||
Store<EntityStore> entityStore = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
|
||||
|
||||
assert blockChunk != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
ChunkColumn column = commandBuffer.getComponent(info.getChunkRef(), ChunkColumn.getComponentType());
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(index);
|
||||
int y = ChunkUtil.yFromBlockInColumn(index);
|
||||
int z = ChunkUtil.zFromBlockInColumn(index);
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(blockStateInfoComponent.getChunkRef(), BlockChunk.getComponentType());
|
||||
|
||||
assert column != null;
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
Ref<ChunkStore> sectionRef = column.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
ChunkColumn chunkColumnComponent = commandBuffer.getComponent(blockStateInfoComponent.getChunkRef(), ChunkColumn.getComponentType());
|
||||
|
||||
assert sectionRef != null;
|
||||
assert chunkColumnComponent != null;
|
||||
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
|
||||
assert blockSection != null;
|
||||
assert sectionRef != null;
|
||||
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert chunkSection != null;
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getZ(), z);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
WorldTimeResource worldTimeResource = world.getEntityStore().getStore().getResource(WorldTimeResource.getResourceType());
|
||||
coop.handleBlockBroken(world, worldTimeResource, entityStore, worldX, worldY, worldZ);
|
||||
}
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
|
||||
assert chunkSectionComponent != null;
|
||||
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
|
||||
coopBlockComponent.handleBlockBroken(world, worldTimeResource, entityStore, worldX, worldY, worldZ);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return QUERY;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnFarmBlockAdded extends RefSystem<ChunkStore> {
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), FarmingBlock.getComponentType());
|
||||
@Nonnull
|
||||
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 farmingBlock = commandBuffer.getComponent(ref, FarmingBlock.getComponentType());
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(ref, this.farmingBlockComponentType);
|
||||
|
||||
assert farmingBlock != null;
|
||||
assert farmingBlockComponent != null;
|
||||
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
|
||||
|
||||
assert info != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
if (farmingBlock.getLastTickGameTime() == null) {
|
||||
int blockId = blockChunk.getBlock(
|
||||
ChunkUtil.xFromBlockInColumn(info.getIndex()), ChunkUtil.yFromBlockInColumn(info.getIndex()), ChunkUtil.zFromBlockInColumn(info.getIndex())
|
||||
);
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockType.getFarming() == null) {
|
||||
return;
|
||||
}
|
||||
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
|
||||
if (chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
|
||||
farmingBlock.setCurrentStageSet(blockType.getFarming().getStartingStageSet());
|
||||
farmingBlock.setLastTickGameTime(
|
||||
store.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()).getGameTime()
|
||||
);
|
||||
blockChunk.markNeedsSaving();
|
||||
if (blockType.getFarming().getStages() != null) {
|
||||
FarmingStageData[] stages = blockType.getFarming().getStages().get(blockType.getFarming().getStartingStageSet());
|
||||
if (stages != null && stages.length > 0) {
|
||||
boolean found = false;
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
for (int i = 0; i < stages.length; i++) {
|
||||
FarmingStageData stage = stages[i];
|
||||
switch (stage) {
|
||||
case BlockTypeFarmingStageData data:
|
||||
if (data.getBlock().equals(blockType.getId())) {
|
||||
farmingBlock.setGrowthProgress(i);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case BlockStateFarmingStageData datax:
|
||||
BlockType stateBlockType = blockType.getBlockForState(datax.getState());
|
||||
if (stateBlockType != null && stateBlockType.getId().equals(blockType.getId())) {
|
||||
farmingBlock.setGrowthProgress(i);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
World world = store.getExternalData().getWorld();
|
||||
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
|
||||
if (farmingBlockComponent.getLastTickGameTime() == null) {
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int blockId = blockChunkComponent.getBlock(
|
||||
ChunkUtil.xFromBlockInColumn(index), ChunkUtil.yFromBlockInColumn(index), ChunkUtil.zFromBlockInColumn(index)
|
||||
);
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FarmingData blockTypeFarming = blockType.getFarming();
|
||||
if (blockTypeFarming == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String startingStageSet = blockTypeFarming.getStartingStageSet();
|
||||
farmingBlockComponent.setCurrentStageSet(startingStageSet);
|
||||
farmingBlockComponent.setLastTickGameTime(worldTimeResource.getGameTime());
|
||||
blockChunkComponent.markNeedsSaving();
|
||||
Map<String, FarmingStageData[]> farmingStages = blockTypeFarming.getStages();
|
||||
if (farmingStages != null) {
|
||||
FarmingStageData[] stages = farmingStages.get(startingStageSet);
|
||||
if (stages != null && stages.length > 0) {
|
||||
boolean found = false;
|
||||
|
||||
for (int i = 0; i < stages.length; i++) {
|
||||
FarmingStageData stage = stages[i];
|
||||
switch (stage) {
|
||||
case BlockTypeFarmingStageData data:
|
||||
if (data.getBlock().equals(blockType.getId())) {
|
||||
farmingBlockComponent.setGrowthProgress(i);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case BlockStateFarmingStageData datax:
|
||||
BlockType stateBlockType = blockType.getBlockForState(datax.getState());
|
||||
if (stateBlockType != null && stateBlockType.getId().equals(blockType.getId())) {
|
||||
farmingBlockComponent.setGrowthProgress(i);
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
Ref<ChunkStore> sectionRef = commandBuffer.getComponent(info.getChunkRef(), ChunkColumn.getComponentType())
|
||||
.getSection(ChunkUtil.chunkCoordinate(ChunkUtil.yFromBlockInColumn(info.getIndex())));
|
||||
stages[0]
|
||||
.apply(
|
||||
commandBuffer,
|
||||
sectionRef,
|
||||
ref,
|
||||
ChunkUtil.xFromBlockInColumn(info.getIndex()),
|
||||
ChunkUtil.yFromBlockInColumn(info.getIndex()),
|
||||
ChunkUtil.zFromBlockInColumn(info.getIndex()),
|
||||
null
|
||||
);
|
||||
if (!found) {
|
||||
ChunkColumn chunkColumnComponent = commandBuffer.getComponent(chunkRef, ChunkColumn.getComponentType());
|
||||
|
||||
assert chunkColumnComponent != null;
|
||||
|
||||
int chunkCoordinate = ChunkUtil.chunkCoordinate(ChunkUtil.yFromBlockInColumn(index));
|
||||
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(chunkCoordinate);
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
stages[0]
|
||||
.apply(
|
||||
commandBuffer,
|
||||
sectionRef,
|
||||
ref,
|
||||
ChunkUtil.xFromBlockInColumn(index),
|
||||
ChunkUtil.yFromBlockInColumn(index),
|
||||
ChunkUtil.zFromBlockInColumn(index),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (farmingBlockComponent.getLastTickGameTime() == null) {
|
||||
farmingBlockComponent.setLastTickGameTime(worldTimeResource.getGameTime());
|
||||
blockChunkComponent.markNeedsSaving();
|
||||
}
|
||||
|
||||
int indexx = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(indexx);
|
||||
int y = ChunkUtil.yFromBlockInColumn(indexx);
|
||||
int z = ChunkUtil.zFromBlockInColumn(indexx);
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
|
||||
assert blockComponentChunk != null;
|
||||
|
||||
ChunkColumn chunkColumnComponentx = commandBuffer.getComponent(chunkRef, ChunkColumn.getComponentType());
|
||||
|
||||
assert chunkColumnComponentx != null;
|
||||
|
||||
Ref<ChunkStore> section = chunkColumnComponentx.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
if (section != null) {
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(section, BlockSection.getComponentType());
|
||||
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
FarmingUtil.tickFarming(commandBuffer, blockChunkComponent, blockSectionComponent, section, ref, farmingBlockComponent, x, y, z, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (farmingBlock.getLastTickGameTime() == null) {
|
||||
farmingBlock.setLastTickGameTime(
|
||||
store.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()).getGameTime()
|
||||
);
|
||||
blockChunk.markNeedsSaving();
|
||||
}
|
||||
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(info.getChunkRef(), BlockComponentChunk.getComponentType());
|
||||
|
||||
assert blockComponentChunk != null;
|
||||
|
||||
ChunkColumn column = commandBuffer.getComponent(info.getChunkRef(), ChunkColumn.getComponentType());
|
||||
|
||||
assert column != null;
|
||||
|
||||
Ref<ChunkStore> section = column.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
BlockSection blockSection = commandBuffer.getComponent(section, BlockSection.getComponentType());
|
||||
FarmingUtil.tickFarming(commandBuffer, blockChunk, blockSection, section, ref, farmingBlock, x, y, z, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -383,51 +466,67 @@ public class FarmingSystems {
|
||||
) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return QUERY;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnSoilAdded extends RefSystem<ChunkStore> {
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), TilledSoilBlock.getComponentType());
|
||||
@Nonnull
|
||||
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 soil = commandBuffer.getComponent(ref, TilledSoilBlock.getComponentType());
|
||||
TilledSoilBlock soilComponent = commandBuffer.getComponent(ref, this.tilledSoilBlockComponentType);
|
||||
|
||||
assert soil != null;
|
||||
assert soilComponent != null;
|
||||
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
|
||||
|
||||
assert info != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
if (!soil.isPlanted()) {
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
|
||||
if (chunkRef.isValid()) {
|
||||
if (!soilComponent.isPlanted()) {
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(index);
|
||||
int y = ChunkUtil.yFromBlockInColumn(index);
|
||||
int z = ChunkUtil.zFromBlockInColumn(index);
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
|
||||
assert info.getChunkRef() != null;
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
|
||||
Instant decayTime = soilComponent.getDecayTime();
|
||||
if (decayTime == null) {
|
||||
int blockId = blockSection.get(x, y, z);
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
FarmingSystems.updateSoilDecayTime(commandBuffer, soilComponent, blockType);
|
||||
}
|
||||
|
||||
assert blockChunk != null;
|
||||
if (decayTime == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockSection blockSection = blockChunk.getSectionAtBlockY(y);
|
||||
Instant decayTime = soil.getDecayTime();
|
||||
if (decayTime == null) {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockSection.get(x, y, z));
|
||||
FarmingSystems.updateSoilDecayTime(commandBuffer, soil, blockType);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
|
||||
}
|
||||
|
||||
if (decayTime == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,15 +536,41 @@ public class FarmingSystems {
|
||||
) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return QUERY;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Ticking extends EntityTickingSystem<ChunkStore> {
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType());
|
||||
@Nonnull
|
||||
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(
|
||||
@@ -455,44 +580,50 @@ public class FarmingSystems {
|
||||
@Nonnull Store<ChunkStore> store,
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||
) {
|
||||
BlockSection blocks = archetypeChunk.getComponent(index, BlockSection.getComponentType());
|
||||
BlockSection blockSectionComponent = archetypeChunk.getComponent(index, this.blockSectionComponentType);
|
||||
|
||||
assert blocks != null;
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
if (blocks.getTickingBlocksCountCopy() != 0) {
|
||||
ChunkSection section = archetypeChunk.getComponent(index, ChunkSection.getComponentType());
|
||||
if (blockSectionComponent.getTickingBlocksCountCopy() != 0) {
|
||||
ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, this.chunkSectionComponentType);
|
||||
|
||||
assert section != null;
|
||||
assert chunkSectionComponent != null;
|
||||
|
||||
if (section.getChunkColumnReference() != null && section.getChunkColumnReference().isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(section.getChunkColumnReference(), BlockComponentChunk.getComponentType());
|
||||
Ref<ChunkStore> chunkColumnRef = chunkSectionComponent.getChunkColumnReference();
|
||||
if (chunkColumnRef != null && chunkColumnRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkColumnRef, BlockComponentChunk.getComponentType());
|
||||
|
||||
assert blockComponentChunk != null;
|
||||
|
||||
Ref<ChunkStore> ref = archetypeChunk.getReferenceTo(index);
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(section.getChunkColumnReference(), BlockChunk.getComponentType());
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(chunkColumnRef, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunk != null;
|
||||
|
||||
blocks.forEachTicking(
|
||||
blockComponentChunk, commandBuffer, section.getY(), (blockComponentChunk1, commandBuffer1, localX, localY, localZ, blockId) -> {
|
||||
blockSectionComponent.forEachTicking(
|
||||
blockComponentChunk,
|
||||
commandBuffer,
|
||||
chunkSectionComponent.getY(),
|
||||
(blockComponentChunk1, commandBuffer1, localX, localY, localZ, blockId) -> {
|
||||
Ref<ChunkStore> blockRef = blockComponentChunk1.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ));
|
||||
if (blockRef == null) {
|
||||
return BlockTickStrategy.IGNORED;
|
||||
} else {
|
||||
FarmingBlock farming = commandBuffer1.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farming != null) {
|
||||
FarmingUtil.tickFarming(commandBuffer1, blockChunk, blocks, ref, blockRef, farming, localX, localY, localZ, false);
|
||||
FarmingBlock farmingBlockComp = commandBuffer1.getComponent(blockRef, this.farmingBlockComponentType);
|
||||
if (farmingBlockComp != null) {
|
||||
FarmingUtil.tickFarming(
|
||||
commandBuffer1, blockChunk, blockSectionComponent, ref, blockRef, farmingBlockComp, localX, localY, localZ, false
|
||||
);
|
||||
return BlockTickStrategy.SLEEP;
|
||||
} else {
|
||||
TilledSoilBlock soil = commandBuffer1.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null) {
|
||||
tickSoil(commandBuffer1, blockComponentChunk1, blockRef, soil);
|
||||
TilledSoilBlock tilledSoilBlockComp = commandBuffer1.getComponent(blockRef, this.tilledSoilBlockComponentType);
|
||||
if (tilledSoilBlockComp != null) {
|
||||
tickSoil(commandBuffer1, blockRef, tilledSoilBlockComp);
|
||||
return BlockTickStrategy.SLEEP;
|
||||
} else {
|
||||
CoopBlock coop = commandBuffer1.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coop != null) {
|
||||
tickCoop(commandBuffer1, blockComponentChunk1, blockRef, coop);
|
||||
CoopBlock coopBlockComp = commandBuffer1.getComponent(blockRef, this.coopBlockComponentType);
|
||||
if (coopBlockComp != null) {
|
||||
tickCoop(commandBuffer1, blockRef, coopBlockComp);
|
||||
return BlockTickStrategy.SLEEP;
|
||||
} else {
|
||||
return BlockTickStrategy.IGNORED;
|
||||
@@ -506,122 +637,128 @@ public class FarmingSystems {
|
||||
}
|
||||
}
|
||||
|
||||
private static void tickSoil(
|
||||
CommandBuffer<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, Ref<ChunkStore> blockRef, TilledSoilBlock soilBlock
|
||||
) {
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
private static void tickSoil(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> blockRef, @Nonnull TilledSoilBlock soilBlock) {
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
assert info != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(index);
|
||||
int y = ChunkUtil.yFromBlockInColumn(index);
|
||||
int z = ChunkUtil.zFromBlockInColumn(index);
|
||||
if (y < 320) {
|
||||
assert info.getChunkRef() != null;
|
||||
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunk != null;
|
||||
|
||||
BlockSection blockSection = blockChunk.getSectionAtBlockY(y);
|
||||
boolean hasCrop = FarmingSystems.hasCropAbove(blockChunk, x, y, z);
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockSection.get(x, y, z));
|
||||
Instant currentTime = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType())
|
||||
.getGameTime();
|
||||
Instant decayTime = soilBlock.getDecayTime();
|
||||
if (soilBlock.isPlanted() && !hasCrop) {
|
||||
if (!FarmingSystems.updateSoilDecayTime(commandBuffer, soilBlock, blockType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (decayTime != null) {
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
|
||||
}
|
||||
} else if (!soilBlock.isPlanted() && !hasCrop) {
|
||||
if (decayTime == null || !decayTime.isAfter(currentTime)) {
|
||||
assert info.getChunkRef() != null;
|
||||
|
||||
if (blockType != null && blockType.getFarming() != null && blockType.getFarming().getSoilConfig() != null) {
|
||||
FarmingData.SoilConfig soilConfig = blockType.getFarming().getSoilConfig();
|
||||
String targetBlock = soilConfig.getTargetBlock();
|
||||
if (targetBlock == null) {
|
||||
return;
|
||||
} else {
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
if (targetBlockId == Integer.MIN_VALUE) {
|
||||
return;
|
||||
} else {
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
int rotation = blockSection.getRotationIndex(x, y, z);
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(info.getChunkRef(), WorldChunk.getComponentType());
|
||||
commandBuffer.run(_store -> worldChunk.setBlock(x, y, z, targetBlockId, targetBlockType, rotation, 0, 0));
|
||||
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
|
||||
if (chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
|
||||
boolean hasCrop = FarmingSystems.hasCropAbove(blockChunkComponent, x, y, z);
|
||||
int blockId = blockSection.get(x, y, z);
|
||||
BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockTypeAsset != null) {
|
||||
Instant currentTime = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType())
|
||||
.getGameTime();
|
||||
Instant decayTime = soilBlock.getDecayTime();
|
||||
if (soilBlock.isPlanted() && !hasCrop) {
|
||||
if (!FarmingSystems.updateSoilDecayTime(commandBuffer, soilBlock, blockTypeAsset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (decayTime != null) {
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
|
||||
}
|
||||
} else if (!soilBlock.isPlanted() && !hasCrop) {
|
||||
if (decayTime == null || !decayTime.isAfter(currentTime)) {
|
||||
if (blockTypeAsset.getFarming() != null && blockTypeAsset.getFarming().getSoilConfig() != null) {
|
||||
FarmingData.SoilConfig soilConfig = blockTypeAsset.getFarming().getSoilConfig();
|
||||
String targetBlock = soilConfig.getTargetBlock();
|
||||
if (targetBlock == null) {
|
||||
return;
|
||||
} else {
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
if (targetBlockId == Integer.MIN_VALUE) {
|
||||
return;
|
||||
} else {
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
int rotationIndex = blockSection.getRotationIndex(x, y, z);
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
commandBuffer.run(_store -> worldChunkComponent.setBlock(x, y, z, targetBlockId, targetBlockType, rotationIndex, 0, 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (hasCrop) {
|
||||
soilBlock.setDecayTime(null);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
|
||||
String targetBlock = soilBlock.computeBlockType(currentTime, blockTypeAsset);
|
||||
if (targetBlock != null && !targetBlock.equals(blockTypeAsset.getId())) {
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
int rotationIndex = blockSection.getRotationIndex(x, y, z);
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
commandBuffer.run(_store -> worldChunkComponent.setBlock(x, y, z, targetBlockId, targetBlockType, rotationIndex, 0, 2));
|
||||
}
|
||||
|
||||
soilBlock.setPlanted(hasCrop);
|
||||
}
|
||||
}
|
||||
} else if (hasCrop) {
|
||||
soilBlock.setDecayTime(null);
|
||||
}
|
||||
|
||||
String targetBlock = soilBlock.computeBlockType(currentTime, blockType);
|
||||
if (targetBlock != null && !targetBlock.equals(blockType.getId())) {
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(info.getChunkRef(), WorldChunk.getComponentType());
|
||||
int rotation = blockSection.getRotationIndex(x, y, z);
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
commandBuffer.run(_store -> worldChunk.setBlock(x, y, z, targetBlockId, targetBlockType, rotation, 0, 2));
|
||||
}
|
||||
|
||||
soilBlock.setPlanted(hasCrop);
|
||||
}
|
||||
}
|
||||
|
||||
private static void tickCoop(
|
||||
CommandBuffer<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, Ref<ChunkStore> blockRef, CoopBlock coopBlock
|
||||
) {
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
private static void tickCoop(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> blockRef, @Nonnull CoopBlock coopBlock) {
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
assert info != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType());
|
||||
FarmingCoopAsset coopAsset = coopBlock.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(index);
|
||||
int y = ChunkUtil.yFromBlockInColumn(index);
|
||||
int z = ChunkUtil.zFromBlockInColumn(index);
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(blockStateInfoComponent.getChunkRef(), BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunk != null;
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
ChunkColumn column = commandBuffer.getComponent(info.getChunkRef(), ChunkColumn.getComponentType());
|
||||
ChunkColumn chunkColumnComponent = commandBuffer.getComponent(blockStateInfoComponent.getChunkRef(), ChunkColumn.getComponentType());
|
||||
|
||||
assert column != null;
|
||||
assert chunkColumnComponent != null;
|
||||
|
||||
Ref<ChunkStore> sectionRef = column.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
|
||||
assert sectionRef != null;
|
||||
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert blockSection != null;
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
|
||||
assert chunkSection != null;
|
||||
assert chunkSectionComponent != null;
|
||||
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getZ(), z);
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(worldX, worldZ));
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(worldX, worldZ);
|
||||
WorldChunk chunk = world.getChunkIfInMemory(chunkIndex);
|
||||
double blockRotation = chunk.getRotation(worldX, worldY, worldZ).yaw().getRadians();
|
||||
Vector3d spawnOffset = new Vector3d().assign(coopAsset.getResidentSpawnOffset()).rotateY((float)blockRotation);
|
||||
Vector3i coopLocation = new Vector3i(worldX, worldY, worldZ);
|
||||
@@ -652,15 +789,15 @@ public class FarmingSystems {
|
||||
|
||||
Instant nextTickInstant = coopBlock.getNextScheduledTick(worldTimeResource);
|
||||
if (nextTickInstant != null) {
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), nextTickInstant);
|
||||
blockSectionComponent.scheduleTick(ChunkUtil.indexBlock(x, y, z), nextTickInstant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public Query<ChunkStore> getQuery() {
|
||||
return QUERY;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ 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.model.config.ModelAsset;
|
||||
import com.hypixel.hytale.server.core.entity.ItemUtils;
|
||||
import com.hypixel.hytale.server.core.inventory.ItemStack;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.BlockHarvestUtils;
|
||||
@@ -43,19 +44,20 @@ public class FarmingUtil {
|
||||
private static final int BETWEEN_RANDOM = 10;
|
||||
|
||||
public static void tickFarming(
|
||||
CommandBuffer<ChunkStore> commandBuffer,
|
||||
BlockChunk blockChunk,
|
||||
BlockSection blockSection,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
FarmingBlock farmingBlock,
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull BlockChunk blockChunk,
|
||||
@Nonnull BlockSection blockSection,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
@Nonnull FarmingBlock farmingBlock,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
WorldTimeResource worldTimeResource = world.getEntityStore().getStore().getResource(WorldTimeResource.getResourceType());
|
||||
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
|
||||
Instant currentTime = worldTimeResource.getGameTime();
|
||||
BlockType blockType = farmingBlock.getPreviousBlockType() != null
|
||||
? BlockType.getAssetMap().getAsset(farmingBlock.getPreviousBlockType())
|
||||
@@ -90,77 +92,79 @@ public class FarmingUtil {
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
} else {
|
||||
long remainingTimeSeconds = currentTime.getEpochSecond() - farmingBlock.getLastTickGameTime().getEpochSecond();
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent != null) {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
|
||||
while (currentStage < stages.length) {
|
||||
FarmingStageData stage = stages[currentStage];
|
||||
if (stage.shouldStop(commandBuffer, sectionRef, blockRef, x, y, z)) {
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGrowthProgress(stages.length);
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
|
||||
Rangef range = stage.getDuration();
|
||||
if (range == null) {
|
||||
blockChunk.markNeedsSaving();
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
|
||||
double rand = HashUtil.random(farmingBlock.getGeneration(), worldX, worldY, worldZ);
|
||||
double baseDuration = range.min + (range.max - range.min) * rand;
|
||||
long remainingDurationSeconds = Math.round(baseDuration * (1.0 - currentProgress % 1.0));
|
||||
double growthMultiplier = 1.0;
|
||||
if (farmingConfig.getGrowthModifiers() != null) {
|
||||
for (String modifierName : farmingConfig.getGrowthModifiers()) {
|
||||
GrowthModifierAsset modifier = GrowthModifierAsset.getAssetMap().getAsset(modifierName);
|
||||
if (modifier != null) {
|
||||
growthMultiplier *= modifier.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainingDurationSeconds = Math.round(remainingDurationSeconds / growthMultiplier);
|
||||
if (remainingTimeSeconds < remainingDurationSeconds) {
|
||||
currentProgress += (float)(remainingTimeSeconds / (baseDuration / growthMultiplier));
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
long nextGrowthInNanos = (remainingDurationSeconds - remainingTimeSeconds) * 1000000000L;
|
||||
long randCap = (long)(
|
||||
(15.0 + 10.0 * HashUtil.random(farmingBlock.getGeneration() ^ 3405692655L, worldX, worldY, worldZ))
|
||||
* world.getTps()
|
||||
* WorldTimeResource.getSecondsPerTick(world)
|
||||
* 1.0E9
|
||||
);
|
||||
long cappedNextGrowthInNanos = Math.min(nextGrowthInNanos, randCap);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), currentTime.plusNanos(cappedNextGrowthInNanos));
|
||||
break;
|
||||
}
|
||||
|
||||
remainingTimeSeconds -= remainingDurationSeconds;
|
||||
currentProgress = ++currentStage;
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGeneration(farmingBlock.getGeneration() + 1);
|
||||
if (currentStage >= stages.length) {
|
||||
if (stages[currentStage - 1].implementsShouldStop()) {
|
||||
currentStage = stages.length - 1;
|
||||
farmingBlock.setGrowthProgress(currentStage);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage]);
|
||||
} else {
|
||||
while (currentStage < stages.length) {
|
||||
FarmingStageData stage = stages[currentStage];
|
||||
if (stage.shouldStop(commandBuffer, sectionRef, blockRef, x, y, z)) {
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGrowthProgress(stages.length);
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
farmingBlock.setExecutions(0);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
farmingBlock.setLastTickGameTime(currentTime);
|
||||
Rangef range = stage.getDuration();
|
||||
if (range == null) {
|
||||
blockChunk.markNeedsSaving();
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
|
||||
double rand = HashUtil.random(farmingBlock.getGeneration(), worldX, worldY, worldZ);
|
||||
double baseDuration = range.min + (range.max - range.min) * rand;
|
||||
long remainingDurationSeconds = Math.round(baseDuration * (1.0 - currentProgress % 1.0));
|
||||
double growthMultiplier = 1.0;
|
||||
if (farmingConfig.getGrowthModifiers() != null) {
|
||||
for (String modifierName : farmingConfig.getGrowthModifiers()) {
|
||||
GrowthModifierAsset modifierAsset = GrowthModifierAsset.getAssetMap().getAsset(modifierName);
|
||||
if (modifierAsset != null) {
|
||||
growthMultiplier *= modifierAsset.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainingDurationSeconds = Math.round(remainingDurationSeconds / growthMultiplier);
|
||||
if (remainingTimeSeconds < remainingDurationSeconds) {
|
||||
currentProgress += (float)(remainingTimeSeconds / (baseDuration / growthMultiplier));
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
long nextGrowthInNanos = (remainingDurationSeconds - remainingTimeSeconds) * 1000000000L;
|
||||
long randCap = (long)(
|
||||
(15.0 + 10.0 * HashUtil.random(farmingBlock.getGeneration() ^ 3405692655L, worldX, worldY, worldZ))
|
||||
* world.getTps()
|
||||
* WorldTimeResource.getSecondsPerTick(world)
|
||||
* 1.0E9
|
||||
);
|
||||
long cappedNextGrowthInNanos = Math.min(nextGrowthInNanos, randCap);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), currentTime.plusNanos(cappedNextGrowthInNanos));
|
||||
break;
|
||||
}
|
||||
|
||||
remainingTimeSeconds -= remainingDurationSeconds;
|
||||
currentProgress = ++currentStage;
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGeneration(farmingBlock.getGeneration() + 1);
|
||||
if (currentStage >= stages.length) {
|
||||
if (stages[currentStage - 1].implementsShouldStop()) {
|
||||
currentStage = stages.length - 1;
|
||||
farmingBlock.setGrowthProgress(currentStage);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage]);
|
||||
} else {
|
||||
farmingBlock.setGrowthProgress(stages.length);
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
}
|
||||
} else {
|
||||
farmingBlock.setExecutions(0);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
farmingBlock.setLastTickGameTime(currentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,22 +172,22 @@ public class FarmingUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void harvest(
|
||||
public static boolean harvest(
|
||||
@Nonnull World world,
|
||||
@Nonnull ComponentAccessor<EntityStore> store,
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull BlockType blockType,
|
||||
int rotationIndex,
|
||||
@Nonnull Vector3i blockPosition
|
||||
) {
|
||||
if (world.getGameplayConfig().getWorldConfig().isBlockGatheringAllowed()) {
|
||||
harvest0(store, ref, blockType, rotationIndex, blockPosition);
|
||||
}
|
||||
return world.getGameplayConfig().getWorldConfig().isBlockGatheringAllowed()
|
||||
? harvest0(componentAccessor, ref, blockType, rotationIndex, blockPosition)
|
||||
: false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CapturedNPCMetadata generateCapturedNPCMetadata(
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor, @Nonnull Ref<EntityStore> entityRef, int roleIndex
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor, @Nonnull Ref<EntityStore> entityRef, String npcNameKey
|
||||
) {
|
||||
PersistentModel persistentModel = componentAccessor.getComponent(entityRef, PersistentModel.getComponentType());
|
||||
if (persistentModel == null) {
|
||||
@@ -195,7 +199,7 @@ public class FarmingUtil {
|
||||
meta.setIconPath(modelAsset.getIcon());
|
||||
}
|
||||
|
||||
meta.setRoleIndex(roleIndex);
|
||||
meta.setNpcNameKey(npcNameKey);
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
@@ -208,24 +212,19 @@ public class FarmingUtil {
|
||||
@Nonnull Vector3i blockPosition
|
||||
) {
|
||||
FarmingData farmingConfig = blockType.getFarming();
|
||||
boolean isFarmable = true;
|
||||
if (farmingConfig == null || farmingConfig.getStages() == null) {
|
||||
return false;
|
||||
} else if (blockType.getGathering().getHarvest() == null) {
|
||||
isFarmable = false;
|
||||
}
|
||||
|
||||
if (blockType.getGathering().getHarvest() == null) {
|
||||
return false;
|
||||
} else {
|
||||
World world = store.getExternalData().getWorld();
|
||||
Vector3d centerPosition = new Vector3d();
|
||||
blockType.getBlockCenter(rotationIndex, centerPosition);
|
||||
centerPosition.add(blockPosition);
|
||||
if (farmingConfig.getStageSetAfterHarvest() == null) {
|
||||
giveDrops(store, ref, centerPosition, blockType);
|
||||
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z));
|
||||
if (chunk != null) {
|
||||
chunk.breakBlock(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if (isFarmable && farmingConfig.getStageSetAfterHarvest() != null) {
|
||||
giveDrops(store, ref, centerPosition, blockType);
|
||||
Map<String, FarmingStageData[]> stageSets = farmingConfig.getStages();
|
||||
FarmingStageData[] stages = stageSets.get(farmingConfig.getStartingStageSet());
|
||||
@@ -285,7 +284,8 @@ public class FarmingUtil {
|
||||
} else {
|
||||
BlockSection section = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (section != null) {
|
||||
section.scheduleTick(ChunkUtil.indexBlock(blockPosition.x, blockPosition.y, blockPosition.z), now);
|
||||
int blockIndex = ChunkUtil.indexBlock(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
section.scheduleTick(blockIndex, now);
|
||||
}
|
||||
|
||||
newStages[0].apply(chunkStore, sectionRef, blockRef, blockPosition.x, blockPosition.y, blockPosition.z, previousStage);
|
||||
@@ -302,6 +302,14 @@ public class FarmingUtil {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
giveDrops(store, ref, centerPosition, blockType);
|
||||
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z));
|
||||
if (chunk != null) {
|
||||
chunk.breakBlock(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,6 +320,9 @@ public class FarmingUtil {
|
||||
HarvestingDropType harvest = blockType.getGathering().getHarvest();
|
||||
String itemId = harvest.getItemId();
|
||||
String dropListId = harvest.getDropListId();
|
||||
BlockHarvestUtils.getDrops(blockType, 1, itemId, dropListId).forEach(itemStack -> ItemUtils.interactivelyPickupItem(ref, itemStack, origin, store));
|
||||
|
||||
for (ItemStack itemStack : BlockHarvestUtils.getDrops(blockType, 1, itemId, dropListId)) {
|
||||
ItemUtils.interactivelyPickupItem(ref, itemStack, origin, store);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.ComponentType;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CoopResidentComponent implements Component<EntityStore> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CoopResidentComponent> CODEC = BuilderCodec.builder(CoopResidentComponent.class, CoopResidentComponent::new)
|
||||
.append(new KeyedCodec<>("CoopLocation", Vector3i.CODEC), (comp, ref) -> comp.coopLocation = ref, comp -> comp.coopLocation)
|
||||
.add()
|
||||
@@ -20,6 +22,7 @@ public class CoopResidentComponent implements Component<EntityStore> {
|
||||
)
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private Vector3i coopLocation = new Vector3i();
|
||||
private boolean markedForDespawn;
|
||||
|
||||
@@ -27,10 +30,11 @@ public class CoopResidentComponent implements Component<EntityStore> {
|
||||
return FarmingPlugin.get().getCoopResidentComponentType();
|
||||
}
|
||||
|
||||
public void setCoopLocation(Vector3i coopLocation) {
|
||||
public void setCoopLocation(@Nonnull Vector3i coopLocation) {
|
||||
this.coopLocation = coopLocation;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Vector3i getCoopLocation() {
|
||||
return this.coopLocation;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, FarmingCoopAsset>> {
|
||||
@Nonnull
|
||||
public static final AssetBuilderCodec<String, FarmingCoopAsset> CODEC = AssetBuilderCodec.builder(
|
||||
FarmingCoopAsset.class, FarmingCoopAsset::new, Codec.STRING, (o, v) -> o.id = v, FarmingCoopAsset::getId, (o, data) -> o.data = data, o -> o.data
|
||||
)
|
||||
@@ -87,6 +88,7 @@ public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMa
|
||||
protected int maxResidents;
|
||||
protected Map<String, String> produceDrops = Collections.emptyMap();
|
||||
protected IntRange residentRoamTime;
|
||||
@Nonnull
|
||||
protected Vector3d residentSpawnOffset = new Vector3d();
|
||||
protected String[] acceptedNpcGroupIds;
|
||||
protected int[] acceptedNpcGroupIndexes;
|
||||
@@ -128,6 +130,7 @@ public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMa
|
||||
return this.residentRoamTime;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Vector3d getResidentSpawnOffset() {
|
||||
return this.residentSpawnOffset;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Growth
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class FertilizerGrowthModifierAsset extends GrowthModifierAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<FertilizerGrowthModifierAsset> CODEC = BuilderCodec.builder(
|
||||
FertilizerGrowthModifierAsset.class, FertilizerGrowthModifierAsset::new, ABSTRACT_CODEC
|
||||
)
|
||||
@@ -18,17 +20,37 @@ public class FertilizerGrowthModifierAsset extends GrowthModifierAsset {
|
||||
|
||||
@Override
|
||||
public double getCurrentGrowthMultiplier(
|
||||
CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z, boolean initialTick
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference();
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType());
|
||||
Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z));
|
||||
if (blockRefBelow == null) {
|
||||
return 1.0;
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
|
||||
assert chunkSectionComponent != null;
|
||||
|
||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
if (blockComponentChunk == null) {
|
||||
return 1.0;
|
||||
} else {
|
||||
int chunkIndexBelow = ChunkUtil.indexBlockInColumn(x, y - 1, z);
|
||||
Ref<ChunkStore> blockBelowRef = blockComponentChunk.getEntityReference(chunkIndexBelow);
|
||||
if (blockBelowRef != null && blockBelowRef.isValid()) {
|
||||
TilledSoilBlock belowTilledSoilComponent = commandBuffer.getComponent(blockBelowRef, TilledSoilBlock.getComponentType());
|
||||
return belowTilledSoilComponent != null && belowTilledSoilComponent.isFertilized()
|
||||
? super.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick)
|
||||
: 1.0;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TilledSoilBlock soil = commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType());
|
||||
return soil != null && soil.isFertilized() ? super.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick) : 1.0;
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,15 @@ import com.hypixel.hytale.protocol.Rangef;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;
|
||||
import com.hypixel.hytale.server.core.codec.ProtocolCodecs;
|
||||
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.chunk.section.BlockSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkLightData;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<LightLevelGrowthModifierAsset> CODEC = BuilderCodec.builder(
|
||||
LightLevelGrowthModifierAsset.class, LightLevelGrowthModifierAsset::new, ABSTRACT_CODEC
|
||||
)
|
||||
@@ -57,7 +60,7 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
return isInRange(redRange, red) && isInRange(greenRange, green) && isInRange(blueRange, blue);
|
||||
}
|
||||
|
||||
protected boolean checkSunLight(WorldTimeResource worldTimeResource, byte sky) {
|
||||
protected boolean checkSunLight(@Nonnull WorldTimeResource worldTimeResource, byte sky) {
|
||||
Rangef range = this.sunlight;
|
||||
double sunlightFactor = worldTimeResource.getSunlightFactor();
|
||||
double daylight = sunlightFactor * sky;
|
||||
@@ -70,19 +73,26 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
|
||||
@Override
|
||||
public double getCurrentGrowthMultiplier(
|
||||
CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z, boolean initialTick
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
short lightRaw = blockSection.getGlobalLight().getLightRaw(x, y, z);
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
short lightRaw = blockSectionComponent.getGlobalLight().getLightRaw(x, y, z);
|
||||
byte redLight = ChunkLightData.getLightValue(lightRaw, 0);
|
||||
byte greenLight = ChunkLightData.getLightValue(lightRaw, 1);
|
||||
byte blueLight = ChunkLightData.getLightValue(lightRaw, 2);
|
||||
byte skyLight = ChunkLightData.getLightValue(lightRaw, 3);
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType());
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
EntityStore entityStore = world.getEntityStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getStore().getResource(WorldTimeResource.getResourceType());
|
||||
boolean active = false;
|
||||
boolean onlySunlight = false;
|
||||
if (this.requireBoth) {
|
||||
@@ -117,6 +127,7 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
}
|
||||
|
||||
public static class ArtificialLight {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<LightLevelGrowthModifierAsset.ArtificialLight> CODEC = BuilderCodec.builder(
|
||||
LightLevelGrowthModifierAsset.ArtificialLight.class, LightLevelGrowthModifierAsset.ArtificialLight::new
|
||||
)
|
||||
|
||||
@@ -28,6 +28,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<WaterGrowthModifierAsset> CODEC = BuilderCodec.builder(
|
||||
WaterGrowthModifierAsset.class, WaterGrowthModifierAsset::new, ABSTRACT_CODEC
|
||||
)
|
||||
@@ -84,19 +85,28 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
|
||||
@Override
|
||||
public double getCurrentGrowthMultiplier(
|
||||
CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z, boolean initialTick
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
boolean hasWaterBlock = this.checkIfWaterSource(commandBuffer, sectionRef, blockRef, x, y, z);
|
||||
boolean hasWaterBlock = this.checkIfWaterSource(commandBuffer, sectionRef, x, y, z);
|
||||
boolean isRaining = this.checkIfRaining(commandBuffer, sectionRef, x, y, z);
|
||||
boolean active = hasWaterBlock || isRaining;
|
||||
TilledSoilBlock soil = getSoil(commandBuffer, sectionRef, x, y, z);
|
||||
if (soil != null) {
|
||||
if (soil.hasExternalWater() != active) {
|
||||
soil.setExternalWater(active);
|
||||
commandBuffer.getComponent(sectionRef, BlockSection.getComponentType()).setTicking(x, y, z, true);
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (blockSectionComponent != null) {
|
||||
blockSectionComponent.setTicking(x, y, z, true);
|
||||
}
|
||||
}
|
||||
|
||||
active |= this.isSoilWaterExpiring(
|
||||
active |= isSoilWaterExpiring(
|
||||
commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()), soil
|
||||
);
|
||||
}
|
||||
@@ -105,15 +115,28 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TilledSoilBlock getSoil(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference();
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType());
|
||||
Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z));
|
||||
return blockRefBelow == null ? null : commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType());
|
||||
private static TilledSoilBlock getSoil(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
return null;
|
||||
} else {
|
||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
if (blockComponentChunk == null) {
|
||||
return null;
|
||||
} else {
|
||||
int blockBelowIndex = ChunkUtil.indexBlockInColumn(x, y - 1, z);
|
||||
Ref<ChunkStore> blockBelowRef = blockComponentChunk.getEntityReference(blockBelowIndex);
|
||||
return blockBelowRef == null ? null : commandBuffer.getComponent(blockBelowRef, TilledSoilBlock.getComponentType());
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean checkIfWaterSource(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
protected boolean checkIfWaterSource(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
IntOpenHashSet waterBlocks = this.fluidIds;
|
||||
if (waterBlocks == null) {
|
||||
return false;
|
||||
@@ -122,31 +145,42 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
if (soil == null) {
|
||||
return false;
|
||||
} else {
|
||||
int[] fluids = this.getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z);
|
||||
|
||||
for (int block : fluids) {
|
||||
if (waterBlocks.contains(block)) {
|
||||
return true;
|
||||
int[] fluids = getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z);
|
||||
if (fluids == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (int block : fluids) {
|
||||
if (waterBlocks.contains(block)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getNeighbourFluids(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
return new int[]{
|
||||
this.getFluidAtPos(x - 1, y, z, sectionRef, section, commandBuffer),
|
||||
this.getFluidAtPos(x + 1, y, z, sectionRef, section, commandBuffer),
|
||||
this.getFluidAtPos(x, y, z - 1, sectionRef, section, commandBuffer),
|
||||
this.getFluidAtPos(x, y, z + 1, sectionRef, section, commandBuffer)
|
||||
};
|
||||
@Nullable
|
||||
private static int[] getNeighbourFluids(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
return chunkSectionComponent == null
|
||||
? null
|
||||
: new int[]{
|
||||
getFluidAtPos(x - 1, y, z, sectionRef, chunkSectionComponent, commandBuffer),
|
||||
getFluidAtPos(x + 1, y, z, sectionRef, chunkSectionComponent, commandBuffer),
|
||||
getFluidAtPos(x, y, z - 1, sectionRef, chunkSectionComponent, commandBuffer),
|
||||
getFluidAtPos(x, y, z + 1, sectionRef, chunkSectionComponent, commandBuffer)
|
||||
};
|
||||
}
|
||||
|
||||
private int getFluidAtPos(
|
||||
int posX, int posY, int posZ, Ref<ChunkStore> sectionRef, ChunkSection currentChunkSection, CommandBuffer<ChunkStore> commandBuffer
|
||||
private static int getFluidAtPos(
|
||||
int posX,
|
||||
int posY,
|
||||
int posZ,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull ChunkSection currentChunkSection,
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||
) {
|
||||
Ref<ChunkStore> chunkToUse = sectionRef;
|
||||
int chunkX = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getX(), posX);
|
||||
@@ -156,49 +190,59 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
chunkToUse = commandBuffer.getExternalData().getChunkSectionReference(chunkX, chunkY, chunkZ);
|
||||
}
|
||||
|
||||
return chunkToUse == null ? Integer.MIN_VALUE : commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType()).getFluidId(posX, posY, posZ);
|
||||
}
|
||||
|
||||
protected boolean checkIfRaining(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
if (this.weatherIds == null) {
|
||||
return false;
|
||||
if (chunkToUse == null) {
|
||||
return Integer.MIN_VALUE;
|
||||
} else {
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
Ref<ChunkStore> chunk = section.getChunkColumnReference();
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(chunk, BlockChunk.getComponentType());
|
||||
int cropId = blockChunk.getBlock(x, y, z);
|
||||
Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType());
|
||||
WeatherResource weatherResource = store.getResource(WeatherResource.getResourceType());
|
||||
int environment = blockChunk.getEnvironment(x, y, z);
|
||||
int weatherId;
|
||||
if (weatherResource.getForcedWeatherIndex() != 0) {
|
||||
weatherId = weatherResource.getForcedWeatherIndex();
|
||||
} else {
|
||||
weatherId = weatherResource.getWeatherIndexForEnvironment(environment);
|
||||
}
|
||||
|
||||
if (this.weatherIds.contains(weatherId)) {
|
||||
boolean unobstructed = true;
|
||||
|
||||
for (int searchY = y + 1; searchY < 320; searchY++) {
|
||||
int block = blockChunk.getBlock(x, searchY, z);
|
||||
if (block != 0 && block != cropId) {
|
||||
unobstructed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unobstructed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
FluidSection fluidSectionComponent = commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType());
|
||||
return fluidSectionComponent == null ? Integer.MIN_VALUE : fluidSectionComponent.getFluidId(posX, posY, posZ);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSoilWaterExpiring(WorldTimeResource worldTimeResource, TilledSoilBlock soilBlock) {
|
||||
protected boolean checkIfRaining(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
if (this.weatherIds == null) {
|
||||
return false;
|
||||
} else {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
int blockId = blockChunkComponent.getBlock(x, y, z);
|
||||
Store<EntityStore> entityStore = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
WeatherResource weatherResource = entityStore.getResource(WeatherResource.getResourceType());
|
||||
int environment = blockChunkComponent.getEnvironment(x, y, z);
|
||||
int weatherId;
|
||||
if (weatherResource.getForcedWeatherIndex() != 0) {
|
||||
weatherId = weatherResource.getForcedWeatherIndex();
|
||||
} else {
|
||||
weatherId = weatherResource.getWeatherIndexForEnvironment(environment);
|
||||
}
|
||||
|
||||
if (!this.weatherIds.contains(weatherId)) {
|
||||
return false;
|
||||
} else {
|
||||
boolean unobstructed = true;
|
||||
|
||||
for (int searchY = y + 1; searchY < 320; searchY++) {
|
||||
int block = blockChunkComponent.getBlock(x, searchY, z);
|
||||
if (block != 0 && block != blockId) {
|
||||
unobstructed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return unobstructed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSoilWaterExpiring(@Nonnull WorldTimeResource worldTimeResource, @Nonnull TilledSoilBlock soilBlock) {
|
||||
Instant until = soilBlock.getWateredUntil();
|
||||
if (until == null) {
|
||||
return false;
|
||||
|
||||
@@ -5,17 +5,22 @@ import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.FarmingStageData;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockStateFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
public static BuilderCodec<BlockStateFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BlockStateFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
BlockStateFarmingStageData.class, BlockStateFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(new KeyedCodec<>("State", Codec.STRING), (stage, block) -> stage.state = block, stage -> stage.state)
|
||||
@@ -29,25 +34,49 @@ public class BlockStateFarmingStageData extends FarmingStageData {
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
int origBlockId = worldChunk.getBlock(x, y, z);
|
||||
BlockType origBlockType = BlockType.getAssetMap().getAsset(origBlockId);
|
||||
BlockType blockType = origBlockType.getBlockForState(this.state);
|
||||
if (blockType != null) {
|
||||
int newType = BlockType.getAssetMap().getIndex(blockType.getId());
|
||||
if (origBlockId != newType) {
|
||||
int rotation = worldChunk.getRotationIndex(x, y, z);
|
||||
commandBuffer.getExternalData().getWorld().execute(() -> worldChunk.setBlock(x, y, z, newType, blockType, rotation, 0, 2));
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing chunk section component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
if (worldChunkComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing world chunk component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
int originBlockId = worldChunkComponent.getBlock(x, y, z);
|
||||
BlockType originBlockType = BlockType.getAssetMap().getAsset(originBlockId);
|
||||
if (originBlockType == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing origin block type for block ID '%s' when applying state farming stage at (%d, %d, %d)", String.valueOf(originBlockId), x, y, z);
|
||||
} else {
|
||||
BlockType blockType = originBlockType.getBlockForState(this.state);
|
||||
if (blockType == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing new block type '%s' when applying state farming stage at (%d, %d, %d)", this.state, x, y, z);
|
||||
} else {
|
||||
int newBlockId = BlockType.getAssetMap().getIndex(blockType.getId());
|
||||
if (originBlockId != newBlockId) {
|
||||
int rotationIndex = worldChunkComponent.getRotationIndex(x, y, z);
|
||||
commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.execute(() -> worldChunkComponent.setBlock(x, y, z, newBlockId, blockType, rotationIndex, 0, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,22 @@ import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.FarmingStageData;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockTypeFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
public static BuilderCodec<BlockTypeFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BlockTypeFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
BlockTypeFarmingStageData.class, BlockTypeFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(new KeyedCodec<>("Block", Codec.STRING), (stage, block) -> stage.block = block, stage -> stage.block)
|
||||
@@ -30,21 +35,42 @@ public class BlockTypeFarmingStageData extends FarmingStageData {
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
int blockId = BlockType.getAssetMap().getIndex(this.block);
|
||||
if (blockId != worldChunk.getBlock(x, y, z)) {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
commandBuffer.getExternalData().getWorld().execute(() -> worldChunk.setBlock(x, y, z, blockId, blockType, worldChunk.getRotationIndex(x, y, z), 0, 2));
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing chunk section component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
if (worldChunkComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing world chunk component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
int blockId = BlockType.getAssetMap().getIndex(this.block);
|
||||
if (blockId != worldChunkComponent.getBlock(x, y, z)) {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockType == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Invalid block type '%s' when applying block type farming stage at (%d, %d, %d)", this.block, x, y, z);
|
||||
} else {
|
||||
commandBuffer.getExternalData().getWorld().execute(() -> {
|
||||
int rotationIndex = worldChunkComponent.getRotationIndex(x, y, z);
|
||||
worldChunkComponent.setBlock(x, y, z, blockId, blockType, rotationIndex, 0, 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -13,13 +12,13 @@ import com.hypixel.hytale.common.map.IWeightedElement;
|
||||
import com.hypixel.hytale.common.map.IWeightedMap;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.util.ChunkUtil;
|
||||
import com.hypixel.hytale.math.util.FastRandom;
|
||||
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;
|
||||
@@ -37,20 +36,24 @@ 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;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PrefabFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
public static final float MIN_VOLUME_PREFAB = 125.0F;
|
||||
public static final float MAX_VOLUME_PREFAB = 1000.0F;
|
||||
public static final float MIN_BROKEN_PARTICLE_RATE = 0.25F;
|
||||
public static final float MAX_BROKEN_PARTICLE_RATE = 0.75F;
|
||||
@Nonnull
|
||||
private static final String[] EMPTY_REPLACE_MASK = new String[0];
|
||||
@Nonnull
|
||||
public static BuilderCodec<PrefabFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
public static final BuilderCodec<PrefabFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
PrefabFarmingStageData.class, PrefabFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(
|
||||
@@ -77,12 +80,12 @@ public class PrefabFarmingStageData extends FarmingStageData {
|
||||
double zLength = prefab.getMaxZ() - prefab.getMinZ();
|
||||
double volume = xLength * yLength * zLength;
|
||||
double ratio = -5.7142857E-4F;
|
||||
double rate = (volume - 125.0) * ratio;
|
||||
double rate = (volume - 125.0) * -5.7142857E-4F;
|
||||
return MathUtil.clamp(rate + 0.75, 0.25, 0.75);
|
||||
}
|
||||
|
||||
private static boolean isPrefabBlockIntact(
|
||||
LocalCachedChunkAccessor chunkAccessor,
|
||||
@Nonnull LocalCachedChunkAccessor chunkAccessor,
|
||||
int worldX,
|
||||
int worldY,
|
||||
int worldZ,
|
||||
@@ -91,33 +94,40 @@ public class PrefabFarmingStageData extends FarmingStageData {
|
||||
int blockZ,
|
||||
int blockId,
|
||||
int rotation,
|
||||
PrefabRotation prefabRotation
|
||||
@Nonnull PrefabRotation prefabRotation
|
||||
) {
|
||||
int globalX = prefabRotation.getX(blockX, blockZ) + worldX;
|
||||
int globalY = blockY + worldY;
|
||||
int globalZ = prefabRotation.getZ(blockX, blockZ) + worldZ;
|
||||
BlockType block = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (block.getMaterial() == BlockMaterial.Empty) {
|
||||
return true;
|
||||
} else {
|
||||
WorldChunk chunk = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(globalX, globalZ));
|
||||
if (chunk == null) {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockType != null && blockType.getMaterial() != BlockMaterial.Empty) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(globalX, globalZ);
|
||||
WorldChunk worldChunkComponent = chunkAccessor.getNonTickingChunk(chunkIndex);
|
||||
if (worldChunkComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
int worldBlockId = chunk.getBlock(globalX, globalY, globalZ);
|
||||
int worldBlockId = worldChunkComponent.getBlock(globalX, globalY, globalZ);
|
||||
if (worldBlockId != blockId) {
|
||||
return false;
|
||||
} else {
|
||||
int expectedRotation = prefabRotation.getRotation(rotation);
|
||||
int worldRotation = chunk.getRotationIndex(globalX, globalY, globalZ);
|
||||
int worldRotation = worldChunkComponent.getRotationIndex(globalX, globalY, globalZ);
|
||||
return worldRotation == expectedRotation;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPrefabIntact(
|
||||
IPrefabBuffer prefabBuffer, LocalCachedChunkAccessor chunkAccessor, int worldX, int worldY, int worldZ, PrefabRotation prefabRotation, FastRandom random
|
||||
@Nonnull IPrefabBuffer prefabBuffer,
|
||||
@Nonnull LocalCachedChunkAccessor chunkAccessor,
|
||||
int worldX,
|
||||
int worldY,
|
||||
int worldZ,
|
||||
@Nonnull PrefabRotation prefabRotation,
|
||||
@Nonnull FastRandom random
|
||||
) {
|
||||
return prefabBuffer.forEachRaw(
|
||||
IPrefabBuffer.iterateAllColumns(),
|
||||
@@ -136,144 +146,210 @@ public class PrefabFarmingStageData extends FarmingStageData {
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
IPrefabBuffer prefabBuffer = this.getCachedPrefab(x, y, z, farming.getGeneration());
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
int randomRotation = HashUtil.randomInt(x, y, z, Rotation.VALUES.length);
|
||||
RotationTuple yaw = RotationTuple.of(Rotation.VALUES[randomRotation], Rotation.None);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
if (farming.getPreviousBlockType() == null) {
|
||||
farming.setPreviousBlockType(BlockType.getAssetMap().getAsset(blockSection.get(x, y, z)).getId());
|
||||
}
|
||||
|
||||
double xLength = prefabBuffer.getMaxX() - prefabBuffer.getMinX();
|
||||
double zLength = prefabBuffer.getMaxZ() - prefabBuffer.getMinZ();
|
||||
int prefabRadius = (int)MathUtil.fastFloor(0.5 * Math.sqrt(xLength * xLength + zLength * zLength));
|
||||
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, x, z, prefabRadius);
|
||||
FastRandom random = new FastRandom();
|
||||
PrefabRotation prefabRotation = PrefabRotation.fromRotation(yaw.yaw());
|
||||
BlockTypeAssetMap<String, BlockType> blockTypeMap = BlockType.getAssetMap();
|
||||
if (previousStage instanceof PrefabFarmingStageData oldPrefab) {
|
||||
IPrefabBuffer oldPrefabBuffer = oldPrefab.getCachedPrefab(worldX, worldY, worldZ, farming.getGeneration() - 1);
|
||||
double brokenParticlesRate = computeParticlesRate(prefabBuffer);
|
||||
world.execute(
|
||||
() -> {
|
||||
boolean isIntact = isPrefabIntact(oldPrefabBuffer, chunkAccessor, worldX, worldY, worldZ, prefabRotation, random);
|
||||
if (isIntact) {
|
||||
boolean isUnobstructed = prefabBuffer.compare(
|
||||
(px, py, pz, blockId, stateWrapper, chance, rotation, filler, secondBlockId, secondStateWrapper, secondChance, secondRotation, secondFiller, prefabBufferCall) -> {
|
||||
int bx = worldX + px;
|
||||
int by = worldY + py;
|
||||
int bz = worldZ + pz;
|
||||
if ((secondBlockId == 0 || secondBlockId == Integer.MIN_VALUE) && blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(bx, bz));
|
||||
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
|
||||
return !this.doesBlockObstruct(blockId, worldBlock);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
new PrefabBufferCall(random, prefabRotation),
|
||||
oldPrefabBuffer
|
||||
);
|
||||
if (isUnobstructed) {
|
||||
prefabBuffer.compare(
|
||||
(px, py, pz, blockId, stateWrapper, chance, rotation, filler, secondBlockId, secondStateWrapper, secondChance, secondRotation, secondFiller, prefabBufferCall) -> {
|
||||
int bx = worldX + px;
|
||||
int by = worldY + py;
|
||||
int bz = worldZ + pz;
|
||||
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(bx, bz));
|
||||
int updatedSetBlockSettings = 2;
|
||||
if (random.nextDouble() > brokenParticlesRate) {
|
||||
updatedSetBlockSettings |= 4;
|
||||
}
|
||||
|
||||
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
BlockType block = blockTypeMap.getAsset(blockId);
|
||||
if (filler != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
|
||||
if ((secondBlockId == 0 || secondBlockId == Integer.MIN_VALUE) && !this.canReplace(worldBlock, blockTypeMap)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nonTickingChunk.setBlock(bx, by, bz, blockId, block, rotation, filler, updatedSetBlockSettings);
|
||||
if (stateWrapper != null) {
|
||||
nonTickingChunk.setState(bx, by, bz, stateWrapper.clone());
|
||||
}
|
||||
} else if (secondBlockId != 0 && secondBlockId != Integer.MIN_VALUE) {
|
||||
nonTickingChunk.breakBlock(bx, by, bz, updatedSetBlockSettings);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
new PrefabBufferCall(random, prefabRotation),
|
||||
oldPrefabBuffer
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing farming block component when applying prefab farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
world.execute(
|
||||
() -> {
|
||||
boolean isUnObstructed = prefabBuffer.forEachRaw(
|
||||
IPrefabBuffer.iterateAllColumns(), (blockX, blockY, blockZ, blockId, chance, holder, supportValue, rotation, filler, t) -> {
|
||||
int bx = worldX + prefabRotation.getX(blockX, blockZ);
|
||||
int by = worldY + blockY;
|
||||
int bz = worldZ + prefabRotation.getX(blockZ, blockX);
|
||||
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
int worldBlock = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(bx, bz)).getBlock(bx, by, bz);
|
||||
return !this.doesBlockObstruct(blockId, worldBlock);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}, (fluidX, fluidY, fluidZ, fluidId, level, o) -> true, null, new PrefabBufferCall(random, prefabRotation)
|
||||
);
|
||||
if (isUnObstructed) {
|
||||
prefabBuffer.forEach(
|
||||
IPrefabBuffer.iterateAllColumns(), (blockX, blockY, blockZ, blockId, holder, supportValue, rotation, filler, t, fluidId, fluidLevel) -> {
|
||||
int bx = worldX + blockX;
|
||||
int by = worldY + blockY;
|
||||
int bz = worldZ + blockZ;
|
||||
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(bx, bz));
|
||||
int updatedSetBlockSettings = 2;
|
||||
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
BlockType block = blockTypeMap.getAsset(blockId);
|
||||
if (filler != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
|
||||
if (!this.canReplace(worldBlock, blockTypeMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nonTickingChunk.setBlock(bx, by, bz, blockId, block, rotation, filler, updatedSetBlockSettings);
|
||||
if (holder != null) {
|
||||
nonTickingChunk.setState(bx, by, bz, holder.clone());
|
||||
}
|
||||
}
|
||||
}, null, null, new PrefabBufferCall(random, prefabRotation)
|
||||
);
|
||||
}
|
||||
IPrefabBuffer prefabBuffer = this.getCachedPrefab(x, y, z, farmingBlockComponent.getGeneration());
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
int randomRotation = HashUtil.randomInt(x, y, z, Rotation.VALUES.length);
|
||||
RotationTuple yaw = RotationTuple.of(Rotation.VALUES[randomRotation], Rotation.None);
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing chunk section component when applying prefab farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
if (farmingBlockComponent.getPreviousBlockType() == null) {
|
||||
farmingBlockComponent.setPreviousBlockType(BlockType.getAssetMap().getAsset(blockSection.get(x, y, z)).getId());
|
||||
}
|
||||
);
|
||||
|
||||
double xLength = prefabBuffer.getMaxX() - prefabBuffer.getMinX();
|
||||
double zLength = prefabBuffer.getMaxZ() - prefabBuffer.getMinZ();
|
||||
int prefabRadius = (int)MathUtil.fastFloor(0.5 * Math.sqrt(xLength * xLength + zLength * zLength));
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, x, z, prefabRadius);
|
||||
FastRandom random = new FastRandom();
|
||||
PrefabRotation prefabRotation = PrefabRotation.fromRotation(yaw.yaw());
|
||||
BlockTypeAssetMap<String, BlockType> blockTypeMap = BlockType.getAssetMap();
|
||||
if (previousStage instanceof PrefabFarmingStageData oldPrefab) {
|
||||
IPrefabBuffer oldPrefabBuffer = oldPrefab.getCachedPrefab(worldX, worldY, worldZ, farmingBlockComponent.getGeneration() - 1);
|
||||
double brokenParticlesRate = computeParticlesRate(prefabBuffer);
|
||||
world.execute(
|
||||
() -> {
|
||||
boolean isIntact = isPrefabIntact(oldPrefabBuffer, chunkAccessor, worldX, worldY, worldZ, prefabRotation, random);
|
||||
if (isIntact) {
|
||||
boolean isUnobstructed = prefabBuffer.compare(
|
||||
(px, py, pz, blockId, stateWrapper, chance, rotation, filler, secondBlockId, secondStateWrapper, secondChance, secondRotation, secondFiller, prefabBufferCall) -> {
|
||||
int bx = worldX + px;
|
||||
int by = worldY + py;
|
||||
int bz = worldZ + pz;
|
||||
if ((secondBlockId == 0 || secondBlockId == Integer.MIN_VALUE) && blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
|
||||
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(chunkIndex);
|
||||
if (nonTickingChunk == null) {
|
||||
return false;
|
||||
} else {
|
||||
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
|
||||
return !this.doesBlockObstruct(blockId, worldBlock);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
new PrefabBufferCall(random, prefabRotation),
|
||||
oldPrefabBuffer
|
||||
);
|
||||
if (isUnobstructed) {
|
||||
prefabBuffer.compare(
|
||||
(px, py, pz, blockId, stateWrapper, chance, rotation, filler, secondBlockId, secondStateWrapper, secondChance, secondRotation, secondFiller, prefabBufferCall) -> {
|
||||
int bx = worldX + px;
|
||||
int by = worldY + py;
|
||||
int bz = worldZ + pz;
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
|
||||
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(chunkIndex);
|
||||
if (nonTickingChunk == null) {
|
||||
return true;
|
||||
} else {
|
||||
int updatedSetBlockSettings = 2;
|
||||
if (random.nextDouble() > brokenParticlesRate) {
|
||||
updatedSetBlockSettings |= 4;
|
||||
}
|
||||
|
||||
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
BlockType block = blockTypeMap.getAsset(blockId);
|
||||
if (block == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log(
|
||||
"Invalid block ID %d in prefab at (%d, %d, %d) for farming stage at (%d, %d, %d)",
|
||||
blockId,
|
||||
px,
|
||||
py,
|
||||
pz,
|
||||
worldX,
|
||||
worldY,
|
||||
worldZ
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (filler != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
|
||||
if ((secondBlockId == 0 || secondBlockId == Integer.MIN_VALUE) && !this.canReplace(worldBlock, blockTypeMap)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nonTickingChunk.setBlock(bx, by, bz, blockId, block, rotation, filler, updatedSetBlockSettings);
|
||||
if (stateWrapper != null) {
|
||||
nonTickingChunk.setState(bx, by, bz, stateWrapper.clone());
|
||||
}
|
||||
} else if (secondBlockId != 0 && secondBlockId != Integer.MIN_VALUE) {
|
||||
nonTickingChunk.breakBlock(bx, by, bz, updatedSetBlockSettings);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
new PrefabBufferCall(random, prefabRotation),
|
||||
oldPrefabBuffer
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
world.execute(
|
||||
() -> {
|
||||
boolean isUnObstructed = prefabBuffer.forEachRaw(
|
||||
IPrefabBuffer.iterateAllColumns(), (blockX, blockY, blockZ, blockId, chance, holder, supportValue, rotation, filler, t) -> {
|
||||
int bx = worldX + prefabRotation.getX(blockX, blockZ);
|
||||
int by = worldY + blockY;
|
||||
int bz = worldZ + prefabRotation.getX(blockZ, blockX);
|
||||
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
|
||||
WorldChunk nonTickingWorldChunkComponent = chunkAccessor.getNonTickingChunk(chunkIndex);
|
||||
if (nonTickingWorldChunkComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
int worldBlock = nonTickingWorldChunkComponent.getBlock(bx, by, bz);
|
||||
return !this.doesBlockObstruct(blockId, worldBlock);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}, (fluidX, fluidY, fluidZ, fluidId, level, o) -> true, null, new PrefabBufferCall(random, prefabRotation)
|
||||
);
|
||||
if (isUnObstructed) {
|
||||
prefabBuffer.forEach(
|
||||
IPrefabBuffer.iterateAllColumns(),
|
||||
(blockX, blockY, blockZ, blockId, holder, supportValue, rotation, filler, t, fluidId, fluidLevel) -> {
|
||||
int bx = worldX + blockX;
|
||||
int by = worldY + blockY;
|
||||
int bz = worldZ + blockZ;
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
|
||||
WorldChunk nonTickingWorldChunkComponent = chunkAccessor.getNonTickingChunk(chunkIndex);
|
||||
if (nonTickingWorldChunkComponent != null) {
|
||||
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
|
||||
BlockType blockTypeAsset = blockTypeMap.getAsset(blockId);
|
||||
if (blockTypeAsset == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log(
|
||||
"Invalid block ID %d in prefab at (%d, %d, %d) for farming stage at (%d, %d, %d)",
|
||||
blockId,
|
||||
blockX,
|
||||
blockY,
|
||||
blockZ,
|
||||
worldX,
|
||||
worldY,
|
||||
worldZ
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filler != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int worldBlock = nonTickingWorldChunkComponent.getBlock(bx, by, bz);
|
||||
if (!this.canReplace(worldBlock, blockTypeMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nonTickingWorldChunkComponent.setBlock(bx, by, bz, blockId, blockTypeAsset, rotation, filler, 2);
|
||||
if (holder != null) {
|
||||
nonTickingWorldChunkComponent.setState(bx, by, bz, holder.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
null,
|
||||
new PrefabBufferCall(random, prefabRotation)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +359,7 @@ public class PrefabFarmingStageData extends FarmingStageData {
|
||||
return blockType != null && blockType.getMaterial() != BlockMaterial.Empty ? !this.canReplace(worldBlockId, assetMap) : false;
|
||||
}
|
||||
|
||||
private boolean canReplace(int worldBlockId, BlockTypeAssetMap<String, BlockType> assetMap) {
|
||||
private boolean canReplace(int worldBlockId, @Nonnull BlockTypeAssetMap<String, BlockType> assetMap) {
|
||||
BlockType worldBlockType = assetMap.getAsset(worldBlockId);
|
||||
if (worldBlockType != null && worldBlockType.getMaterial() != BlockMaterial.Empty) {
|
||||
for (int tagIndex : this.replaceMaskTagIndices) {
|
||||
@@ -299,18 +375,39 @@ public class PrefabFarmingStageData extends FarmingStageData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(ComponentAccessor<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
public void remove(
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> blockRef, int x, int y, int z
|
||||
) {
|
||||
super.remove(commandBuffer, sectionRef, blockRef, x, y, z);
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
IPrefabBuffer prefab = this.getCachedPrefab(worldX, worldY, worldZ, farming.getGeneration() - 1);
|
||||
RotationTuple rotation = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType()).getRotation(x, y, z);
|
||||
double rate = computeParticlesRate(prefab);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
world.execute(() -> PrefabUtil.remove(prefab, world, new Vector3i(worldX, worldY, worldZ), rotation.yaw(), true, new FastRandom(), 2, rate));
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing chunk section component when removing prefab farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing farming block component when removing prefab farming stage at (%d, %d, %d)", worldX, worldY, worldZ);
|
||||
} else {
|
||||
IPrefabBuffer prefab = this.getCachedPrefab(worldX, worldY, worldZ, farmingBlockComponent.getGeneration() - 1);
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (blockSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing block section component when removing prefab farming stage at (%d, %d, %d)", worldX, worldY, worldZ);
|
||||
} else {
|
||||
RotationTuple rotation = blockSectionComponent.getRotation(x, y, z);
|
||||
double rate = computeParticlesRate(prefab);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
world.execute(() -> PrefabUtil.remove(prefab, world, new Vector3i(worldX, worldY, worldZ), rotation.yaw(), true, new FastRandom(), 2, rate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -326,15 +423,17 @@ public class PrefabFarmingStageData extends FarmingStageData {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PrefabFarmingStageData{replaceMaskTags=" + Arrays.toString((Object[])this.replaceMaskTags) + ", prefabStages=" + this.prefabStages + "}";
|
||||
}
|
||||
|
||||
public static class PrefabStage implements IWeightedElement {
|
||||
@Nonnull
|
||||
public static final PrefabFarmingStageData.PrefabStage[] EMPTY_ARRAY = new PrefabFarmingStageData.PrefabStage[0];
|
||||
@Nonnull
|
||||
public static Codec<PrefabFarmingStageData.PrefabStage> CODEC = BuilderCodec.builder(
|
||||
public static final Codec<PrefabFarmingStageData.PrefabStage> CODEC = BuilderCodec.builder(
|
||||
PrefabFarmingStageData.PrefabStage.class, PrefabFarmingStageData.PrefabStage::new
|
||||
)
|
||||
.append(new KeyedCodec<>("Weight", Codec.INTEGER), (prefabStage, integer) -> prefabStage.weight = integer, prefabStage -> prefabStage.weight)
|
||||
@@ -354,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
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<DirectionalGrowthBehaviour> CODEC = BuilderCodec.builder(
|
||||
DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour::new, BASE_CODEC
|
||||
)
|
||||
@@ -92,9 +93,9 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
|
||||
@Override
|
||||
public void execute(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> componentAccessor,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int worldX,
|
||||
int worldY,
|
||||
int worldZ,
|
||||
@@ -103,54 +104,68 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
int x = 0;
|
||||
int z = 0;
|
||||
FastRandom random = new FastRandom();
|
||||
String blockTypeKey = this.blockTypes.get(random).getBlockTypeKey();
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, worldX, worldZ, 1);
|
||||
DirectionalGrowthBehaviour.BlockTypeWeight blockTypeWeight = this.blockTypes.get(random);
|
||||
if (blockTypeWeight != null) {
|
||||
String blockTypeKey = blockTypeWeight.getBlockTypeKey();
|
||||
World world = componentAccessor.getExternalData().getWorld();
|
||||
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, worldX, worldZ, 1);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (this.horizontalRange != null) {
|
||||
double angle = (float) (Math.PI * 2) * random.nextFloat();
|
||||
int radius = this.horizontalRange.getInt(random.nextFloat());
|
||||
x = MathUtil.fastRound(radius * TrigMathUtil.cos(angle));
|
||||
z = MathUtil.fastRound(radius * TrigMathUtil.sin(angle));
|
||||
}
|
||||
|
||||
int targetX = worldX + x;
|
||||
int targetZ = worldZ + z;
|
||||
int chunkX = ChunkUtil.chunkCoordinate(targetX);
|
||||
int chunkZ = ChunkUtil.chunkCoordinate(targetZ);
|
||||
WorldChunk chunk = chunkAccessor.getChunkIfInMemory(ChunkUtil.indexChunk(chunkX, chunkZ));
|
||||
if (chunk != null) {
|
||||
int targetY;
|
||||
if (this.verticalRange != null) {
|
||||
int directionValue = switch (this.verticalDirection) {
|
||||
case DOWNWARDS, UPWARDS -> this.verticalDirection.getValue();
|
||||
case BOTH -> random.nextBoolean() ? 1 : -1;
|
||||
};
|
||||
targetY = worldY + this.verticalRange.getInt(random.nextFloat()) * directionValue;
|
||||
} else {
|
||||
targetY = chunk.getHeight(targetX, targetZ) + 1;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (this.horizontalRange != null) {
|
||||
double angle = (float) (Math.PI * 2) * random.nextFloat();
|
||||
int radius = this.horizontalRange.getInt(random.nextFloat());
|
||||
x = MathUtil.fastRound(radius * TrigMathUtil.cos(angle));
|
||||
z = MathUtil.fastRound(radius * TrigMathUtil.sin(angle));
|
||||
}
|
||||
|
||||
if (this.tryPlaceBlock(world, chunk, targetX, targetY, targetZ, blockTypeKey, 0)) {
|
||||
int finalTargetY = targetY;
|
||||
world.execute(() -> {
|
||||
WorldChunk loadedChunk = chunkAccessor.getChunk(ChunkUtil.indexChunk(chunkX, chunkZ));
|
||||
if (loadedChunk != null) {
|
||||
loadedChunk.placeBlock(targetX, finalTargetY, targetZ, blockTypeKey, Rotation.None, Rotation.None, Rotation.None);
|
||||
decaySpread(commandBuffer, loadedChunk.getBlockComponentChunk(), targetX, finalTargetY, targetZ, newSpreadRate);
|
||||
}
|
||||
});
|
||||
return;
|
||||
int targetX = worldX + x;
|
||||
int targetZ = worldZ + z;
|
||||
int chunkX = ChunkUtil.chunkCoordinate(targetX);
|
||||
int chunkZ = ChunkUtil.chunkCoordinate(targetZ);
|
||||
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
WorldChunk worldChunkComponent = chunkAccessor.getChunkIfInMemory(chunkIndex);
|
||||
if (worldChunkComponent != null) {
|
||||
int targetY;
|
||||
if (this.verticalRange != null) {
|
||||
int directionValue = switch (this.verticalDirection) {
|
||||
case DOWNWARDS, UPWARDS -> this.verticalDirection.getValue();
|
||||
case BOTH -> random.nextBoolean() ? 1 : -1;
|
||||
};
|
||||
targetY = worldY + this.verticalRange.getInt(random.nextFloat()) * directionValue;
|
||||
} else {
|
||||
targetY = worldChunkComponent.getHeight(targetX, targetZ) + 1;
|
||||
}
|
||||
|
||||
if (this.tryPlaceBlock(world, worldChunkComponent, targetX, targetY, targetZ, blockTypeKey, 0)) {
|
||||
int finalTargetY = targetY;
|
||||
world.execute(() -> {
|
||||
long loadedChunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
WorldChunk loadedChunk = chunkAccessor.getChunk(loadedChunkIndex);
|
||||
if (loadedChunk != null) {
|
||||
loadedChunk.placeBlock(targetX, finalTargetY, targetZ, blockTypeKey, Rotation.None, Rotation.None, Rotation.None);
|
||||
BlockComponentChunk blockComponentChunk = loadedChunk.getBlockComponentChunk();
|
||||
if (blockComponentChunk != null) {
|
||||
decaySpread(componentAccessor, blockComponentChunk, targetX, finalTargetY, targetZ, newSpreadRate);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void decaySpread(
|
||||
ComponentAccessor<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, int worldX, int worldY, int worldZ, float newSpreadRate
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull BlockComponentChunk blockComponentChunk,
|
||||
int worldX,
|
||||
int worldY,
|
||||
int worldZ,
|
||||
float newSpreadRate
|
||||
) {
|
||||
Ref<ChunkStore> blockRefPlaced = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(worldX, worldY, worldZ));
|
||||
int blockIndex = ChunkUtil.indexBlockInColumn(worldX, worldY, worldZ);
|
||||
Ref<ChunkStore> blockRefPlaced = blockComponentChunk.getEntityReference(blockIndex);
|
||||
if (blockRefPlaced != null) {
|
||||
FarmingBlock farmingPlaced = commandBuffer.getComponent(blockRefPlaced, FarmingBlock.getComponentType());
|
||||
if (farmingPlaced != null) {
|
||||
@@ -159,37 +174,58 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tryPlaceBlock(@Nonnull World world, @Nonnull WorldChunk chunk, int worldX, int worldY, int worldZ, String blockTypeKey, int rotation) {
|
||||
private boolean tryPlaceBlock(
|
||||
@Nonnull World world, @Nonnull WorldChunk chunk, int worldX, int worldY, int worldZ, @Nonnull String blockTypeKey, int rotation
|
||||
) {
|
||||
if (chunk.getBlock(worldX, worldY, worldZ) != 0) {
|
||||
return false;
|
||||
} else if (!this.validatePosition(world, worldX, worldY, worldZ)) {
|
||||
return false;
|
||||
} else {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockTypeKey);
|
||||
if (blockType == null) {
|
||||
BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockTypeKey);
|
||||
if (blockTypeAsset == null) {
|
||||
return false;
|
||||
} else if (!chunk.testPlaceBlock(worldX, worldY, worldZ, blockType, rotation)) {
|
||||
} else if (!chunk.testPlaceBlock(worldX, worldY, worldZ, blockTypeAsset, rotation)) {
|
||||
return false;
|
||||
} else {
|
||||
int cx = chunk.getX();
|
||||
int cz = chunk.getZ();
|
||||
int cy = ChunkUtil.indexSection(worldY);
|
||||
Ref<ChunkStore> sectionRef = world.getChunkStore().getChunkSectionReference(cx, cy, cz);
|
||||
if (sectionRef == null) {
|
||||
return false;
|
||||
} else {
|
||||
Store<ChunkStore> store = world.getChunkStore().getStore();
|
||||
BlockPhysics blockPhysics = store.getComponent(sectionRef, BlockPhysics.getComponentType());
|
||||
FluidSection fluidSection = store.getComponent(sectionRef, FluidSection.getComponentType());
|
||||
BlockSection blockSection = store.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
int filler = blockSection.getFiller(worldX, worldY, worldZ);
|
||||
int chunkX = chunk.getX();
|
||||
int chunkY = ChunkUtil.indexSection(worldY);
|
||||
int chunkZ = chunk.getZ();
|
||||
ChunkStore chunkStore = world.getChunkStore();
|
||||
Ref<ChunkStore> sectionRef = chunkStore.getChunkSectionReference(chunkX, chunkY, chunkZ);
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
Store<ChunkStore> store = chunkStore.getStore();
|
||||
BlockPhysics blockPhysicsComponent = store.getComponent(sectionRef, BlockPhysics.getComponentType());
|
||||
|
||||
assert blockPhysicsComponent != null;
|
||||
|
||||
FluidSection fluidSectionComponent = store.getComponent(sectionRef, FluidSection.getComponentType());
|
||||
|
||||
assert fluidSectionComponent != null;
|
||||
|
||||
BlockSection blockSectionComponent = store.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
int filler = blockSectionComponent.getFiller(worldX, worldY, worldZ);
|
||||
BlockPhysicsSystems.CachedAccessor cachedAccessor = BlockPhysicsSystems.CachedAccessor.of(
|
||||
store, blockSection, blockPhysics, fluidSection, cx, cy, cz, 14
|
||||
store, blockSectionComponent, blockPhysicsComponent, fluidSectionComponent, chunkX, chunkY, chunkZ, 14
|
||||
);
|
||||
return BlockPhysicsUtil.testBlockPhysics(
|
||||
cachedAccessor, blockSection, blockPhysics, fluidSection, worldX, worldY, worldZ, blockType, rotation, filler
|
||||
cachedAccessor,
|
||||
blockSectionComponent,
|
||||
blockPhysicsComponent,
|
||||
fluidSectionComponent,
|
||||
worldX,
|
||||
worldY,
|
||||
worldZ,
|
||||
blockTypeAsset,
|
||||
rotation,
|
||||
filler
|
||||
)
|
||||
!= 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -212,7 +248,7 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
|
||||
public static class BlockTypeWeight implements IWeightedElement {
|
||||
@Nonnull
|
||||
public static BuilderCodec<DirectionalGrowthBehaviour.BlockTypeWeight> CODEC = BuilderCodec.builder(
|
||||
public static final BuilderCodec<DirectionalGrowthBehaviour.BlockTypeWeight> CODEC = BuilderCodec.builder(
|
||||
DirectionalGrowthBehaviour.BlockTypeWeight.class, DirectionalGrowthBehaviour.BlockTypeWeight::new
|
||||
)
|
||||
.append(
|
||||
|
||||
@@ -19,7 +19,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class SpreadFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
public static BuilderCodec<SpreadFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
public static final BuilderCodec<SpreadFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
SpreadFarmingStageData.class, SpreadFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(
|
||||
@@ -84,50 +84,67 @@ public class SpreadFarmingStageData extends FarmingStageData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldStop(ComponentAccessor<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
float spreadRate = farming.getSpreadRate();
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
float executions = this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farming.getGeneration())) * spreadRate;
|
||||
int executed = farming.getExecutions();
|
||||
return spreadRate <= 0.0F || executed >= executions;
|
||||
public boolean shouldStop(
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> blockRef, int x, int y, int z
|
||||
) {
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
return true;
|
||||
} else {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
return true;
|
||||
} else {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
float spreadRate = farmingBlockComponent.getSpreadRate();
|
||||
float executions = this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farmingBlockComponent.getGeneration())) * spreadRate;
|
||||
int executed = farmingBlockComponent.getExecutions();
|
||||
return spreadRate <= 0.0F || executed >= executions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
float spreadRate = farming.getSpreadRate();
|
||||
double executions = Math.floor(this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farming.getGeneration())) * spreadRate);
|
||||
int executed = farming.getExecutions();
|
||||
if (!(spreadRate <= 0.0F) && !(executed >= executions)) {
|
||||
for (int i = 0; i < this.spreadGrowthBehaviours.length; i++) {
|
||||
SpreadGrowthBehaviour spreadGrowthBehaviour = this.spreadGrowthBehaviours[i];
|
||||
float decayRate = this.spreadDecayPercent.getInt(HashUtil.random(i | (long)farming.getGeneration() << 32, worldX, worldY, worldZ)) / 100.0F;
|
||||
spreadGrowthBehaviour.execute(commandBuffer, sectionRef, blockRef, worldX, worldY, worldZ, spreadRate - decayRate);
|
||||
}
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent != null) {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent != null) {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
float spreadRate = farmingBlockComponent.getSpreadRate();
|
||||
int generation = farmingBlockComponent.getGeneration();
|
||||
double executions = Math.floor(this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, generation)) * spreadRate);
|
||||
int executed = farmingBlockComponent.getExecutions();
|
||||
if (!(spreadRate <= 0.0F) && !(executed >= executions)) {
|
||||
for (int i = 0; i < this.spreadGrowthBehaviours.length; i++) {
|
||||
SpreadGrowthBehaviour spreadGrowthBehaviour = this.spreadGrowthBehaviours[i];
|
||||
float decayRate = this.spreadDecayPercent.getInt(HashUtil.random(i | (long)generation << 32, worldX, worldY, worldZ)) / 100.0F;
|
||||
spreadGrowthBehaviour.execute(commandBuffer, sectionRef, blockRef, worldX, worldY, worldZ, spreadRate - decayRate);
|
||||
}
|
||||
|
||||
farming.setExecutions(++executed);
|
||||
farmingBlockComponent.setExecutions(++executed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(ComponentAccessor<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
public void remove(
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> blockRef, int x, int y, int z
|
||||
) {
|
||||
super.remove(commandBuffer, sectionRef, blockRef, x, y, z);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,12 @@ import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import com.hypixel.hytale.server.core.universe.world.worldlocationcondition.WorldLocationCondition;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class SpreadGrowthBehaviour {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<SpreadGrowthBehaviour> CODEC = new CodecMapCodec<>("Type");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SpreadGrowthBehaviour> BASE_CODEC = BuilderCodec.abstractBuilder(SpreadGrowthBehaviour.class)
|
||||
.append(
|
||||
new KeyedCodec<>("LocationConditions", new ArrayCodec<>(WorldLocationCondition.CODEC, WorldLocationCondition[]::new)),
|
||||
@@ -23,9 +26,11 @@ public abstract class SpreadGrowthBehaviour {
|
||||
.build();
|
||||
protected WorldLocationCondition[] worldLocationConditions;
|
||||
|
||||
public abstract void execute(ComponentAccessor<ChunkStore> var1, Ref<ChunkStore> var2, Ref<ChunkStore> var3, int var4, int var5, int var6, float var7);
|
||||
public abstract void execute(
|
||||
@Nonnull ComponentAccessor<ChunkStore> var1, @Nonnull Ref<ChunkStore> var2, @Nonnull Ref<ChunkStore> var3, int var4, int var5, int var6, float var7
|
||||
);
|
||||
|
||||
protected boolean validatePosition(World world, int worldX, int worldY, int worldZ) {
|
||||
protected boolean validatePosition(@Nonnull World world, int worldX, int worldY, int worldZ) {
|
||||
if (this.worldLocationConditions == null) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -35,7 +35,9 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ChangeFarmingStageInteraction> CODEC = BuilderCodec.builder(
|
||||
ChangeFarmingStageInteraction.class, ChangeFarmingStageInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -75,11 +77,11 @@ public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
|
||||
.build();
|
||||
protected int targetStage = -1;
|
||||
@Nullable
|
||||
protected Integer increaseBy = null;
|
||||
protected Integer increaseBy;
|
||||
@Nullable
|
||||
protected Integer decreaseBy = null;
|
||||
protected Integer decreaseBy;
|
||||
@Nullable
|
||||
protected String targetStageSet = null;
|
||||
protected String targetStageSet;
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@@ -270,16 +272,16 @@ public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
|
||||
);
|
||||
Ref<ChunkStore> sectionRef = world.getChunkStore()
|
||||
.getChunkSectionReference(ChunkUtil.chunkCoordinate(x), ChunkUtil.chunkCoordinate(y), ChunkUtil.chunkCoordinate(z));
|
||||
if (sectionRef != null) {
|
||||
BlockSection section = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (section != null) {
|
||||
section.scheduleTick(ChunkUtil.indexBlock(x, y, z), now);
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
BlockSection blockSectionComponent = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (blockSectionComponent != null) {
|
||||
blockSectionComponent.scheduleTick(ChunkUtil.indexBlock(x, y, z), now);
|
||||
}
|
||||
|
||||
stages[stageIndex].apply(chunkStore, sectionRef, blockRef, x, y, z, previousStage);
|
||||
LOGGER.atInfo().log("[ChangeFarmingStage] Applied stage %d via stages[%d].apply()", stageIndex, stageIndex);
|
||||
} else {
|
||||
LOGGER.atWarning().log("[ChangeFarmingStage] sectionRef was null - could not apply stage!");
|
||||
LOGGER.atWarning().log("[ChangeFarmingStage] sectionRef was null or invalid - could not apply stage!");
|
||||
}
|
||||
|
||||
worldChunk.setTicking(x, y, z, true);
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FertilizeSoilInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<FertilizeSoilInteraction> CODEC = BuilderCodec.builder(
|
||||
FertilizeSoilInteraction.class, FertilizeSoilInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -56,40 +57,45 @@ public class FertilizeSoilInteraction extends SimpleBlockInteraction {
|
||||
) {
|
||||
int x = targetBlock.getX();
|
||||
int z = targetBlock.getZ();
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef == null) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
|
||||
WorldChunk worldChunkComponent = world.getChunk(chunkIndex);
|
||||
if (worldChunkComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
TilledSoilBlock soil = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null && !soil.isFertilized()) {
|
||||
soil.setFertilized(true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
FarmingBlock farmingState = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingState == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
Ref<ChunkStore> blockRef = worldChunkComponent.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null || !blockRef.isValid()) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunkComponent, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
TilledSoilBlock tilledSoilComponent = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilComponent != null && !tilledSoilComponent.isFertilized()) {
|
||||
tilledSoilComponent.setFertilized(true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
Ref<ChunkStore> soilRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilRef == null) {
|
||||
FarmingBlock farmingBlockComponent = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
soil = chunkStore.getComponent(soilRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null && !soil.isFertilized()) {
|
||||
soil.setFertilized(true);
|
||||
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
Ref<ChunkStore> soilBlockRef = worldChunkComponent.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilBlockRef != null && soilBlockRef.isValid()) {
|
||||
tilledSoilComponent = chunkStore.getComponent(soilBlockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilComponent != null && !tilledSoilComponent.isFertilized()) {
|
||||
tilledSoilComponent.setFertilized(true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY(), z, true);
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.hypixel.hytale.builtin.adventure.farming.interactions;
|
||||
|
||||
import com.hypixel.hytale.builtin.adventure.farming.FarmingUtil;
|
||||
import com.hypixel.hytale.codec.Codec;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
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.InteractionState;
|
||||
import com.hypixel.hytale.protocol.InteractionType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import com.hypixel.hytale.server.core.entity.InteractionContext;
|
||||
@@ -22,11 +25,21 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class HarvestCropInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<HarvestCropInteraction> CODEC = BuilderCodec.builder(
|
||||
HarvestCropInteraction.class, HarvestCropInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
.documentation("Harvests the resources from the target farmable block.")
|
||||
.<Boolean>appendInherited(
|
||||
new KeyedCodec<>("RequireNotBroken", Codec.BOOLEAN),
|
||||
(interaction, s) -> interaction.requireNotBroken = s,
|
||||
interaction -> interaction.requireNotBroken,
|
||||
(interaction, parent) -> interaction.requireNotBroken = parent.requireNotBroken
|
||||
)
|
||||
.documentation("If true, the interaction will fail if the held item is broken (durability = 0).")
|
||||
.add()
|
||||
.build();
|
||||
protected boolean requireNotBroken = false;
|
||||
|
||||
@Override
|
||||
protected void interactWithBlock(
|
||||
@@ -38,25 +51,31 @@ public class HarvestCropInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull Vector3i targetBlock,
|
||||
@Nonnull CooldownHandler cooldownHandler
|
||||
) {
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
ChunkStore chunkStore = world.getChunkStore();
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z);
|
||||
Ref<ChunkStore> chunkRef = chunkStore.getChunkReference(chunkIndex);
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getStore().getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (this.requireNotBroken && itemInHand != null && itemInHand.isBroken()) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
ChunkStore chunkStore = world.getChunkStore();
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z);
|
||||
Ref<ChunkStore> chunkRef = chunkStore.getChunkReference(chunkIndex);
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getStore().getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.y);
|
||||
if (section != null) {
|
||||
WorldChunk worldChunkComponent = chunkStore.getStore().getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(targetBlock.y);
|
||||
if (blockSection != null) {
|
||||
WorldChunk worldChunkComponent = chunkStore.getStore().getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
BlockType blockType = worldChunkComponent.getBlockType(targetBlock);
|
||||
if (blockType != null) {
|
||||
int rotationIndex = section.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
FarmingUtil.harvest(world, commandBuffer, ref, blockType, rotationIndex, targetBlock);
|
||||
BlockType blockType = worldChunkComponent.getBlockType(targetBlock);
|
||||
if (blockType != null) {
|
||||
int rotationIndex = blockSection.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
if (!FarmingUtil.harvest(world, commandBuffer, ref, blockType, rotationIndex, targetBlock)) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.hypixel.hytale.server.core.inventory.Inventory;
|
||||
import com.hypixel.hytale.server.core.inventory.ItemStack;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInteraction;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction;
|
||||
@@ -41,6 +42,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<UseCaptureCrateInteraction> CODEC = BuilderCodec.builder(
|
||||
UseCaptureCrateInteraction.class, UseCaptureCrateInteraction::new, SimpleInteraction.CODEC
|
||||
)
|
||||
@@ -74,20 +76,26 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
boolean firstRun, float time, @Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler
|
||||
) {
|
||||
CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer();
|
||||
if (commandBuffer == null) {
|
||||
|
||||
assert commandBuffer != null;
|
||||
|
||||
ItemStack item = context.getHeldItem();
|
||||
if (item == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
ItemStack item = context.getHeldItem();
|
||||
if (item == null) {
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
if (!(EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity)) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
if (!(EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity)) {
|
||||
Inventory inventory = livingEntity.getInventory();
|
||||
byte activeHotbarSlot = inventory.getActiveHotbarSlot();
|
||||
ItemStack inHandItemStack = inventory.getActiveHotbarItem();
|
||||
if (inHandItemStack == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
Inventory inventory = livingEntity.getInventory();
|
||||
byte activeHotbarSlot = inventory.getActiveHotbarSlot();
|
||||
ItemStack inHandItemStack = inventory.getActiveHotbarItem();
|
||||
CapturedNPCMetadata existingMeta = item.getFromMetadataOrNull("CapturedEntity", CapturedNPCMetadata.CODEC);
|
||||
if (existingMeta != null) {
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
@@ -95,47 +103,56 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
Ref<EntityStore> targetEntity = context.getTargetEntity();
|
||||
if (targetEntity == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
NPCEntity npcComponent = commandBuffer.getComponent(targetEntity, NPCEntity.getComponentType());
|
||||
if (npcComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
|
||||
boolean tagFound = false;
|
||||
|
||||
for (int group : this.acceptedNpcGroupIndexes) {
|
||||
if (tagSetPlugin.tagInSet(group, npcComponent.getRoleIndex())) {
|
||||
tagFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tagFound) {
|
||||
DeathComponent deathComponent = commandBuffer.getComponent(targetEntity, DeathComponent.getComponentType());
|
||||
if (deathComponent != null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
PersistentModel persistentModel = commandBuffer.getComponent(targetEntity, PersistentModel.getComponentType());
|
||||
if (persistentModel == null) {
|
||||
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
|
||||
boolean tagFound = false;
|
||||
|
||||
for (int group : this.acceptedNpcGroupIndexes) {
|
||||
if (tagSetPlugin.tagInSet(group, npcComponent.getRoleIndex())) {
|
||||
tagFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tagFound) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(persistentModel.getModelReference().getModelAssetId());
|
||||
CapturedNPCMetadata meta = inHandItemStack.getFromMetadataOrDefault("CapturedEntity", CapturedNPCMetadata.CODEC);
|
||||
if (modelAsset != null) {
|
||||
meta.setIconPath(modelAsset.getIcon());
|
||||
}
|
||||
PersistentModel persistentModelComponent = commandBuffer.getComponent(targetEntity, PersistentModel.getComponentType());
|
||||
if (persistentModelComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(persistentModelComponent.getModelReference().getModelAssetId());
|
||||
CapturedNPCMetadata itemMetaData = inHandItemStack.getFromMetadataOrDefault("CapturedEntity", CapturedNPCMetadata.CODEC);
|
||||
if (modelAsset != null) {
|
||||
itemMetaData.setIconPath(modelAsset.getIcon());
|
||||
}
|
||||
|
||||
meta.setRoleIndex(npcComponent.getRoleIndex());
|
||||
String npcName = NPCPlugin.get().getName(npcComponent.getRoleIndex());
|
||||
if (npcName != null) {
|
||||
meta.setNpcNameKey(npcName);
|
||||
}
|
||||
String npcName = NPCPlugin.get().getName(npcComponent.getRoleIndex());
|
||||
if (npcName != null) {
|
||||
itemMetaData.setNpcNameKey(npcName);
|
||||
}
|
||||
|
||||
if (this.fullIcon != null) {
|
||||
meta.setFullItemIcon(this.fullIcon);
|
||||
}
|
||||
if (this.fullIcon != null) {
|
||||
itemMetaData.setFullItemIcon(this.fullIcon);
|
||||
}
|
||||
|
||||
ItemStack itemWithNPC = inHandItemStack.withMetadata(CapturedNPCMetadata.KEYED_CODEC, meta);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, itemWithNPC);
|
||||
commandBuffer.removeEntity(targetEntity, RemoveReason.REMOVE);
|
||||
ItemStack itemWithNPC = inHandItemStack.withMetadata(CapturedNPCMetadata.KEYED_CODEC, itemMetaData);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, itemWithNPC);
|
||||
commandBuffer.removeEntity(targetEntity, RemoveReason.REMOVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,46 +189,51 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
if (pos == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(pos.x, pos.z));
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(pos.x, pos.y, pos.z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, pos.x, pos.y, pos.z);
|
||||
}
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(pos.x, pos.z);
|
||||
WorldChunk worldChunk = world.getChunk(chunkIndex);
|
||||
if (worldChunk == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(pos.x, pos.y, pos.z);
|
||||
if (blockRef == null || !blockRef.isValid()) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
ItemStack noMetaItemStack = item.withMetadata(null);
|
||||
if (blockRef != null) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
CoopBlock coopBlockState = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockState != null) {
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
if (coopBlockState.tryPutResident(existingMeta, worldTimeResource)) {
|
||||
world.execute(
|
||||
() -> coopBlockState.ensureSpawnResidentsInWorld(
|
||||
world, world.getEntityStore().getStore(), new Vector3d(pos.x, pos.y, pos.z), new Vector3d().assign(Vector3d.FORWARD)
|
||||
)
|
||||
);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
ItemStack noMetaItemStack = item.withMetadata(null);
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
CoopBlock coopBlockComponent = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockComponent != null) {
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
if (coopBlockComponent.tryPutResident(existingMeta, worldTimeResource)) {
|
||||
world.execute(
|
||||
() -> coopBlockComponent.ensureSpawnResidentsInWorld(
|
||||
world, world.getEntityStore().getStore(), new Vector3d(pos.x, pos.y, pos.z), new Vector3d().assign(Vector3d.FORWARD)
|
||||
)
|
||||
);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
context.getState().state = InteractionState.Finished;
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3d spawnPos = new Vector3d(pos.x + 0.5F, pos.y, pos.z + 0.5F);
|
||||
if (context.getClientState() != null) {
|
||||
BlockFace blockFace = BlockFace.fromProtocolFace(context.getClientState().blockFace);
|
||||
if (blockFace != null) {
|
||||
spawnPos.add(blockFace.getDirection());
|
||||
Vector3d spawnPos = new Vector3d(pos.x + 0.5F, pos.y, pos.z + 0.5F);
|
||||
if (context.getClientState() != null) {
|
||||
BlockFace blockFace = BlockFace.fromProtocolFace(context.getClientState().blockFace);
|
||||
if (blockFace != null) {
|
||||
spawnPos.add(blockFace.getDirection());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NPCPlugin npcModule = NPCPlugin.get();
|
||||
Store<EntityStore> store = context.getCommandBuffer().getStore();
|
||||
int roleIndex = existingMeta.getRoleIndex();
|
||||
commandBuffer.run(_store -> npcModule.spawnEntity(store, roleIndex, spawnPos, Vector3f.ZERO, null, null));
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
String roleId = existingMeta.getNpcNameKey();
|
||||
int roleIndex = NPCPlugin.get().getIndex(roleId);
|
||||
commandBuffer.run(_store -> NPCPlugin.get().spawnEntity(_store, roleIndex, spawnPos, Vector3f.ZERO, null, null));
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UseCoopInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<UseCoopInteraction> CODEC = BuilderCodec.builder(
|
||||
UseCoopInteraction.class, UseCoopInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -43,39 +44,39 @@ public class UseCoopInteraction extends SimpleBlockInteraction {
|
||||
) {
|
||||
int x = targetBlock.getX();
|
||||
int z = targetBlock.getZ();
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
|
||||
WorldChunk worldChunk = world.getChunk(chunkIndex);
|
||||
if (worldChunk == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
if (blockRef == null || !blockRef.isValid()) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
CoopBlock coopBlockState = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockState == null) {
|
||||
CoopBlock coopBlockComponent = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<EntityStore> playerRef = context.getEntity();
|
||||
LivingEntity playerEntity = (LivingEntity)EntityUtils.getEntity(playerRef, commandBuffer);
|
||||
if (playerEntity == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
CombinedItemContainer playerInventoryContainer = playerEntity.getInventory().getCombinedHotbarFirst();
|
||||
if (playerInventoryContainer != null) {
|
||||
coopBlockState.gatherProduceFromInventory(playerInventoryContainer);
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
if (EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity) {
|
||||
CombinedItemContainer inventoryContainer = livingEntity.getInventory().getCombinedHotbarFirst();
|
||||
if (inventoryContainer != null) {
|
||||
coopBlockComponent.gatherProduceFromContainer(inventoryContainer);
|
||||
BlockType currentBlockType = worldChunk.getBlockType(targetBlock);
|
||||
|
||||
assert currentBlockType != null;
|
||||
|
||||
worldChunk.setBlockInteractionState(targetBlock, currentBlockType, coopBlockState.hasProduce() ? "Produce_Ready" : "default");
|
||||
worldChunk.setBlockInteractionState(targetBlock, currentBlockType, coopBlockComponent.hasProduce() ? "Produce_Ready" : "default");
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UseWateringCanInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<UseWateringCanInteraction> CODEC = BuilderCodec.builder(
|
||||
UseWateringCanInteraction.class, UseWateringCanInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -61,45 +62,52 @@ public class UseWateringCanInteraction extends SimpleBlockInteraction {
|
||||
) {
|
||||
int x = targetBlock.getX();
|
||||
int z = targetBlock.getZ();
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef == null) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
|
||||
WorldChunk worldChunk = world.getChunk(chunkIndex);
|
||||
if (worldChunk == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
TilledSoilBlock soil = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null) {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
soil.setWateredUntil(wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
FarmingBlock farmingState = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingState == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
TilledSoilBlock tilledSoilBlockComponent = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilBlockComponent != null) {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
tilledSoilBlockComponent.setWateredUntil(wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
Ref<ChunkStore> soilRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilRef == null) {
|
||||
FarmingBlock farmingBlockComponent = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
soil = chunkStore.getComponent(soilRef, TilledSoilBlock.getComponentType());
|
||||
if (soil == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
Ref<ChunkStore> soilBlockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilBlockRef != null && soilBlockRef.isValid()) {
|
||||
tilledSoilBlockComponent = chunkStore.getComponent(soilBlockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
tilledSoilBlockComponent.setWateredUntil(wateredUntil);
|
||||
worldChunk.getBlockChunk()
|
||||
.getSectionAtBlockY(targetBlock.y - 1)
|
||||
.scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y - 1, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
}
|
||||
} else {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
soil.setWateredUntil(wateredUntil);
|
||||
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y - 1).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y - 1, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CoopBlock implements Component<ChunkStore> {
|
||||
@Nonnull
|
||||
public static final String STATE_PRODUCE = "Produce_Ready";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CoopBlock> CODEC = BuilderCodec.builder(CoopBlock.class, CoopBlock::new)
|
||||
.append(new KeyedCodec<>("FarmingCoopId", Codec.STRING, true), (coop, s) -> coop.coopAssetId = s, coop -> coop.coopAssetId)
|
||||
.add()
|
||||
@@ -73,7 +76,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
.add()
|
||||
.build();
|
||||
protected String coopAssetId;
|
||||
protected List<CoopBlock.CoopResident> residents = new ArrayList<>();
|
||||
@Nonnull
|
||||
protected List<CoopBlock.CoopResident> residents = new ObjectArrayList<>();
|
||||
@Nonnull
|
||||
protected ItemContainer itemContainer = EmptyItemContainer.INSTANCE;
|
||||
|
||||
public static ComponentType<ChunkStore, CoopBlock> getComponentType() {
|
||||
@@ -81,7 +86,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
public CoopBlock() {
|
||||
ArrayList<ItemStack> remainder = new ArrayList<>();
|
||||
List<ItemStack> remainder = new ObjectArrayList<>();
|
||||
this.itemContainer = ItemContainer.ensureContainerCapacity(this.itemContainer, (short)5, SimpleItemContainer::new, remainder);
|
||||
}
|
||||
|
||||
@@ -90,7 +95,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
return FarmingCoopAsset.getAssetMap().getAsset(this.coopAssetId);
|
||||
}
|
||||
|
||||
public CoopBlock(String farmingCoopId, List<CoopBlock.CoopResident> residents, ItemContainer itemContainer) {
|
||||
public CoopBlock(@Nonnull String farmingCoopId, @Nonnull List<CoopBlock.CoopResident> residents, @Nonnull ItemContainer itemContainer) {
|
||||
this.coopAssetId = farmingCoopId;
|
||||
this.residents.addAll(residents);
|
||||
this.itemContainer = itemContainer.clone();
|
||||
@@ -98,13 +103,13 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
this.itemContainer = ItemContainer.ensureContainerCapacity(this.itemContainer, (short)5, SimpleItemContainer::new, remainder);
|
||||
}
|
||||
|
||||
public boolean tryPutResident(CapturedNPCMetadata metadata, WorldTimeResource worldTimeResource) {
|
||||
public boolean tryPutResident(@Nonnull CapturedNPCMetadata metadata, @Nonnull WorldTimeResource worldTimeResource) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return false;
|
||||
} else if (this.residents.size() >= coopAsset.getMaxResidents()) {
|
||||
return false;
|
||||
} else if (!this.getCoopAcceptsNPCGroup(metadata.getRoleIndex())) {
|
||||
} else if (!this.getCoopAcceptsNPC(metadata.getNpcNameKey())) {
|
||||
return false;
|
||||
} else {
|
||||
this.residents.add(new CoopBlock.CoopResident(metadata, null, worldTimeResource.getGameTime()));
|
||||
@@ -112,7 +117,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryPutWildResidentFromWild(Store<EntityStore> store, Ref<EntityStore> entityRef, WorldTimeResource worldTimeResource, Vector3i coopLocation) {
|
||||
public boolean tryPutWildResidentFromWild(
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> entityRef, @Nonnull WorldTimeResource worldTimeResource, @Nonnull Vector3i coopLocation
|
||||
) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return false;
|
||||
@@ -124,7 +131,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
|
||||
if (coopResidentComponent != null) {
|
||||
return false;
|
||||
} else if (!this.getCoopAcceptsNPCGroup(npcComponent.getRoleIndex())) {
|
||||
} else if (!this.getCoopAcceptsNPC(npcComponent.getRoleName())) {
|
||||
return false;
|
||||
} else if (this.residents.size() >= coopAsset.getMaxResidents()) {
|
||||
return false;
|
||||
@@ -137,7 +144,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
} else {
|
||||
PersistentRef persistentRef = new PersistentRef();
|
||||
persistentRef.setEntity(entityRef, uuidComponent.getUuid());
|
||||
CapturedNPCMetadata metadata = FarmingUtil.generateCapturedNPCMetadata(store, entityRef, npcComponent.getRoleIndex());
|
||||
CapturedNPCMetadata metadata = FarmingUtil.generateCapturedNPCMetadata(store, entityRef, npcComponent.getRoleName());
|
||||
CoopBlock.CoopResident residentRecord = new CoopBlock.CoopResident(metadata, persistentRef, worldTimeResource.getGameTime());
|
||||
residentRecord.deployedToWorld = true;
|
||||
this.residents.add(residentRecord);
|
||||
@@ -148,8 +155,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getCoopAcceptsNPCGroup(int npcRoleIndex) {
|
||||
public boolean getCoopAcceptsNPC(String npcNameKey) {
|
||||
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
|
||||
int roleIndex = NPCPlugin.get().getIndex(npcNameKey);
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return false;
|
||||
@@ -159,7 +167,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
return true;
|
||||
} else {
|
||||
for (int group : acceptedNpcGroupIndexes) {
|
||||
if (tagSetPlugin.tagInSet(group, npcRoleIndex)) {
|
||||
if (tagSetPlugin.tagInSet(group, roleIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +177,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void generateProduceToInventory(WorldTimeResource worldTimeResource) {
|
||||
public void generateProduceToInventory(@Nonnull WorldTimeResource worldTimeResource) {
|
||||
Instant currentTime = worldTimeResource.getGameTime();
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
@@ -184,8 +192,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
resident.setLastProduced(currentTime);
|
||||
} else {
|
||||
CapturedNPCMetadata residentMeta = resident.getMetadata();
|
||||
int npcRoleIndex = residentMeta.getRoleIndex();
|
||||
String npcName = NPCPlugin.get().getName(npcRoleIndex);
|
||||
String npcName = residentMeta.getNpcNameKey();
|
||||
String npcDropListName = produceDropsMap.get(npcName);
|
||||
if (npcDropListName != null) {
|
||||
ItemDropList dropListAsset = ItemDropList.getAssetMap().getAsset(npcDropListName);
|
||||
@@ -225,14 +232,15 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void gatherProduceFromInventory(ItemContainer playerInventory) {
|
||||
public void gatherProduceFromContainer(@Nonnull ItemContainer playerInventory) {
|
||||
for (ItemStack item : this.itemContainer.removeAllItemStacks()) {
|
||||
playerInventory.addItemStack(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureSpawnResidentsInWorld(World world, Store<EntityStore> store, Vector3d coopLocation, Vector3d spawnOffset) {
|
||||
NPCPlugin npcModule = NPCPlugin.get();
|
||||
public void ensureSpawnResidentsInWorld(
|
||||
@Nonnull World world, @Nonnull Store<EntityStore> store, @Nonnull Vector3d coopLocation, @Nonnull Vector3d spawnOffset
|
||||
) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
float radiansPerSpawn = (float) (Math.PI * 2) / coopAsset.getMaxResidents();
|
||||
@@ -241,7 +249,8 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
CapturedNPCMetadata residentMeta = resident.getMetadata();
|
||||
int npcRoleIndex = residentMeta.getRoleIndex();
|
||||
String npcNameKey = residentMeta.getNpcNameKey();
|
||||
int npcRoleIndex = NPCPlugin.get().getIndex(npcNameKey);
|
||||
boolean residentDeployed = resident.getDeployedToWorld();
|
||||
PersistentRef residentEntityId = resident.getPersistentRef();
|
||||
if (!residentDeployed && residentEntityId == null) {
|
||||
@@ -251,9 +260,8 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
spawningContext.setSpawnable((ISpawnableWithModel)roleBuilder);
|
||||
if (spawningContext.set(world, residentSpawnLocation.x, residentSpawnLocation.y, residentSpawnLocation.z)
|
||||
&& spawningContext.canSpawn() == SpawnTestResult.TEST_OK) {
|
||||
Pair<Ref<EntityStore>, NPCEntity> npcPair = npcModule.spawnEntity(
|
||||
store, npcRoleIndex, spawningContext.newPosition(), Vector3f.ZERO, null, null
|
||||
);
|
||||
Pair<Ref<EntityStore>, NPCEntity> npcPair = NPCPlugin.get()
|
||||
.spawnEntity(store, npcRoleIndex, spawningContext.newPosition(), Vector3f.ZERO, null, null);
|
||||
if (npcPair == null) {
|
||||
resident.setPersistentRef(null);
|
||||
resident.setDeployedToWorld(false);
|
||||
@@ -288,40 +296,45 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureNoResidentsInWorld(Store<EntityStore> store) {
|
||||
ArrayList<CoopBlock.CoopResident> residentsToRemove = new ArrayList<>();
|
||||
public void ensureNoResidentsInWorld(@Nonnull Store<EntityStore> store) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
ObjectArrayList<CoopBlock.CoopResident> residentsToRemove = new ObjectArrayList<>();
|
||||
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
boolean deployed = resident.getDeployedToWorld();
|
||||
PersistentRef entityUuid = resident.getPersistentRef();
|
||||
if (deployed || entityUuid != null) {
|
||||
Ref<EntityStore> entityRef = entityUuid.getEntity(store);
|
||||
if (entityRef == null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
|
||||
if (coopResidentComponent == null) {
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
boolean deployed = resident.getDeployedToWorld();
|
||||
PersistentRef entityUuid = resident.getPersistentRef();
|
||||
if (deployed || entityUuid != null) {
|
||||
Ref<EntityStore> entityRef = entityUuid.getEntity(store);
|
||||
if (entityRef == null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
DeathComponent deathComponent = store.getComponent(entityRef, DeathComponent.getComponentType());
|
||||
if (deathComponent != null) {
|
||||
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
|
||||
if (coopResidentComponent == null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
coopResidentComponent.setMarkedForDespawn(true);
|
||||
resident.setPersistentRef(null);
|
||||
resident.setDeployedToWorld(false);
|
||||
DeathComponent deathComponent = store.getComponent(entityRef, DeathComponent.getComponentType());
|
||||
if (deathComponent != null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else if (!this.getCoopAcceptsNPC(resident.metadata.getNpcNameKey())) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
coopResidentComponent.setMarkedForDespawn(true);
|
||||
resident.setPersistentRef(null);
|
||||
resident.setDeployedToWorld(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (CoopBlock.CoopResident residentx : residentsToRemove) {
|
||||
this.residents.remove(residentx);
|
||||
for (CoopBlock.CoopResident residentx : residentsToRemove) {
|
||||
this.residents.remove(residentx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldResidentsBeInCoop(WorldTimeResource worldTimeResource) {
|
||||
public boolean shouldResidentsBeInCoop(@Nonnull WorldTimeResource worldTimeResource) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return true;
|
||||
@@ -337,7 +350,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Instant getNextScheduledTick(WorldTimeResource worldTimeResource) {
|
||||
public Instant getNextScheduledTick(@Nonnull WorldTimeResource worldTimeResource) {
|
||||
Instant gameTime = worldTimeResource.getGameTime();
|
||||
LocalDateTime gameDateTime = worldTimeResource.getGameDateTime();
|
||||
int gameHour = worldTimeResource.getCurrentHour();
|
||||
@@ -366,7 +379,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleResidentDespawn(UUID entityUuid) {
|
||||
public void handleResidentDespawn(@Nonnull UUID entityUuid) {
|
||||
CoopBlock.CoopResident removedResident = null;
|
||||
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
@@ -381,7 +394,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleBlockBroken(World world, WorldTimeResource worldTimeResource, Store<EntityStore> store, int blockX, int blockY, int blockZ) {
|
||||
public void handleBlockBroken(
|
||||
@Nonnull World world, @Nonnull WorldTimeResource worldTimeResource, @Nonnull Store<EntityStore> store, int blockX, int blockY, int blockZ
|
||||
) {
|
||||
Vector3i location = new Vector3i(blockX, blockY, blockZ);
|
||||
world.execute(() -> this.ensureSpawnResidentsInWorld(world, store, location.toVector3d(), new Vector3d().assign(Vector3d.FORWARD)));
|
||||
this.generateProduceToInventory(worldTimeResource);
|
||||
@@ -416,6 +431,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
public static class CoopResident {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CoopBlock.CoopResident> CODEC = BuilderCodec.builder(CoopBlock.CoopResident.class, CoopBlock.CoopResident::new)
|
||||
.append(new KeyedCodec<>("Metadata", CapturedNPCMetadata.CODEC), (coop, meta) -> coop.metadata = meta, coop -> coop.metadata)
|
||||
.add()
|
||||
@@ -439,7 +455,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
public CoopResident() {
|
||||
}
|
||||
|
||||
public CoopResident(CapturedNPCMetadata metadata, PersistentRef persistentRef, Instant lastProduced) {
|
||||
public CoopResident(CapturedNPCMetadata metadata, @Nullable PersistentRef persistentRef, @Nonnull Instant lastProduced) {
|
||||
this.metadata = metadata;
|
||||
this.persistentRef = persistentRef;
|
||||
this.lastProduced = lastProduced;
|
||||
|
||||
@@ -8,10 +8,13 @@ import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.ComponentType;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import java.time.Instant;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FarmingBlock implements Component<ChunkStore> {
|
||||
@Nonnull
|
||||
public static final String DEFAULT_STAGE_SET = "Default";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<FarmingBlock> CODEC = BuilderCodec.builder(FarmingBlock.class, FarmingBlock::new)
|
||||
.append(
|
||||
new KeyedCodec<>("CurrentStageSet", Codec.STRING),
|
||||
@@ -56,13 +59,14 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
)
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private String currentStageSet = "Default";
|
||||
private float growthProgress;
|
||||
private Instant lastTickGameTime;
|
||||
private int generation;
|
||||
private String previousBlockType;
|
||||
private float spreadRate = 1.0F;
|
||||
private int executions = 0;
|
||||
private int executions;
|
||||
|
||||
public static ComponentType<ChunkStore, FarmingBlock> getComponentType() {
|
||||
return FarmingPlugin.get().getFarmingBlockComponentType();
|
||||
@@ -72,7 +76,13 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
public FarmingBlock(
|
||||
String currentStageSet, float growthProgress, Instant lastTickGameTime, int generation, String previousBlockType, float spreadRate, int executions
|
||||
@Nonnull String currentStageSet,
|
||||
float growthProgress,
|
||||
Instant lastTickGameTime,
|
||||
int generation,
|
||||
String previousBlockType,
|
||||
float spreadRate,
|
||||
int executions
|
||||
) {
|
||||
this.currentStageSet = currentStageSet;
|
||||
this.growthProgress = growthProgress;
|
||||
@@ -83,11 +93,12 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
this.executions = executions;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getCurrentStageSet() {
|
||||
return this.currentStageSet;
|
||||
}
|
||||
|
||||
public void setCurrentStageSet(String currentStageSet) {
|
||||
public void setCurrentStageSet(@Nullable String currentStageSet) {
|
||||
this.currentStageSet = currentStageSet != null ? currentStageSet : "Default";
|
||||
}
|
||||
|
||||
@@ -147,6 +158,7 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FarmingBlock{currentStageSet='"
|
||||
|
||||
@@ -13,7 +13,7 @@ import javax.annotation.Nullable;
|
||||
@Deprecated(forRemoval = true)
|
||||
public class FarmingBlockState implements Component<ChunkStore> {
|
||||
@Nonnull
|
||||
public static BuilderCodec<FarmingBlockState> CODEC = BuilderCodec.builder(FarmingBlockState.class, FarmingBlockState::new)
|
||||
public static final BuilderCodec<FarmingBlockState> CODEC = BuilderCodec.builder(FarmingBlockState.class, FarmingBlockState::new)
|
||||
.append(new KeyedCodec<>("BaseCrop", Codec.STRING), (state, crop) -> state.baseCrop = crop, state -> state.baseCrop)
|
||||
.add()
|
||||
.append(new KeyedCodec<>("StageStart", Codec.INSTANT), (state, start) -> state.stageStart = start, state -> state.stageStart)
|
||||
|
||||
@@ -13,10 +13,12 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TilledSoilBlock implements Component<ChunkStore> {
|
||||
public static int VERSION = 1;
|
||||
@Nonnull
|
||||
public static final BuilderCodec<TilledSoilBlock> CODEC = BuilderCodec.builder(TilledSoilBlock.class, TilledSoilBlock::new)
|
||||
.versioned()
|
||||
.codecVersion(VERSION)
|
||||
@@ -116,7 +118,8 @@ public class TilledSoilBlock implements Component<ChunkStore> {
|
||||
this.decayTime = decayTime;
|
||||
}
|
||||
|
||||
public String computeBlockType(Instant gameTime, BlockType type) {
|
||||
@Nullable
|
||||
public String computeBlockType(@Nonnull Instant gameTime, @Nonnull BlockType type) {
|
||||
boolean watered = this.hasExternalWater() || this.wateredUntil != null && this.wateredUntil.isAfter(gameTime);
|
||||
if (this.fertilized && watered) {
|
||||
return type.getBlockKeyForState("Fertilized_Watered");
|
||||
@@ -127,6 +130,7 @@ public class TilledSoilBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TilledSoilBlock{planted="
|
||||
|
||||
@@ -11,7 +11,9 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesGameplayConfig {
|
||||
@Nonnull
|
||||
public static final String ID = "Memories";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesGameplayConfig> CODEC = BuilderCodec.builder(MemoriesGameplayConfig.class, MemoriesGameplayConfig::new)
|
||||
.appendInherited(
|
||||
new KeyedCodec<>("MemoriesAmountPerLevel", Codec.INT_ARRAY),
|
||||
|
||||
@@ -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;
|
||||
@@ -69,9 +70,14 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesPlugin extends JavaPlugin {
|
||||
@Nonnull
|
||||
public static final String MEMORIES_JSON_PATH = "memories.json";
|
||||
private static MemoriesPlugin instance;
|
||||
@Nonnull
|
||||
private final Config<MemoriesPlugin.MemoriesPluginConfig> config = this.withConfig(MemoriesPlugin.MemoriesPluginConfig.CODEC);
|
||||
@Nonnull
|
||||
private final List<MemoryProvider<?>> providers = new ObjectArrayList<>();
|
||||
@Nonnull
|
||||
private final Map<String, Set<Memory>> allMemories = new Object2ObjectRBTreeMap<>();
|
||||
private ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType;
|
||||
@Nullable
|
||||
@@ -95,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();
|
||||
@@ -105,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);
|
||||
}
|
||||
|
||||
@@ -169,6 +182,7 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
this.providers.add(memoryProvider);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<String, Set<Memory>> getAllMemories() {
|
||||
return this.allMemories;
|
||||
}
|
||||
@@ -299,6 +313,7 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
public static class MemoriesPluginConfig {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesPlugin.MemoriesPluginConfig> CODEC = BuilderCodec.builder(
|
||||
MemoriesPlugin.MemoriesPluginConfig.class, MemoriesPlugin.MemoriesPluginConfig::new
|
||||
)
|
||||
@@ -321,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
|
||||
@@ -339,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));
|
||||
@@ -361,6 +393,7 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
private static class RecordedMemories {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesPlugin.RecordedMemories> CODEC = BuilderCodec.builder(
|
||||
MemoriesPlugin.RecordedMemories.class, MemoriesPlugin.RecordedMemories::new
|
||||
)
|
||||
@@ -371,7 +404,9 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
}, recordedMemories -> recordedMemories.memories.toArray(Memory[]::new))
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
@Nonnull
|
||||
private final Set<Memory> memories = new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class PlayerMemories implements Component<EntityStore> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<PlayerMemories> CODEC = BuilderCodec.builder(PlayerMemories.class, PlayerMemories::new)
|
||||
.append(
|
||||
new KeyedCodec<>("Capacity", Codec.INTEGER),
|
||||
@@ -29,6 +30,7 @@ public class PlayerMemories implements Component<EntityStore> {
|
||||
}, playerMemories -> playerMemories.memories.toArray(Memory[]::new))
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private final Set<Memory> memories = new LinkedHashSet<>();
|
||||
private int memoriesCapacity;
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ public class MemoriesConditionInteraction extends Interaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configurePacket(com.hypixel.hytale.protocol.Interaction packet) {
|
||||
protected void configurePacket(@Nonnull com.hypixel.hytale.protocol.Interaction packet) {
|
||||
super.configurePacket(packet);
|
||||
com.hypixel.hytale.protocol.MemoriesConditionInteraction p = (com.hypixel.hytale.protocol.MemoriesConditionInteraction)packet;
|
||||
p.memoriesNext = new Int2IntOpenHashMap(this.next.size());
|
||||
@@ -156,11 +156,9 @@ public class MemoriesConditionInteraction extends Interaction {
|
||||
|
||||
@Override
|
||||
public boolean walk(@Nonnull Collector collector, @Nonnull InteractionContext context) {
|
||||
if (this.next != null) {
|
||||
for (Entry<String> entry : this.next.int2ObjectEntrySet()) {
|
||||
if (InteractionManager.walkInteraction(collector, context, new MemoriesConditionInteraction.MemoriesTag(entry.getIntKey()), entry.getValue())) {
|
||||
return true;
|
||||
}
|
||||
for (Entry<String> entry : this.next.int2ObjectEntrySet()) {
|
||||
if (InteractionManager.walkInteraction(collector, context, new MemoriesConditionInteraction.MemoriesTag(entry.getIntKey()), entry.getValue())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +170,7 @@ public class MemoriesConditionInteraction extends Interaction {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public WaitForDataFrom getWaitForDataFrom() {
|
||||
return WaitForDataFrom.Server;
|
||||
|
||||
@@ -21,6 +21,15 @@ import com.hypixel.hytale.server.core.util.NotificationUtil;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SetMemoriesCapacityInteraction extends SimpleInstantInteraction {
|
||||
@Nonnull
|
||||
private static final String NOTIFICATION_ICON_MEMORIES = "NotificationIcons/MemoriesIcon.png";
|
||||
@Nonnull
|
||||
private static final Message MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_NOTIFICATION = Message.translation(
|
||||
"server.memories.general.featureUnlockedNotification"
|
||||
);
|
||||
@Nonnull
|
||||
private static final Message MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_MESSAGE = Message.translation("server.memories.general.featureUnlockedMessage");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SetMemoriesCapacityInteraction> CODEC = BuilderCodec.builder(
|
||||
SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction::new, SimpleInstantInteraction.CODEC
|
||||
)
|
||||
@@ -48,15 +57,14 @@ public class SetMemoriesCapacityInteraction extends SimpleInstantInteraction {
|
||||
memoriesComponent.setMemoriesCapacity(this.capacity);
|
||||
if (previousCapacity <= 0) {
|
||||
PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
|
||||
|
||||
assert playerRefComponent != null;
|
||||
|
||||
PacketHandler playerConnection = playerRefComponent.getPacketHandler();
|
||||
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(true));
|
||||
NotificationUtil.sendNotification(
|
||||
playerConnection, Message.translation("server.memories.general.featureUnlockedNotification"), null, "NotificationIcons/MemoriesIcon.png"
|
||||
);
|
||||
playerRefComponent.sendMessage(Message.translation("server.memories.general.featureUnlockedMessage"));
|
||||
if (playerRefComponent != null) {
|
||||
PacketHandler playerConnection = playerRefComponent.getPacketHandler();
|
||||
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(true));
|
||||
NotificationUtil.sendNotification(
|
||||
playerConnection, MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_NOTIFICATION, null, "NotificationIcons/MemoriesIcon.png"
|
||||
);
|
||||
playerRefComponent.sendMessage(MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
context.getState().state = InteractionState.Finished;
|
||||
|
||||
@@ -6,6 +6,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class Memory {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<Memory> CODEC = new CodecMapCodec<>();
|
||||
|
||||
public abstract String getId();
|
||||
|
||||
@@ -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;
|
||||
@@ -34,7 +35,6 @@ import com.hypixel.hytale.server.core.modules.entity.component.TransformComponen
|
||||
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
|
||||
import com.hypixel.hytale.server.core.modules.entity.item.PickupItemComponent;
|
||||
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
|
||||
import com.hypixel.hytale.server.core.modules.i18n.I18nModule;
|
||||
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;
|
||||
@@ -53,18 +53,14 @@ public class NPCMemory extends Memory {
|
||||
@Nonnull
|
||||
public static final String ID = "NPC";
|
||||
@Nonnull
|
||||
public static final String ZONE_NAME_UNKNOWN = "???";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<NPCMemory> CODEC = BuilderCodec.builder(NPCMemory.class, NPCMemory::new)
|
||||
.append(new KeyedCodec<>("NPCRole", Codec.STRING), (npcMemory, s) -> npcMemory.npcRole = s, npcMemory -> npcMemory.npcRole)
|
||||
.addValidator(Validators.nonNull())
|
||||
.add()
|
||||
.append(new KeyedCodec<>("TranslationKey", Codec.STRING), (npcMemory, s) -> npcMemory.memoryTitleKey = s, npcMemory -> npcMemory.memoryTitleKey)
|
||||
.add()
|
||||
.append(
|
||||
new KeyedCodec<>("IsMemoriesNameOverridden", Codec.BOOLEAN),
|
||||
(npcMemory, aBoolean) -> npcMemory.isMemoriesNameOverridden = aBoolean,
|
||||
npcMemory -> npcMemory.isMemoriesNameOverridden
|
||||
)
|
||||
.add()
|
||||
.append(
|
||||
new KeyedCodec<>("CapturedTimestamp", Codec.LONG),
|
||||
(npcMemory, aDouble) -> npcMemory.capturedTimestamp = aDouble,
|
||||
@@ -83,10 +79,8 @@ public class NPCMemory extends Memory {
|
||||
npcMemory -> npcMemory.foundLocationGeneralNameKey
|
||||
)
|
||||
.add()
|
||||
.afterDecode(NPCMemory::processConfig)
|
||||
.build();
|
||||
private String npcRole;
|
||||
private boolean isMemoriesNameOverridden;
|
||||
private long capturedTimestamp;
|
||||
private String foundLocationZoneNameKey;
|
||||
private String foundLocationGeneralNameKey;
|
||||
@@ -95,11 +89,9 @@ public class NPCMemory extends Memory {
|
||||
private NPCMemory() {
|
||||
}
|
||||
|
||||
public NPCMemory(@Nonnull String npcRole, @Nonnull String nameTranslationKey, boolean isMemoriesNameOverridden) {
|
||||
public NPCMemory(@Nonnull String npcRole, @Nonnull String nameTranslationKey) {
|
||||
this.npcRole = npcRole;
|
||||
this.memoryTitleKey = nameTranslationKey;
|
||||
this.isMemoriesNameOverridden = isMemoriesNameOverridden;
|
||||
this.processConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,25 +111,12 @@ public class NPCMemory extends Memory {
|
||||
return Message.translation("server.memories.general.discovered.tooltipText");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getIconPath() {
|
||||
return "UI/Custom/Pages/Memories/npcs/" + this.npcRole + ".png";
|
||||
}
|
||||
|
||||
public void processConfig() {
|
||||
if (this.isMemoriesNameOverridden) {
|
||||
this.memoryTitleKey = "server.npcRoles." + this.npcRole + ".name";
|
||||
if (I18nModule.get().getMessage("en-US", this.memoryTitleKey) == null) {
|
||||
this.memoryTitleKey = "server.memories.names." + this.npcRole;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.memoryTitleKey == null || this.memoryTitleKey.isEmpty()) {
|
||||
this.memoryTitleKey = "server.npcRoles." + this.npcRole + ".name";
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Message getUndiscoveredTooltipText() {
|
||||
@@ -157,6 +136,7 @@ public class NPCMemory extends Memory {
|
||||
return this.foundLocationZoneNameKey;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Message getLocationMessage() {
|
||||
if (this.foundLocationGeneralNameKey != null) {
|
||||
return Message.translation(this.foundLocationGeneralNameKey);
|
||||
@@ -166,30 +146,28 @@ public class NPCMemory extends Memory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (o == null || this.getClass() != o.getClass()) {
|
||||
return false;
|
||||
} else if (!super.equals(o)) {
|
||||
return false;
|
||||
} else {
|
||||
NPCMemory npcMemory = (NPCMemory)o;
|
||||
return this.isMemoriesNameOverridden == npcMemory.isMemoriesNameOverridden && Objects.equals(this.npcRole, npcMemory.npcRole);
|
||||
return Objects.equals(this.npcRole, npcMemory.npcRole);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + Objects.hashCode(this.npcRole);
|
||||
return 31 * result + Boolean.hashCode(this.isMemoriesNameOverridden);
|
||||
return 31 * result + Objects.hashCode(this.npcRole);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NPCMemory{npcRole='"
|
||||
+ this.npcRole
|
||||
+ "', isMemoriesNameOverride="
|
||||
+ this.isMemoriesNameOverridden
|
||||
+ "', capturedTimestamp="
|
||||
+ this.capturedTimestamp
|
||||
+ "', foundLocationZoneNameKey='"
|
||||
@@ -199,12 +177,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(), 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;
|
||||
}
|
||||
|
||||
@@ -216,12 +211,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;
|
||||
|
||||
@@ -230,13 +225,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;
|
||||
|
||||
@@ -248,29 +243,22 @@ public class NPCMemory extends Memory {
|
||||
NPCEntity npcComponent = commandBuffer.getComponent(npcRef, NPCEntity.getComponentType());
|
||||
if (npcComponent != null) {
|
||||
Role role = npcComponent.getRole();
|
||||
|
||||
assert role != null;
|
||||
|
||||
if (role.isMemory()) {
|
||||
temp.isMemoriesNameOverridden = role.isMemoriesNameOverriden();
|
||||
temp.npcRole = temp.isMemoriesNameOverridden ? role.getMemoriesNameOverride() : npcComponent.getRoleName();
|
||||
if (role != null && role.isMemory()) {
|
||||
String memoriesNameOverride = role.getMemoriesNameOverride();
|
||||
temp.npcRole = memoriesNameOverride != null && !memoriesNameOverride.isEmpty() ? memoriesNameOverride : npcComponent.getRoleName();
|
||||
temp.memoryTitleKey = role.getNameTranslationKey();
|
||||
temp.capturedTimestamp = System.currentTimeMillis();
|
||||
temp.foundLocationGeneralNameKey = foundLocationZoneNameKey;
|
||||
if (!memoriesPlugin.hasRecordedMemory(temp)) {
|
||||
temp.processConfig();
|
||||
if (playerMemoriesComponent.recordMemory(temp)) {
|
||||
NotificationUtil.sendNotification(
|
||||
playerRefComponent.getPacketHandler(),
|
||||
Message.translation("server.memories.general.collected").param("memoryTitle", Message.translation(temp.getTitle())),
|
||||
null,
|
||||
"NotificationIcons/MemoriesIcon.png"
|
||||
);
|
||||
temp = new NPCMemory();
|
||||
TransformComponent npcTransformComponent = commandBuffer.getComponent(npcRef, TransformComponent.getComponentType());
|
||||
|
||||
assert npcTransformComponent != null;
|
||||
|
||||
if (!memoriesPlugin.hasRecordedMemory(temp) && playerMemoriesComponent.recordMemory(temp)) {
|
||||
NotificationUtil.sendNotification(
|
||||
playerRefComponent.getPacketHandler(),
|
||||
Message.translation("server.memories.general.collected").param("memoryTitle", Message.translation(temp.getTitle())),
|
||||
null,
|
||||
"NotificationIcons/MemoriesIcon.png"
|
||||
);
|
||||
temp = new NPCMemory();
|
||||
TransformComponent npcTransformComponent = commandBuffer.getComponent(npcRef, TransformComponent.getComponentType());
|
||||
if (npcTransformComponent != null) {
|
||||
MemoriesGameplayConfig memoriesGameplayConfig = MemoriesGameplayConfig.get(store.getExternalData().getWorld().getGameplayConfig());
|
||||
if (memoriesGameplayConfig != null) {
|
||||
ItemStack memoryItemStack = new ItemStack(memoriesGameplayConfig.getMemoriesCatchItemId());
|
||||
@@ -301,7 +289,7 @@ public class NPCMemory extends Memory {
|
||||
}
|
||||
}
|
||||
|
||||
private static String findLocationZoneName(World world, Vector3d position) {
|
||||
private static String findLocationZoneName(@Nonnull World world, @Nonnull Vector3d position) {
|
||||
if (world.getChunkStore().getGenerator() instanceof ChunkGenerator generator) {
|
||||
int seed = (int)world.getWorldConfig().getSeed();
|
||||
ZoneBiomeResult result = generator.getZoneBiomeResultAt(seed, MathUtil.floor(position.x), MathUtil.floor(position.z));
|
||||
@@ -320,7 +308,10 @@ public class NPCMemory extends Memory {
|
||||
}
|
||||
|
||||
private static void displayCatchEntityParticles(
|
||||
MemoriesGameplayConfig memoriesGameplayConfig, Vector3d targetPosition, Ref<EntityStore> targetRef, @Nonnull CommandBuffer<EntityStore> commandBuffer
|
||||
@Nonnull MemoriesGameplayConfig memoriesGameplayConfig,
|
||||
@Nonnull Vector3d targetPosition,
|
||||
@Nonnull Ref<EntityStore> targetRef,
|
||||
@Nonnull CommandBuffer<EntityStore> commandBuffer
|
||||
) {
|
||||
ModelParticle particle = memoriesGameplayConfig.getMemoriesCatchEntityParticle();
|
||||
if (particle != null) {
|
||||
@@ -335,10 +326,9 @@ public class NPCMemory extends Memory {
|
||||
|
||||
for (Ref<EntityStore> ref : results) {
|
||||
PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
|
||||
|
||||
assert playerRefComponent != null;
|
||||
|
||||
playerRefComponent.getPacketHandler().write(packet);
|
||||
if (playerRefComponent != null) {
|
||||
playerRefComponent.getPacketHandler().write(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,7 +337,7 @@ public class NPCMemory extends Memory {
|
||||
@Nonnull
|
||||
@Override
|
||||
public Query<EntityStore> getQuery() {
|
||||
return QUERY;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ public class NPCMemoryProvider extends MemoryProvider<NPCMemory> {
|
||||
String translationKey = getNPCNameTranslationKey(builder);
|
||||
NPCMemory memory;
|
||||
if (memoriesNameOverride != null && !memoriesNameOverride.isEmpty()) {
|
||||
memory = new NPCMemory(memoriesNameOverride, translationKey, true);
|
||||
memory = new NPCMemory(memoriesNameOverride, translationKey);
|
||||
} else {
|
||||
memory = new NPCMemory(builderInfo.getKeyName(), translationKey, false);
|
||||
memory = new NPCMemory(builderInfo.getKeyName(), translationKey);
|
||||
}
|
||||
|
||||
allMemories.computeIfAbsent(category, s -> new HashSet<>()).add(memory);
|
||||
|
||||
@@ -34,11 +34,8 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
@@ -50,9 +47,10 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
|
||||
private String currentCategory;
|
||||
@Nullable
|
||||
private Memory selectedMemory;
|
||||
private Vector3d recordMemoriesParticlesPosition;
|
||||
@Nonnull
|
||||
private final Vector3d recordMemoriesParticlesPosition;
|
||||
|
||||
public MemoriesPage(@Nonnull PlayerRef playerRef, BlockPosition blockPosition) {
|
||||
public MemoriesPage(@Nonnull PlayerRef playerRef, @Nonnull BlockPosition blockPosition) {
|
||||
super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction, MemoriesPage.PageEventData.CODEC);
|
||||
this.recordMemoriesParticlesPosition = new Vector3d(blockPosition.x, blockPosition.y, blockPosition.z);
|
||||
}
|
||||
@@ -103,11 +101,11 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
|
||||
commandBuilder.set(selector + "#TotalMemoryCountComplete.Text", String.valueOf(memoriesInCategory.size()));
|
||||
boolean isCategoryComplete = recordedMemoriesCount == memoriesInCategory.size();
|
||||
if (isCategoryComplete) {
|
||||
commandBuilder.set(selector + "#CategoryIcon.Background", "Pages/Memories/categories/" + category + "Complete.png");
|
||||
commandBuilder.set(selector + "#CategoryIcon.AssetPath", "UI/Custom/Pages/Memories/categories/" + category + "Complete.png");
|
||||
commandBuilder.set(selector + "#CompleteCategoryBackground.Visible", true);
|
||||
commandBuilder.set(selector + "#CompleteCategoryCounter.Visible", true);
|
||||
} else {
|
||||
commandBuilder.set(selector + "#CategoryIcon.Background", "Pages/Memories/categories/" + category + ".png");
|
||||
commandBuilder.set(selector + "#CategoryIcon.AssetPath", "UI/Custom/Pages/Memories/categories/" + category + ".png");
|
||||
commandBuilder.set(selector + "#NotCompleteCategoryCounter.Visible", true);
|
||||
}
|
||||
|
||||
@@ -356,10 +354,9 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
|
||||
if (memory instanceof NPCMemory npcMemory) {
|
||||
Message locationNameKey = npcMemory.getLocationMessage();
|
||||
long capturedTimestamp = npcMemory.getCapturedTimestamp();
|
||||
String timeString = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(Locale.getDefault())
|
||||
.format(Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC));
|
||||
Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn").param("location", locationNameKey).param("time", timeString);
|
||||
Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn")
|
||||
.param("location", locationNameKey)
|
||||
.param("dateValue", Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC).toString());
|
||||
commandBuilder.set("#MemoryTimeLocation.TextSpans", memoryLocationTimeText);
|
||||
}
|
||||
|
||||
@@ -378,13 +375,18 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
|
||||
MemoriesInfo,
|
||||
SelectMemory;
|
||||
|
||||
@Nonnull
|
||||
public static final Codec<MemoriesPage.PageAction> CODEC = new EnumCodec<>(MemoriesPage.PageAction.class);
|
||||
}
|
||||
|
||||
public static class PageEventData {
|
||||
@Nonnull
|
||||
public static final String KEY_ACTION = "Action";
|
||||
@Nonnull
|
||||
public static final String KEY_CATEGORY = "Category";
|
||||
@Nonnull
|
||||
public static final String KEY_MEMORY_ID = "MemoryId";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesPage.PageEventData> CODEC = BuilderCodec.builder(
|
||||
MemoriesPage.PageEventData.class, MemoriesPage.PageEventData::new
|
||||
)
|
||||
|
||||
@@ -2,17 +2,25 @@ package com.hypixel.hytale.builtin.adventure.memories.page;
|
||||
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.protocol.BlockPosition;
|
||||
import com.hypixel.hytale.server.core.entity.InteractionContext;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
|
||||
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 MemoriesPageSupplier implements OpenCustomUIInteraction.CustomPageSupplier {
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomUIPage tryCreate(Ref<EntityStore> ref, ComponentAccessor<EntityStore> componentAccessor, PlayerRef playerRef, InteractionContext context) {
|
||||
return new MemoriesPage(playerRef, context.getTargetBlock());
|
||||
public CustomUIPage tryCreate(
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
|
||||
@Nonnull PlayerRef playerRef,
|
||||
@Nonnull InteractionContext context
|
||||
) {
|
||||
BlockPosition targetBlock = context.getTargetBlock();
|
||||
return targetBlock == null ? null : new MemoriesPage(playerRef, targetBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,11 +51,14 @@ public class MemoriesUnlockedPage extends InteractiveCustomUIPage<MemoriesUnlock
|
||||
public static enum PageAction {
|
||||
DiscoverMemories;
|
||||
|
||||
@Nonnull
|
||||
public static final Codec<MemoriesUnlockedPage.PageAction> CODEC = new EnumCodec<>(MemoriesUnlockedPage.PageAction.class);
|
||||
}
|
||||
|
||||
public static class PageEventData {
|
||||
@Nonnull
|
||||
public static final String KEY_ACTION = "Action";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesUnlockedPage.PageEventData> CODEC = BuilderCodec.builder(
|
||||
MemoriesUnlockedPage.PageEventData.class, MemoriesUnlockedPage.PageEventData::new
|
||||
)
|
||||
|
||||
@@ -2,17 +2,25 @@ package com.hypixel.hytale.builtin.adventure.memories.page;
|
||||
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.protocol.BlockPosition;
|
||||
import com.hypixel.hytale.server.core.entity.InteractionContext;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
|
||||
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 MemoriesUnlockedPageSuplier implements OpenCustomUIInteraction.CustomPageSupplier {
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomUIPage tryCreate(Ref<EntityStore> ref, ComponentAccessor<EntityStore> componentAccessor, PlayerRef playerRef, InteractionContext context) {
|
||||
return new MemoriesUnlockedPage(playerRef, context.getTargetBlock());
|
||||
public CustomUIPage tryCreate(
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
|
||||
@Nonnull PlayerRef playerRef,
|
||||
@Nonnull InteractionContext context
|
||||
) {
|
||||
BlockPosition targetBlock = context.getTargetBlock();
|
||||
return targetBlock == null ? null : new MemoriesUnlockedPage(playerRef, targetBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.hypixel.hytale.codec.Codec;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ForgottenTempleConfig {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ForgottenTempleConfig> CODEC = BuilderCodec.builder(ForgottenTempleConfig.class, ForgottenTempleConfig::new)
|
||||
.append(new KeyedCodec<>("MinYRespawn", Codec.DOUBLE), (config, o) -> config.minYRespawn = o, config -> config.minYRespawn)
|
||||
.documentation("The Y at which players are teleported back to spawn.")
|
||||
|
||||
@@ -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,13 +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> {
|
||||
public static final Query<EntityStore> QUERY = Query.and(PlayerRef.getComponentType(), TransformComponent.getComponentType());
|
||||
@Nonnull
|
||||
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
|
||||
@@ -39,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;
|
||||
|
||||
@@ -50,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesWindow extends Window {
|
||||
@Nonnull
|
||||
private final JsonObject windowData = new JsonObject();
|
||||
|
||||
public MemoriesWindow() {
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.hypixel.hytale.builtin.adventure.objectives.config.task.UseEntityObje
|
||||
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;
|
||||
@@ -33,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;
|
||||
@@ -56,45 +60,45 @@ public class NPCObjectivesPlugin extends JavaPlugin {
|
||||
@Override
|
||||
protected void setup() {
|
||||
instance = this;
|
||||
ObjectivePlugin.get()
|
||||
.registerTask(
|
||||
"KillSpawnBeacon",
|
||||
KillSpawnBeaconObjectiveTaskAsset.class,
|
||||
KillSpawnBeaconObjectiveTaskAsset.CODEC,
|
||||
KillSpawnBeaconObjectiveTask.class,
|
||||
KillSpawnBeaconObjectiveTask.CODEC,
|
||||
KillSpawnBeaconObjectiveTask::new
|
||||
);
|
||||
ObjectivePlugin.get()
|
||||
.registerTask(
|
||||
"KillSpawnMarker",
|
||||
KillSpawnMarkerObjectiveTaskAsset.class,
|
||||
KillSpawnMarkerObjectiveTaskAsset.CODEC,
|
||||
KillSpawnMarkerObjectiveTask.class,
|
||||
KillSpawnMarkerObjectiveTask.CODEC,
|
||||
KillSpawnMarkerObjectiveTask::new
|
||||
);
|
||||
ObjectivePlugin.get()
|
||||
.registerTask(
|
||||
"Bounty",
|
||||
BountyObjectiveTaskAsset.class,
|
||||
BountyObjectiveTaskAsset.CODEC,
|
||||
BountyObjectiveTask.class,
|
||||
BountyObjectiveTask.CODEC,
|
||||
BountyObjectiveTask::new
|
||||
);
|
||||
ObjectivePlugin.get()
|
||||
.registerTask(
|
||||
"KillNPC",
|
||||
KillObjectiveTaskAsset.class,
|
||||
KillObjectiveTaskAsset.CODEC,
|
||||
KillNPCObjectiveTask.class,
|
||||
KillNPCObjectiveTask.CODEC,
|
||||
KillNPCObjectiveTask::new
|
||||
);
|
||||
this.getEntityStoreRegistry().registerSystem(new SpawnBeaconCheckRemovalSystem());
|
||||
this.killTrackerResourceType = this.getEntityStoreRegistry().registerResource(KillTrackerResource.class, KillTrackerResource::new);
|
||||
this.getEntityStoreRegistry().registerSystem(new KillTrackerSystem());
|
||||
ObjectivePlugin objectivePlugin = ObjectivePlugin.get();
|
||||
ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
|
||||
objectivePlugin.registerTask(
|
||||
"KillSpawnBeacon",
|
||||
KillSpawnBeaconObjectiveTaskAsset.class,
|
||||
KillSpawnBeaconObjectiveTaskAsset.CODEC,
|
||||
KillSpawnBeaconObjectiveTask.class,
|
||||
KillSpawnBeaconObjectiveTask.CODEC,
|
||||
KillSpawnBeaconObjectiveTask::new
|
||||
);
|
||||
objectivePlugin.registerTask(
|
||||
"KillSpawnMarker",
|
||||
KillSpawnMarkerObjectiveTaskAsset.class,
|
||||
KillSpawnMarkerObjectiveTaskAsset.CODEC,
|
||||
KillSpawnMarkerObjectiveTask.class,
|
||||
KillSpawnMarkerObjectiveTask.CODEC,
|
||||
KillSpawnMarkerObjectiveTask::new
|
||||
);
|
||||
objectivePlugin.registerTask(
|
||||
"Bounty",
|
||||
BountyObjectiveTaskAsset.class,
|
||||
BountyObjectiveTaskAsset.CODEC,
|
||||
BountyObjectiveTask.class,
|
||||
BountyObjectiveTask.CODEC,
|
||||
BountyObjectiveTask::new
|
||||
);
|
||||
objectivePlugin.registerTask(
|
||||
"KillNPC",
|
||||
KillObjectiveTaskAsset.class,
|
||||
KillObjectiveTaskAsset.CODEC,
|
||||
KillNPCObjectiveTask.class,
|
||||
KillNPCObjectiveTask.CODEC,
|
||||
KillNPCObjectiveTask::new
|
||||
);
|
||||
this.killTrackerResourceType = entityStoreRegistry.registerResource(KillTrackerResource.class, KillTrackerResource::new);
|
||||
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)
|
||||
@@ -114,48 +118,51 @@ public class NPCObjectivesPlugin extends JavaPlugin {
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull UUID npcId, @Nonnull String taskId
|
||||
) {
|
||||
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
|
||||
ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore();
|
||||
Map<String, Set<UUID>> entityObjectiveUUIDs = objectiveDataStore.getEntityTasksForPlayer(uuidComponent.getUuid());
|
||||
if (entityObjectiveUUIDs == null) {
|
||||
if (uuidComponent == null) {
|
||||
return null;
|
||||
} else {
|
||||
Set<UUID> objectiveUUIDsForTaskId = entityObjectiveUUIDs.get(taskId);
|
||||
if (objectiveUUIDsForTaskId == null) {
|
||||
ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore();
|
||||
Map<String, Set<UUID>> entityObjectiveUUIDs = objectiveDataStore.getEntityTasksForPlayer(uuidComponent.getUuid());
|
||||
if (entityObjectiveUUIDs == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (UUID objectiveUUID : objectiveUUIDsForTaskId) {
|
||||
Objective objective = objectiveDataStore.getObjective(objectiveUUID);
|
||||
if (objective != null) {
|
||||
for (ObjectiveTask task : objective.getCurrentTasks()) {
|
||||
if (task instanceof UseEntityObjectiveTask useEntityTask) {
|
||||
UseEntityObjectiveTaskAsset taskAsset = useEntityTask.getAsset();
|
||||
if (taskAsset.getTaskId().equals(taskId)) {
|
||||
if (!useEntityTask.increaseTaskCompletion(store, ref, 1, objective, playerRef, npcId)) {
|
||||
return null;
|
||||
}
|
||||
Set<UUID> objectiveUUIDsForTaskId = entityObjectiveUUIDs.get(taskId);
|
||||
if (objectiveUUIDsForTaskId == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (UUID objectiveUUID : objectiveUUIDsForTaskId) {
|
||||
Objective objective = objectiveDataStore.getObjective(objectiveUUID);
|
||||
if (objective != null) {
|
||||
ObjectiveTask[] currentTasks = objective.getCurrentTasks();
|
||||
if (currentTasks != null) {
|
||||
for (ObjectiveTask task : currentTasks) {
|
||||
if (task instanceof UseEntityObjectiveTask useEntityTask) {
|
||||
UseEntityObjectiveTaskAsset taskAsset = useEntityTask.getAsset();
|
||||
if (taskAsset.getTaskId().equals(taskId)) {
|
||||
if (!useEntityTask.increaseTaskCompletion(store, ref, 1, objective, playerRef, npcId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return taskAsset.getAnimationIdToPlay();
|
||||
return taskAsset.getAnimationIdToPlay();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void startObjective(@Nonnull Ref<EntityStore> playerReference, @Nonnull String taskId, @Nonnull Store<EntityStore> store) {
|
||||
UUIDComponent uuidComponent = store.getComponent(playerReference, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
|
||||
World world = store.getExternalData().getWorld();
|
||||
ObjectivePlugin.get().startObjective(taskId, Set.of(uuidComponent.getUuid()), world.getWorldConfig().getUuid(), null, store);
|
||||
public static void startObjective(@Nonnull Ref<EntityStore> playerRef, @Nonnull String taskId, @Nonnull Store<EntityStore> store) {
|
||||
UUIDComponent uuidComponent = store.getComponent(playerRef, UUIDComponent.getComponentType());
|
||||
if (uuidComponent != null) {
|
||||
World world = store.getExternalData().getWorld();
|
||||
ObjectivePlugin.get().startObjective(taskId, Set.of(uuidComponent.getUuid()), world.getWorldConfig().getUuid(), null, store);
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceType<EntityStore, KillTrackerResource> getKillTrackerResourceType() {
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BountyObjectiveTaskAsset extends ObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BountyObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
BountyObjectiveTaskAsset.class, BountyObjectiveTaskAsset::new, ObjectiveTaskAsset.BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
KillObjectiveTaskAsset.class, KillObjectiveTaskAsset::new, CountObjectiveTaskAsset.CODEC
|
||||
)
|
||||
@@ -45,7 +46,7 @@ public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset {
|
||||
if (!super.matchesAsset0(task)) {
|
||||
return false;
|
||||
} else {
|
||||
return !(task instanceof KillObjectiveTaskAsset) ? false : ((KillObjectiveTaskAsset)task).npcGroupId.equals(this.npcGroupId);
|
||||
return task instanceof KillObjectiveTaskAsset killObjectiveTaskAsset ? killObjectiveTaskAsset.npcGroupId.equals(this.npcGroupId) : false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
KillSpawnBeaconObjectiveTaskAsset.class, KillSpawnBeaconObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC
|
||||
)
|
||||
@@ -56,9 +57,9 @@ public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
if (!super.matchesAsset0(task)) {
|
||||
return false;
|
||||
} else {
|
||||
return !(task instanceof KillSpawnBeaconObjectiveTaskAsset)
|
||||
? false
|
||||
: Arrays.equals((Object[])((KillSpawnBeaconObjectiveTaskAsset)task).spawnBeacons, (Object[])this.spawnBeacons);
|
||||
return task instanceof KillSpawnBeaconObjectiveTaskAsset killSpawnBeaconObjectiveTaskAsset
|
||||
? Arrays.equals((Object[])killSpawnBeaconObjectiveTaskAsset.spawnBeacons, (Object[])this.spawnBeacons)
|
||||
: false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +70,7 @@ public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
}
|
||||
|
||||
public static class ObjectiveSpawnBeacon {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon> CODEC = BuilderCodec.builder(
|
||||
KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon.class, KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon::new
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillSpawnMarkerObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnMarkerObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
KillSpawnMarkerObjectiveTaskAsset.class, KillSpawnMarkerObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC
|
||||
)
|
||||
|
||||
@@ -25,41 +25,42 @@ public class ActionCompleteTask extends ActionPlayAnimation {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
|
||||
Ref<EntityStore> target = role.getStateSupport().getInteractionIterationTarget();
|
||||
boolean targetExists = target != null && !store.getArchetype(target).contains(DeathComponent.getComponentType());
|
||||
Ref<EntityStore> targetRef = role.getStateSupport().getInteractionIterationTarget();
|
||||
boolean targetExists = targetRef != null && targetRef.isValid() && !store.getArchetype(targetRef).contains(DeathComponent.getComponentType());
|
||||
return super.canExecute(ref, role, sensorInfo, dt, store) && targetExists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
|
||||
UUIDComponent parentUuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
|
||||
assert parentUuidComponent != null;
|
||||
|
||||
Ref<EntityStore> targetPlayerReference = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (targetPlayerReference == null) {
|
||||
if (parentUuidComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
PlayerRef targetPlayerRefComponent = store.getComponent(targetPlayerReference, PlayerRef.getComponentType());
|
||||
if (targetPlayerRefComponent == null) {
|
||||
Ref<EntityStore> targetPlayerReference = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (targetPlayerReference == null) {
|
||||
return false;
|
||||
} else {
|
||||
List<String> activeTasks = role.getEntitySupport().getTargetPlayerActiveTasks();
|
||||
String animation = null;
|
||||
if (activeTasks != null) {
|
||||
for (int i = 0; i < activeTasks.size(); i++) {
|
||||
animation = NPCObjectivesPlugin.updateTaskCompletion(
|
||||
store, targetPlayerReference, targetPlayerRefComponent, parentUuidComponent.getUuid(), activeTasks.get(i)
|
||||
);
|
||||
PlayerRef targetPlayerRefComponent = store.getComponent(targetPlayerReference, PlayerRef.getComponentType());
|
||||
if (targetPlayerRefComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
List<String> activeTasks = role.getEntitySupport().getTargetPlayerActiveTasks();
|
||||
String animation = null;
|
||||
if (activeTasks != null) {
|
||||
for (int i = 0; i < activeTasks.size(); i++) {
|
||||
animation = NPCObjectivesPlugin.updateTaskCompletion(
|
||||
store, targetPlayerReference, targetPlayerRefComponent, parentUuidComponent.getUuid(), activeTasks.get(i)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.playAnimation && animation != null) {
|
||||
this.setAnimationId(animation);
|
||||
super.execute(ref, role, sensorInfo, dt, store);
|
||||
}
|
||||
if (this.playAnimation && animation != null) {
|
||||
this.setAnimationId(animation);
|
||||
super.execute(ref, role, sensorInfo, dt, store);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,12 @@ public class ActionStartObjective extends ActionBase {
|
||||
@Override
|
||||
public boolean execute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
|
||||
super.execute(ref, role, sensorInfo, dt, store);
|
||||
NPCObjectivesPlugin.startObjective(role.getStateSupport().getInteractionIterationTarget(), this.objectiveId, store);
|
||||
return true;
|
||||
Ref<EntityStore> interactionIterationTarget = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (interactionIterationTarget == null) {
|
||||
return false;
|
||||
} else {
|
||||
NPCObjectivesPlugin.startObjective(interactionIterationTarget, this.objectiveId, store);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,39 +30,42 @@ public class SensorHasTask extends SensorBase {
|
||||
public boolean matches(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, double dt, @Nonnull Store<EntityStore> store) {
|
||||
if (!super.matches(ref, role, dt, store)) {
|
||||
return false;
|
||||
} else {
|
||||
Ref<EntityStore> target = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (target == null) {
|
||||
return false;
|
||||
} else {
|
||||
Archetype<EntityStore> targetArchetype = store.getArchetype(target);
|
||||
} else if (this.tasksById != null && this.tasksById.length != 0) {
|
||||
Ref<EntityStore> targetRef = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (targetRef != null && targetRef.isValid()) {
|
||||
Archetype<EntityStore> targetArchetype = store.getArchetype(targetRef);
|
||||
if (targetArchetype.contains(DeathComponent.getComponentType())) {
|
||||
return false;
|
||||
} else {
|
||||
UUIDComponent targetUuidComponent = store.getComponent(target, UUIDComponent.getComponentType());
|
||||
UUIDComponent targetUuidComponent = store.getComponent(targetRef, UUIDComponent.getComponentType());
|
||||
if (targetUuidComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
UUID targetUuid = targetUuidComponent.getUuid();
|
||||
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
if (uuidComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
UUID uuid = uuidComponent.getUuid();
|
||||
EntitySupport entitySupport = role.getEntitySupport();
|
||||
boolean match = false;
|
||||
|
||||
assert targetUuidComponent != null;
|
||||
for (String taskById : this.tasksById) {
|
||||
if (NPCObjectivesPlugin.hasTask(targetUuid, uuid, taskById)) {
|
||||
match = true;
|
||||
entitySupport.addTargetPlayerActiveTask(taskById);
|
||||
}
|
||||
}
|
||||
|
||||
UUID targetUuid = targetUuidComponent.getUuid();
|
||||
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
|
||||
UUID uuid = uuidComponent.getUuid();
|
||||
NPCObjectivesPlugin objectiveSystem = NPCObjectivesPlugin.get();
|
||||
EntitySupport entitySupport = role.getEntitySupport();
|
||||
boolean match = false;
|
||||
|
||||
for (String taskById : this.tasksById) {
|
||||
if (NPCObjectivesPlugin.hasTask(targetUuid, uuid, taskById)) {
|
||||
match = true;
|
||||
entitySupport.addTargetPlayerActiveTask(taskById);
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionCompleteTask extends BuilderActionPlayAnimation {
|
||||
@Nonnull
|
||||
protected final BooleanHolder playAnimation = new BooleanHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionStartObjective extends BuilderActionBase {
|
||||
@Nonnull
|
||||
protected final AssetHolder objectiveId = new AssetHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BuilderSensorHasTask extends BuilderSensorBase {
|
||||
@Nonnull
|
||||
protected final StringArrayHolder tasksById = new StringArrayHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveExistsValidator extends AssetValidator {
|
||||
@Nonnull
|
||||
private static final ObjectiveExistsValidator DEFAULT_INSTANCE = new ObjectiveExistsValidator();
|
||||
|
||||
private ObjectiveExistsValidator() {
|
||||
@@ -38,6 +39,7 @@ public class ObjectiveExistsValidator extends AssetValidator {
|
||||
return ObjectiveAsset.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ObjectiveExistsValidator required() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
@@ -10,17 +10,18 @@ import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillTrackerResource implements Resource<EntityStore> {
|
||||
@Nonnull
|
||||
private final List<KillTaskTransaction> killTasks = new ObjectArrayList<>();
|
||||
|
||||
public static ResourceType<EntityStore, KillTrackerResource> getResourceType() {
|
||||
return NPCObjectivesPlugin.get().getKillTrackerResourceType();
|
||||
}
|
||||
|
||||
public void watch(KillTaskTransaction task) {
|
||||
public void watch(@Nonnull KillTaskTransaction task) {
|
||||
this.killTasks.add(task);
|
||||
}
|
||||
|
||||
public void unwatch(KillTaskTransaction task) {
|
||||
public void unwatch(@Nonnull KillTaskTransaction task) {
|
||||
this.killTasks.remove(task);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,35 +3,55 @@ 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;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems;
|
||||
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 entity = store.getComponent(ref, NPCEntity.getComponentType());
|
||||
KillTrackerResource tracker = store.getResource(KillTrackerResource.getResourceType());
|
||||
List<KillTaskTransaction> killTasks = tracker.getKillTasks();
|
||||
int size = killTasks.size();
|
||||
NPCEntity npcEntityComponent = store.getComponent(ref, this.npcEntityComponentType);
|
||||
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
KillTaskTransaction entry = killTasks.get(i);
|
||||
entry.getTask().checkKilledEntity(store, ref, entry.getObjective(), entity, component.getDeathInfo());
|
||||
assert npcEntityComponent != null;
|
||||
|
||||
KillTrackerResource killTrackerResource = store.getResource(this.killTrackerResourceType);
|
||||
List<KillTaskTransaction> killTasks = killTrackerResource.getKillTasks();
|
||||
Damage deathInfo = component.getDeathInfo();
|
||||
if (deathInfo != null) {
|
||||
int size = killTasks.size();
|
||||
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
KillTaskTransaction entry = killTasks.get(i);
|
||||
entry.getTask().checkKilledEntity(store, ref, entry.getObjective(), npcEntityComponent, deathInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.hypixel.hytale.builtin.adventure.npcobjectives.transaction.KillTaskTr
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.Objective;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.config.task.ObjectiveTaskAsset;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.markers.ObjectiveTaskMarker;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.task.ObjectiveTask;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.transaction.RegistrationTransactionRecord;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.transaction.SpawnEntityTransactionRecord;
|
||||
@@ -15,25 +16,29 @@ import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Transform;
|
||||
import com.hypixel.hytale.math.vector.Vector3d;
|
||||
import com.hypixel.hytale.math.vector.Vector3f;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.protocol.packets.worldmap.MapMarker;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.entity.UUIDComponent;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.npc.INonPlayerCharacter;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.core.util.PositionUtil;
|
||||
import com.hypixel.hytale.server.npc.NPCPlugin;
|
||||
import com.hypixel.hytale.server.npc.entities.NPCEntity;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
@Nonnull
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BountyObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
BountyObjectiveTask.class, BountyObjectiveTask::new, ObjectiveTask.BASE_CODEC
|
||||
)
|
||||
@@ -65,36 +70,47 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
return (BountyObjectiveTaskAsset)super.getAsset();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Nullable
|
||||
@Override
|
||||
protected TransactionRecord[] setup0(@Nonnull Objective objective, @Nonnull World world, @Nonnull Store<EntityStore> store) {
|
||||
if (this.serializedTransactionRecords != null) {
|
||||
return RegistrationTransactionRecord.append(this.serializedTransactionRecords, this.eventRegistry);
|
||||
} else {
|
||||
Vector3d objectivePosition = objective.getPosition(store);
|
||||
|
||||
assert objectivePosition != null;
|
||||
|
||||
Vector3i spawnPosition = this.getAsset().getWorldLocationProvider().runCondition(world, objectivePosition.clone().floor().toVector3i());
|
||||
TransactionRecord[] transactionRecords = new TransactionRecord[2];
|
||||
Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair = NPCPlugin.get()
|
||||
.spawnNPC(store, this.getAsset().getNpcId(), null, spawnPosition.toVector3d(), Vector3f.ZERO);
|
||||
Ref<EntityStore> npcReference = npcPair.first();
|
||||
UUIDComponent npcUuidComponent = store.getComponent(npcReference, UUIDComponent.getComponentType());
|
||||
|
||||
assert npcUuidComponent != null;
|
||||
|
||||
UUID npcUuid = npcUuidComponent.getUuid();
|
||||
ObjectivePlugin.get().getLogger().at(Level.INFO).log("Spawned Entity '" + this.getAsset().getNpcId() + "' at position: " + spawnPosition);
|
||||
transactionRecords[0] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), npcUuid);
|
||||
this.entityUuid = npcUuid;
|
||||
this.addMarker(
|
||||
new MapMarker(getBountyMarkerIDFromUUID(npcUuid), "Bounty Target", "Home.png", PositionUtil.toTransformPacket(new Transform(spawnPosition)), null)
|
||||
);
|
||||
KillTaskTransaction transaction = new KillTaskTransaction(this, objective, store);
|
||||
store.getResource(KillTrackerResource.getResourceType()).watch(transaction);
|
||||
transactionRecords[1] = transaction;
|
||||
return transactionRecords;
|
||||
if (objectivePosition == null) {
|
||||
return null;
|
||||
} else {
|
||||
Vector3i spawnPosition = this.getAsset().getWorldLocationProvider().runCondition(world, objectivePosition.clone().floor().toVector3i());
|
||||
if (spawnPosition == null) {
|
||||
return null;
|
||||
} else {
|
||||
TransactionRecord[] transactionRecords = new TransactionRecord[2];
|
||||
String npcId = this.getAsset().getNpcId();
|
||||
Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair = NPCPlugin.get().spawnNPC(store, npcId, null, spawnPosition.toVector3d(), Vector3f.ZERO);
|
||||
if (npcPair == null) {
|
||||
return null;
|
||||
} else {
|
||||
Ref<EntityStore> npcReference = npcPair.first();
|
||||
UUIDComponent npcUuidComponent = store.getComponent(npcReference, UUIDComponent.getComponentType());
|
||||
if (npcUuidComponent == null) {
|
||||
return null;
|
||||
} else {
|
||||
UUID npcUuid = npcUuidComponent.getUuid();
|
||||
ObjectivePlugin.get().getLogger().at(Level.INFO).log("Spawned Entity '" + npcId + "' at position: " + spawnPosition);
|
||||
transactionRecords[0] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), npcUuid);
|
||||
this.entityUuid = npcUuid;
|
||||
ObjectiveTaskMarker marker = new ObjectiveTaskMarker(
|
||||
getBountyMarkerIDFromUUID(npcUuid), new Transform(spawnPosition), "Home.png", Message.translation("server.objectives.bounty.marker")
|
||||
);
|
||||
this.addMarker(marker);
|
||||
KillTaskTransaction transaction = new KillTaskTransaction(this, objective, store);
|
||||
store.getResource(KillTrackerResource.getResourceType()).watch(transaction);
|
||||
transactionRecords[1] = transaction;
|
||||
return transactionRecords;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +126,7 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
|
||||
@Override
|
||||
public void checkKilledEntity(
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> npcRef, @Nonnull Objective objective, NPCEntity npc, Damage damageInfo
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> npcRef, @Nonnull Objective objective, @Nonnull NPCEntity npc, @Nonnull Damage damageInfo
|
||||
) {
|
||||
UUIDComponent uuidComponent = store.getComponent(npcRef, UUIDComponent.getComponentType());
|
||||
|
||||
@@ -129,7 +145,8 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
@Nonnull
|
||||
public com.hypixel.hytale.protocol.ObjectiveTask toPacket(@Nonnull Objective objective) {
|
||||
com.hypixel.hytale.protocol.ObjectiveTask packet = new com.hypixel.hytale.protocol.ObjectiveTask();
|
||||
packet.taskDescriptionKey = this.asset.getDescriptionKey(objective.getObjectiveId(), this.taskSetIndex, this.taskIndex);
|
||||
packet.taskDescriptionKey = Message.translation(this.asset.getDescriptionKey(objective.getObjectiveId(), this.taskSetIndex, this.taskIndex))
|
||||
.getFormattedMessage();
|
||||
packet.currentCompletion = this.completed ? 1 : 0;
|
||||
packet.completionNeeded = 1;
|
||||
return packet;
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillNPCObjectiveTask extends KillObjectiveTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillNPCObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
KillNPCObjectiveTask.class, KillNPCObjectiveTask::new, KillObjectiveTask.CODEC
|
||||
)
|
||||
|
||||
@@ -8,8 +8,6 @@ import com.hypixel.hytale.builtin.tagset.config.NPCGroup;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.entity.Entity;
|
||||
import com.hypixel.hytale.server.core.entity.EntityUtils;
|
||||
import com.hypixel.hytale.server.core.entity.UUIDComponent;
|
||||
import com.hypixel.hytale.server.core.entity.entities.Player;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
|
||||
@@ -18,6 +16,7 @@ import com.hypixel.hytale.server.npc.entities.NPCEntity;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class KillObjectiveTask extends CountObjectiveTask implements KillTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillObjectiveTask> CODEC = BuilderCodec.abstractBuilder(KillObjectiveTask.class, CountObjectiveTask.CODEC).build();
|
||||
|
||||
public KillObjectiveTask(@Nonnull KillObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) {
|
||||
@@ -41,16 +40,14 @@ public abstract class KillObjectiveTask extends CountObjectiveTask implements Ki
|
||||
if (index == Integer.MIN_VALUE) {
|
||||
throw new IllegalArgumentException("Unknown npc group! " + key);
|
||||
} else if (TagSetPlugin.get(NPCGroup.class).tagInSet(index, npc.getNPCTypeIndex())) {
|
||||
if (info.getSource() instanceof Damage.EntitySource) {
|
||||
Ref<EntityStore> attackerEntityRef = ((Damage.EntitySource)info.getSource()).getRef();
|
||||
Entity attackerEntity = EntityUtils.getEntity(attackerEntityRef, attackerEntityRef.getStore());
|
||||
if (attackerEntity instanceof Player) {
|
||||
UUIDComponent attackerUuidComponent = store.getComponent(attackerEntityRef, UUIDComponent.getComponentType());
|
||||
|
||||
assert attackerUuidComponent != null;
|
||||
|
||||
if (objective.getActivePlayerUUIDs().contains(attackerUuidComponent.getUuid())) {
|
||||
this.increaseTaskCompletion(store, npcRef, 1, objective);
|
||||
if (info.getSource() instanceof Damage.EntitySource entitySource) {
|
||||
Ref var11 = entitySource.getRef();
|
||||
if (store.getArchetype(var11).contains(Player.getComponentType())) {
|
||||
UUIDComponent sourceUuidComponent = store.getComponent(var11, UUIDComponent.getComponentType());
|
||||
if (sourceUuidComponent != null) {
|
||||
if (objective.getActivePlayerUUIDs().contains(sourceUuidComponent.getUuid())) {
|
||||
this.increaseTaskCompletion(store, npcRef, 1, objective);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Vector3d;
|
||||
import com.hypixel.hytale.math.vector.Vector3f;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.server.core.entity.UUIDComponent;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
@@ -31,6 +32,7 @@ import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnBeaconObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
KillSpawnBeaconObjectiveTask.class, KillSpawnBeaconObjectiveTask::new, KillObjectiveTask.CODEC
|
||||
)
|
||||
@@ -91,7 +93,12 @@ public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
|
||||
|
||||
WorldLocationProvider worldLocationCondition = spawnBeaconConfig.getWorldLocationProvider();
|
||||
if (worldLocationCondition != null) {
|
||||
spawnPosition = worldLocationCondition.runCondition(world, spawnPosition.toVector3i()).toVector3d();
|
||||
Vector3i potentialSpawnLocation = worldLocationCondition.runCondition(world, spawnPosition.toVector3i());
|
||||
if (potentialSpawnLocation != null) {
|
||||
spawnPosition = potentialSpawnLocation.toVector3d();
|
||||
} else {
|
||||
spawnPosition = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnPosition == null) {
|
||||
@@ -103,11 +110,12 @@ public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
|
||||
);
|
||||
spawnBeaconPair.second().setObjectiveUUID(objective.getObjectiveUUID());
|
||||
UUIDComponent spawnBeaconUuidComponent = componentAccessor.getComponent(spawnBeaconPair.first(), UUIDComponent.getComponentType());
|
||||
|
||||
assert spawnBeaconUuidComponent != null;
|
||||
|
||||
logger.at(Level.INFO).log("Spawned SpawnBeacon '" + spawnBeaconId + "' at position: " + position);
|
||||
transactionRecords[i] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), spawnBeaconUuidComponent.getUuid());
|
||||
if (spawnBeaconUuidComponent == null) {
|
||||
transactionRecords[i] = new WorldTransactionRecord().fail("Failed to retrieve UUID component for spawned beacon " + spawnBeaconId);
|
||||
} else {
|
||||
logger.at(Level.INFO).log("Spawned SpawnBeacon '" + spawnBeaconId + "' at position: " + position);
|
||||
transactionRecords[i] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), spawnBeaconUuidComponent.getUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,13 @@ import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnMarkerObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
KillSpawnMarkerObjectiveTask.class, KillSpawnMarkerObjectiveTask::new, KillObjectiveTask.CODEC
|
||||
)
|
||||
.build();
|
||||
private static final ComponentType<EntityStore, SpawnMarkerEntity> SPAWN_MARKER_COMPONENT_TYPE = SpawnMarkerEntity.getComponentType();
|
||||
@Nonnull
|
||||
private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
|
||||
|
||||
public KillSpawnMarkerObjectiveTask(@Nonnull KillSpawnMarkerObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) {
|
||||
@@ -55,21 +57,17 @@ public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask {
|
||||
String[] spawnMarkerIds = asset.getSpawnMarkerIds();
|
||||
HytaleLogger logger = ObjectivePlugin.get().getLogger();
|
||||
|
||||
for (Ref<EntityStore> entityReference : results) {
|
||||
SpawnMarkerEntity entitySpawnMarkerComponent = store.getComponent(entityReference, SPAWN_MARKER_COMPONENT_TYPE);
|
||||
|
||||
assert entitySpawnMarkerComponent != null;
|
||||
|
||||
String spawnMarkerId = entitySpawnMarkerComponent.getSpawnMarkerId();
|
||||
if (ArrayUtil.contains(spawnMarkerIds, spawnMarkerId)) {
|
||||
world.execute(() -> entitySpawnMarkerComponent.trigger(entityReference, store));
|
||||
logger.at(Level.INFO)
|
||||
.log(
|
||||
"Triggered SpawnMarker '"
|
||||
+ spawnMarkerId
|
||||
+ "' at position: "
|
||||
+ store.getComponent(entityReference, TRANSFORM_COMPONENT_TYPE).getPosition()
|
||||
);
|
||||
for (Ref<EntityStore> ref : results) {
|
||||
SpawnMarkerEntity entitySpawnMarkerComponent = store.getComponent(ref, SPAWN_MARKER_COMPONENT_TYPE);
|
||||
if (entitySpawnMarkerComponent != null) {
|
||||
String spawnMarkerId = entitySpawnMarkerComponent.getSpawnMarkerId();
|
||||
if (ArrayUtil.contains(spawnMarkerIds, spawnMarkerId)) {
|
||||
world.execute(() -> entitySpawnMarkerComponent.trigger(ref, store));
|
||||
TransformComponent transformComponent = store.getComponent(ref, TRANSFORM_COMPONENT_TYPE);
|
||||
if (transformComponent != null) {
|
||||
logger.at(Level.INFO).log("Triggered SpawnMarker '" + spawnMarkerId + "' at position: " + transformComponent.getPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@ import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.npc.entities.NPCEntity;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface KillTask {
|
||||
void checkKilledEntity(Store<EntityStore> var1, Ref<EntityStore> var2, Objective var3, NPCEntity var4, Damage var5);
|
||||
void checkKilledEntity(
|
||||
@Nonnull Store<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull Objective var3, @Nonnull NPCEntity var4, @Nonnull Damage var5
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,16 @@ import java.util.Map.Entry;
|
||||
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(
|
||||
ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType, ComponentType<EntityStore, NPCEntity> npcEntityComponentType
|
||||
@Nonnull ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType,
|
||||
@Nonnull ComponentType<EntityStore, NPCEntity> npcEntityComponentType
|
||||
) {
|
||||
this.reputationGroupComponentType = reputationGroupComponentType;
|
||||
this.npcEntityComponentType = npcEntityComponentType;
|
||||
@@ -38,8 +41,11 @@ public class NPCReputationHolderSystem extends HolderSystem<EntityStore> {
|
||||
|
||||
@Override
|
||||
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
|
||||
NPCEntity npcEntity = holder.getComponent(this.npcEntityComponentType);
|
||||
int npcTypeIndex = npcEntity.getNPCTypeIndex();
|
||||
NPCEntity npcComponent = holder.getComponent(this.npcEntityComponentType);
|
||||
|
||||
assert npcComponent != null;
|
||||
|
||||
int npcTypeIndex = npcComponent.getNPCTypeIndex();
|
||||
|
||||
for (Entry<String, ReputationGroup> reputationEntry : ReputationGroup.getAssetMap().getAssetMap().entrySet()) {
|
||||
for (String npcGroup : reputationEntry.getValue().getNpcGroups()) {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
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;
|
||||
|
||||
@@ -13,7 +19,12 @@ public class NPCReputationPlugin extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
this.getEntityStoreRegistry().registerSystem(new ReputationAttitudeSystem());
|
||||
this.getEntityStoreRegistry().registerSystem(new NPCReputationHolderSystem(ReputationGroupComponent.getComponentType(), NPCEntity.getComponentType()));
|
||||
ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
|
||||
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;
|
||||
@@ -11,14 +12,24 @@ import com.hypixel.hytale.server.npc.blackboard.view.attitude.AttitudeView;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReputationAttitudeSystem extends StoreSystem<EntityStore> {
|
||||
private final ResourceType<EntityStore, Blackboard> resourceType = Blackboard.getResourceType();
|
||||
@Nonnull
|
||||
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 blackboard = store.getResource(this.resourceType);
|
||||
AttitudeView view = blackboard.getView(AttitudeView.class, 0L);
|
||||
view.registerProvider(100, (ref, role, targetRef, accessor) -> {
|
||||
Player playerComponent = store.getComponent(targetRef, Player.getComponentType());
|
||||
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, this.playerComponentType);
|
||||
return playerComponent == null ? null : ReputationPlugin.get().getAttitude(store, targetRef, ref);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ActionOpenBarterShop extends ActionBase {
|
||||
@Nonnull
|
||||
protected final String shopId;
|
||||
|
||||
public ActionOpenBarterShop(@Nonnull BuilderActionOpenBarterShop builder, @Nonnull BuilderSupport support) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ActionOpenShop extends ActionBase {
|
||||
@Nonnull
|
||||
protected final String shopId;
|
||||
|
||||
public ActionOpenShop(@Nonnull BuilderActionOpenShop builder, @Nonnull BuilderSupport support) {
|
||||
@@ -34,15 +35,17 @@ public class ActionOpenShop extends ActionBase {
|
||||
return false;
|
||||
} else {
|
||||
PlayerRef playerRefComponent = store.getComponent(playerReference, PlayerRef.getComponentType());
|
||||
|
||||
assert playerRefComponent != null;
|
||||
|
||||
Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
|
||||
|
||||
assert playerComponent != null;
|
||||
|
||||
playerComponent.getPageManager().openCustomPage(ref, store, new ShopPage(playerRefComponent, this.shopId));
|
||||
return true;
|
||||
if (playerRefComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
|
||||
if (playerComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
playerComponent.getPageManager().openCustomPage(ref, store, new ShopPage(playerRefComponent, this.shopId));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BarterShopExistsValidator extends AssetValidator {
|
||||
@Nonnull
|
||||
private static final BarterShopExistsValidator DEFAULT_INSTANCE = new BarterShopExistsValidator();
|
||||
|
||||
private BarterShopExistsValidator() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ShopExistsValidator extends AssetValidator {
|
||||
@Nonnull
|
||||
private static final ShopExistsValidator DEFAULT_INSTANCE = new ShopExistsValidator();
|
||||
|
||||
private ShopExistsValidator() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionOpenBarterShop extends BuilderActionBase {
|
||||
@Nonnull
|
||||
protected final AssetHolder shopId = new AssetHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionOpenShop extends BuilderActionBase {
|
||||
@Nonnull
|
||||
protected final AssetHolder shopId = new AssetHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -28,8 +28,9 @@ public class ReputationCompletion extends ObjectiveCompletion {
|
||||
Player playerComponent = componentAccessor.getComponent(participantReference, Player.getComponentType());
|
||||
if (playerComponent != null) {
|
||||
UUIDComponent uuidComponent = componentAccessor.getComponent(participantReference, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
if (uuidComponent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String reputationGroupId = asset.getReputationGroupId();
|
||||
int amount = asset.getAmount();
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReputationCompletionAsset extends ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ReputationCompletionAsset> CODEC = BuilderCodec.builder(
|
||||
ReputationCompletionAsset.class, ReputationCompletionAsset::new, ObjectiveCompletionAsset.BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class ReputationObjectiveRewardHistoryData extends ObjectiveRewardHistoryData {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ReputationObjectiveRewardHistoryData> CODEC = BuilderCodec.builder(
|
||||
ReputationObjectiveRewardHistoryData.class, ReputationObjectiveRewardHistoryData::new, ObjectiveRewardHistoryData.BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DialogPage extends InteractiveCustomUIPage<DialogPage.DialogPageEventData> {
|
||||
@Nonnull
|
||||
public static final String LAYOUT = "Pages/DialogPage.ui";
|
||||
private final UseEntityObjectiveTaskAsset.DialogOptions dialogOptions;
|
||||
|
||||
@@ -37,10 +38,13 @@ public class DialogPage extends InteractiveCustomUIPage<DialogPage.DialogPageEve
|
||||
|
||||
public void handleDataEvent(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull DialogPage.DialogPageEventData data) {
|
||||
Player playerComponent = store.getComponent(ref, Player.getComponentType());
|
||||
playerComponent.getPageManager().setPage(ref, store, Page.None);
|
||||
if (playerComponent != null) {
|
||||
playerComponent.getPageManager().setPage(ref, store, Page.None);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DialogPageEventData {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<DialogPage.DialogPageEventData> CODEC = BuilderCodec.builder(
|
||||
DialogPage.DialogPageEventData.class, DialogPage.DialogPageEventData::new
|
||||
)
|
||||
|
||||
@@ -43,6 +43,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class Objective implements NetworkSerializable<com.hypixel.hytale.protocol.Objective> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<Objective> CODEC = BuilderCodec.builder(Objective.class, Objective::new)
|
||||
.append(new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY), (objective, uuid) -> objective.objectiveUUID = uuid, objective -> objective.objectiveUUID)
|
||||
.add()
|
||||
@@ -225,39 +226,47 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
}
|
||||
|
||||
public boolean setupCurrentTasks(@Nonnull Store<EntityStore> store) {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
TransactionRecord[] taskTransactions = task.setup(this, store);
|
||||
if (taskTransactions != null && TransactionUtil.anyFailed(taskTransactions)) {
|
||||
ObjectivePlugin.get()
|
||||
.getLogger()
|
||||
.at(Level.WARNING)
|
||||
.log("Failed to setup objective tasks, transaction records:%s", Arrays.toString((Object[])taskTransactions));
|
||||
if (this.currentTasks == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
TransactionRecord[] taskTransactions = task.setup(this, store);
|
||||
if (taskTransactions != null && TransactionUtil.anyFailed(taskTransactions)) {
|
||||
ObjectivePlugin.get()
|
||||
.getLogger()
|
||||
.at(Level.WARNING)
|
||||
.log("Failed to setup objective tasks, transaction records:%s", Arrays.toString((Object[])taskTransactions));
|
||||
|
||||
for (ObjectiveTask taskSetup : this.currentTasks) {
|
||||
taskSetup.revertTransactionRecords();
|
||||
if (taskSetup == task) {
|
||||
break;
|
||||
for (ObjectiveTask taskSetup : this.currentTasks) {
|
||||
taskSetup.revertTransactionRecords();
|
||||
if (taskSetup == task) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkTaskSetCompletion(@Nonnull Store<EntityStore> store) {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
return false;
|
||||
if (this.currentTasks == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.taskSetComplete(store);
|
||||
return true;
|
||||
this.taskSetComplete(store);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void taskSetComplete(@Nonnull Store<EntityStore> store) {
|
||||
@@ -269,13 +278,12 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
this.taskSetComplete(store);
|
||||
} else {
|
||||
TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(this.toPacket());
|
||||
this.forEachParticipant((participantReference, message, trackOrUpdateObjective) -> {
|
||||
this.forEachParticipant((participantReference, trackOrUpdateObjective) -> {
|
||||
PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
|
||||
if (playerRefComponent != null) {
|
||||
playerRefComponent.sendMessage(message);
|
||||
playerRefComponent.getPacketHandler().writeNoCache(trackOrUpdateObjective);
|
||||
}
|
||||
}, this.getTaskInfoMessage(), trackObjectivePacket);
|
||||
}, trackObjectivePacket);
|
||||
this.checkTaskSetCompletion(store);
|
||||
}
|
||||
} else {
|
||||
@@ -304,28 +312,21 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.revertTransactionRecords();
|
||||
if (this.currentTasks != null) {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.revertTransactionRecords();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.unloadTransactionRecords();
|
||||
if (this.currentTasks != null) {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.unloadTransactionRecords();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Message getTaskInfoMessage() {
|
||||
Message info = Message.translation(this.getCurrentDescription());
|
||||
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
info.insert("\n").insert(task.getInfoMessage(this));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public void reloadObjectiveAsset(@Nonnull Map<String, ObjectiveAsset> reloadedAssets) {
|
||||
ObjectiveTaskAsset[] taskAssets = this.checkPossibleAssetReload(reloadedAssets);
|
||||
if (taskAssets != null) {
|
||||
@@ -404,13 +405,17 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
|
||||
@Nullable
|
||||
private ObjectiveTask findMatchingObjectiveTask(@Nonnull ObjectiveTaskAsset taskAsset) {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
if (objectiveTask.getAsset().matchesAsset(taskAsset)) {
|
||||
return objectiveTask;
|
||||
if (this.currentTasks == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
if (objectiveTask.getAsset().matchesAsset(taskAsset)) {
|
||||
return objectiveTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelReload(@Nonnull ObjectiveTask[] newTasks) {
|
||||
@@ -425,18 +430,20 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
}
|
||||
|
||||
private void revertRemovedTasks(@Nonnull ObjectiveTask[] newTasks) {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
boolean foundMatchingTask = false;
|
||||
if (this.currentTasks != null) {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
boolean foundMatchingTask = false;
|
||||
|
||||
for (ObjectiveTask newTask : newTasks) {
|
||||
if (newTask.equals(objectiveTask)) {
|
||||
foundMatchingTask = true;
|
||||
break;
|
||||
for (ObjectiveTask newTask : newTasks) {
|
||||
if (newTask.equals(objectiveTask)) {
|
||||
foundMatchingTask = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatchingTask) {
|
||||
objectiveTask.revertTransactionRecords();
|
||||
if (!foundMatchingTask) {
|
||||
objectiveTask.revertTransactionRecords();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,7 +470,10 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
for (UUID playerUUID : this.playerUUIDs) {
|
||||
PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
|
||||
if (playerRef != null) {
|
||||
consumer.accept(playerRef.getReference(), t, u);
|
||||
Ref<EntityStore> ref = playerRef.getReference();
|
||||
if (ref != null && ref.isValid()) {
|
||||
consumer.accept(playerRef.getReference(), t, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,8 +524,8 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
ObjectiveAsset objectiveAsset = Objects.requireNonNull(this.getObjectiveAsset());
|
||||
com.hypixel.hytale.protocol.Objective packet = new com.hypixel.hytale.protocol.Objective();
|
||||
packet.objectiveUuid = this.objectiveUUID;
|
||||
packet.objectiveTitleKey = objectiveAsset.getTitleKey();
|
||||
packet.objectiveDescriptionKey = this.getCurrentDescription();
|
||||
packet.objectiveTitleKey = Message.translation(objectiveAsset.getTitleKey()).getFormattedMessage();
|
||||
packet.objectiveDescriptionKey = Message.translation(this.getCurrentDescription()).getFormattedMessage();
|
||||
if (this.objectiveLineHistoryData != null) {
|
||||
packet.objectiveLineId = this.objectiveLineHistoryData.getId();
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ObjectiveDataStore {
|
||||
@Nonnull
|
||||
private final Map<UUID, Objective> objectives = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final Map<UUID, Map<String, Set<UUID>>> entityObjectiveUUIDsPerPlayer = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final DataStore<Objective> dataStore;
|
||||
@Nonnull
|
||||
private final Map<Class<? extends ObjectiveTask>, Set<ObjectiveTaskRef<? extends ObjectiveTask>>> taskRefByType = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final HytaleLogger logger;
|
||||
|
||||
@@ -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;
|
||||
@@ -110,15 +114,20 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class ObjectivePlugin extends JavaPlugin {
|
||||
protected static ObjectivePlugin instance;
|
||||
@Nonnull
|
||||
public static final String OBJECTIVE_LOCATION_MARKER_MODEL_ID = "Objective_Location_Marker";
|
||||
public static final long SAVE_INTERVAL_MINUTES = 5L;
|
||||
@Nonnull
|
||||
private final Map<Class<? extends ObjectiveTaskAsset>, TriFunction<ObjectiveTaskAsset, Integer, Integer, ? extends ObjectiveTask>> taskGenerators = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final Map<Class<? extends ObjectiveCompletionAsset>, Function<ObjectiveCompletionAsset, ? extends ObjectiveCompletion>> completionGenerators = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final Config<ObjectivePlugin.ObjectivePluginConfig> config = this.withConfig(ObjectivePlugin.ObjectivePluginConfig.CODEC);
|
||||
private Model objectiveLocationMarkerModel;
|
||||
private ComponentType<EntityStore, ObjectiveHistoryComponent> objectiveHistoryComponentType;
|
||||
private ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponentType;
|
||||
private ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponentType;
|
||||
@Nullable
|
||||
private ObjectiveDataStore objectiveDataStore;
|
||||
|
||||
public static ObjectivePlugin get() {
|
||||
@@ -137,6 +146,7 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
return this.objectiveLocationMarkerModel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ObjectiveDataStore getObjectiveDataStore() {
|
||||
return this.objectiveDataStore;
|
||||
}
|
||||
@@ -144,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()
|
||||
@@ -185,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
|
||||
);
|
||||
@@ -231,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
|
||||
@@ -280,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() {
|
||||
@@ -305,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(
|
||||
@@ -342,79 +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.sendMessage(objective.getTaskInfoMessage());
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -587,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) {
|
||||
this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, ((UseEntityObjectiveTask)task).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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -728,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(
|
||||
@@ -785,6 +854,8 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
oldModel.getGradientId(),
|
||||
oldModel.getEyeHeight(),
|
||||
oldModel.getCrouchOffset(),
|
||||
oldModel.getSittingOffset(),
|
||||
oldModel.getSleepingOffset(),
|
||||
oldModel.getAnimationSetMap(),
|
||||
oldModel.getCamera(),
|
||||
oldModel.getLight(),
|
||||
@@ -815,43 +886,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -860,33 +935,37 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private void onWorldAdded(AddWorldEvent event) {
|
||||
private void onWorldAdded(@Nonnull AddWorldEvent event) {
|
||||
event.getWorld().getWorldMapManager().addMarkerProvider("objectives", ObjectiveMarkerProvider.INSTANCE);
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
public static class ObjectivePluginConfig {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectivePlugin.ObjectivePluginConfig> CODEC = BuilderCodec.builder(
|
||||
ObjectivePlugin.ObjectivePluginConfig.class, ObjectivePlugin.ObjectivePluginConfig::new
|
||||
)
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.UUID;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TreasureChestState extends ItemContainerState implements BreakValidatedBlockState {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<TreasureChestState> CODEC = BuilderCodec.builder(TreasureChestState.class, TreasureChestState::new, BlockState.BASE_CODEC)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -53,38 +53,36 @@ public class ObjectiveLocationMarkerCommand extends AbstractCommandCollection {
|
||||
protected void execute(
|
||||
@Nonnull CommandContext context, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull World world
|
||||
) {
|
||||
Ref<EntityStore> playerReference = playerRef.getReference();
|
||||
TransformComponent playerTransformComponent = store.getComponent(playerReference, TransformComponent.getComponentType());
|
||||
|
||||
assert playerTransformComponent != null;
|
||||
|
||||
String objectiveLocationMarkerId = this.locationMarkerArg.get(context);
|
||||
if (ObjectiveLocationMarkerAsset.getAssetMap().getAsset(objectiveLocationMarkerId) == null) {
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.notFound").param("id", objectiveLocationMarkerId));
|
||||
context.sendMessage(
|
||||
Message.translation("server.general.failed.didYouMean")
|
||||
.param(
|
||||
"choices",
|
||||
StringUtil.sortByFuzzyDistance(
|
||||
objectiveLocationMarkerId, ObjectiveLocationMarkerAsset.getAssetMap().getAssetMap().keySet(), CommandUtil.RECOMMEND_COUNT
|
||||
)
|
||||
.toString()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
|
||||
holder.addComponent(ObjectiveLocationMarker.getComponentType(), new ObjectiveLocationMarker(objectiveLocationMarkerId));
|
||||
Model model = ObjectivePlugin.get().getObjectiveLocationMarkerModel();
|
||||
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
|
||||
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
|
||||
holder.addComponent(Nameplate.getComponentType(), new Nameplate(objectiveLocationMarkerId));
|
||||
TransformComponent transform = new TransformComponent(playerTransformComponent.getPosition(), playerTransformComponent.getRotation());
|
||||
holder.addComponent(TransformComponent.getComponentType(), transform);
|
||||
holder.ensureComponent(UUIDComponent.getComponentType());
|
||||
holder.ensureComponent(Intangible.getComponentType());
|
||||
holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType());
|
||||
store.addEntity(holder, AddReason.SPAWN);
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.added").param("id", objectiveLocationMarkerId));
|
||||
TransformComponent playerTransformComponent = store.getComponent(ref, TransformComponent.getComponentType());
|
||||
if (playerTransformComponent != null) {
|
||||
String objectiveLocationMarkerId = this.locationMarkerArg.get(context);
|
||||
if (ObjectiveLocationMarkerAsset.getAssetMap().getAsset(objectiveLocationMarkerId) == null) {
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.notFound").param("id", objectiveLocationMarkerId));
|
||||
context.sendMessage(
|
||||
Message.translation("server.general.failed.didYouMean")
|
||||
.param(
|
||||
"choices",
|
||||
StringUtil.sortByFuzzyDistance(
|
||||
objectiveLocationMarkerId, ObjectiveLocationMarkerAsset.getAssetMap().getAssetMap().keySet(), CommandUtil.RECOMMEND_COUNT
|
||||
)
|
||||
.toString()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
|
||||
holder.addComponent(ObjectiveLocationMarker.getComponentType(), new ObjectiveLocationMarker(objectiveLocationMarkerId));
|
||||
Model model = ObjectivePlugin.get().getObjectiveLocationMarkerModel();
|
||||
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
|
||||
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
|
||||
holder.addComponent(Nameplate.getComponentType(), new Nameplate(objectiveLocationMarkerId));
|
||||
TransformComponent transform = new TransformComponent(playerTransformComponent.getPosition(), playerTransformComponent.getRotation());
|
||||
holder.addComponent(TransformComponent.getComponentType(), transform);
|
||||
holder.ensureComponent(UUIDComponent.getComponentType());
|
||||
holder.ensureComponent(Intangible.getComponentType());
|
||||
holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType());
|
||||
store.addEntity(holder, AddReason.SPAWN);
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.added").param("id", objectiveLocationMarkerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveHistoryComponent implements Component<EntityStore> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveHistoryComponent> CODEC = BuilderCodec.builder(ObjectiveHistoryComponent.class, ObjectiveHistoryComponent::new)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveHistory", new MapCodec<>(ObjectiveHistoryData.CODEC, Object2ObjectOpenHashMap::new, false)),
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveAsset>> {
|
||||
@Nonnull
|
||||
public static final AssetBuilderCodec<String, ObjectiveAsset> CODEC = AssetBuilderCodec.builder(
|
||||
ObjectiveAsset.class,
|
||||
ObjectiveAsset::new,
|
||||
@@ -87,6 +88,7 @@ public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveAsset::getAssetStore));
|
||||
private static AssetStore<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> ASSET_STORE;
|
||||
protected AssetExtraInfo.Data extraData;
|
||||
|
||||
@@ -79,6 +79,7 @@ public class ObjectiveLineAsset implements JsonAssetWithMap<String, DefaultAsset
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLineAsset::getAssetStore));
|
||||
private static AssetStore<String, ObjectiveLineAsset, DefaultAssetMap<String, ObjectiveLineAsset>> ASSET_STORE;
|
||||
protected AssetExtraInfo.Data extraData;
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> {
|
||||
@Nonnull
|
||||
public static final AssetBuilderCodec<String, ObjectiveLocationMarkerAsset> CODEC = AssetBuilderCodec.builder(
|
||||
ObjectiveLocationMarkerAsset.class,
|
||||
ObjectiveLocationMarkerAsset::new,
|
||||
@@ -74,6 +75,7 @@ public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, De
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLocationMarkerAsset::getAssetStore));
|
||||
private static AssetStore<String, ObjectiveLocationMarkerAsset, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> ASSET_STORE;
|
||||
protected AssetExtraInfo.Data data;
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ClearObjectiveItemsCompletionAsset extends ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ClearObjectiveItemsCompletionAsset> CODEC = BuilderCodec.builder(
|
||||
ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset::new, BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GiveItemsCompletionAsset extends ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<GiveItemsCompletionAsset> CODEC = BuilderCodec.builder(
|
||||
GiveItemsCompletionAsset.class, GiveItemsCompletionAsset::new, BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -5,7 +5,9 @@ import com.hypixel.hytale.codec.lookup.CodecMapCodec;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<ObjectiveCompletionAsset> CODEC = new CodecMapCodec<>("Type");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveCompletionAsset> BASE_CODEC = BuilderCodec.abstractBuilder(ObjectiveCompletionAsset.class).build();
|
||||
|
||||
protected ObjectiveCompletionAsset() {
|
||||
|
||||
@@ -12,7 +12,9 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ObjectiveGameplayConfig {
|
||||
@Nonnull
|
||||
public static final String ID = "Objective";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveGameplayConfig> CODEC = BuilderCodec.builder(ObjectiveGameplayConfig.class, ObjectiveGameplayConfig::new)
|
||||
.appendInherited(
|
||||
new KeyedCodec<>("StarterObjectiveLinePerWorld", new MapCodec<>(Codec.STRING, Object2ObjectOpenHashMap::new, true)),
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveLocationAreaBox> CODEC = BuilderCodec.builder(ObjectiveLocationAreaBox.class, ObjectiveLocationAreaBox::new)
|
||||
.append(
|
||||
new KeyedCodec<>("EntryBox", Box.CODEC),
|
||||
@@ -33,7 +34,9 @@ public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
|
||||
.add()
|
||||
.afterDecode(ObjectiveLocationAreaBox::computeAreaBoxes)
|
||||
.build();
|
||||
@Nonnull
|
||||
private static final Box DEFAULT_ENTRY_BOX = new Box(-5.0, -5.0, -5.0, 5.0, 5.0, 5.0);
|
||||
@Nonnull
|
||||
private static final Box DEFAULT_EXIT_BOX = new Box(-10.0, -10.0, -10.0, 10.0, 10.0, 10.0);
|
||||
private Box entryArea;
|
||||
private Box exitArea;
|
||||
@@ -115,7 +118,7 @@ public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
|
||||
|
||||
private static void getPlayersInArea(
|
||||
@Nonnull SpatialResource<Ref<EntityStore>, EntityStore> spatialComponent,
|
||||
List<Ref<EntityStore>> results,
|
||||
@Nonnull List<Ref<EntityStore>> results,
|
||||
@Nonnull Vector3d markerPosition,
|
||||
@Nonnull Box box
|
||||
) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveLocationAreaRadius extends ObjectiveLocationMarkerArea {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveLocationAreaRadius> CODEC = BuilderCodec.builder(
|
||||
ObjectiveLocationAreaRadius.class, ObjectiveLocationAreaRadius::new
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SetupObjective extends ObjectiveTypeSetup {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SetupObjective> CODEC = BuilderCodec.builder(SetupObjective.class, SetupObjective::new)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveId", Codec.STRING), (setupObjective, s) -> setupObjective.objectiveId = s, setupObjective -> setupObjective.objectiveId
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SetupObjectiveLine extends ObjectiveTypeSetup {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SetupObjectiveLine> CODEC = BuilderCodec.builder(SetupObjectiveLine.class, SetupObjectiveLine::new)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveLineId", Codec.STRING),
|
||||
|
||||
@@ -11,6 +11,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockTagOrItemIdField {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BlockTagOrItemIdField> CODEC = BuilderCodec.builder(BlockTagOrItemIdField.class, BlockTagOrItemIdField::new)
|
||||
.append(
|
||||
new KeyedCodec<>("BlockTag", Codec.STRING),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user