This commit is contained in:
luk
2026-02-17 17:11:46 +00:00
parent 4d608f059c
commit 1c2a87c680
1475 changed files with 32505 additions and 14619 deletions

View File

@@ -7,6 +7,7 @@ import com.hypixel.hytale.logger.sentry.SkipSentryException;
import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.server.core.HytaleServerConfig;
import com.hypixel.hytale.server.core.Options;
import com.hypixel.hytale.server.core.console.ConsoleModule;
import io.sentry.Sentry;
import java.util.Map.Entry;
import java.util.logging.Level;
@@ -19,6 +20,7 @@ public class LateMain {
try {
if (!Options.parse(args)) {
HytaleLogger.init();
ConsoleModule.initializeTerminal();
HytaleFileHandler.INSTANCE.enable();
HytaleLogger.replaceStd();
HytaleLoggerBackend.LOG_LEVEL_LOADER = name -> {

View File

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

View File

@@ -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")
@@ -76,6 +77,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
)
@@ -92,6 +94,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;
@@ -119,6 +122,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
)
@@ -135,6 +139,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;

View File

@@ -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;
@@ -17,17 +17,17 @@ public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<Strin
}
@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) {
@@ -42,7 +42,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()) {

View File

@@ -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;
@@ -19,19 +19,19 @@ public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<Movem
@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);
@@ -44,7 +44,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);

View File

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

View File

@@ -23,12 +23,18 @@ 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() {
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
@@ -40,7 +46,7 @@ public class CameraEffectSystem extends DamageEventSystem {
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return QUERY;
return this.query;
}
public void handle(
@@ -50,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;
@@ -58,7 +64,7 @@ public class CameraEffectSystem extends DamageEventSystem {
if (healthStat != null) {
float health = healthStat.getMax() - healthStat.getMin();
if (!(health <= 0.0F)) {
PlayerRef playerRefComponent = archetypeChunk.getComponent(index, PLAYER_REF_COMPONENT_TYPE);
PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType);
assert playerRefComponent != null;

View File

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

View File

@@ -42,6 +42,7 @@ 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;
@@ -51,7 +52,7 @@ public class FarmingSystems {
public 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 {
@@ -70,38 +71,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() {
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
@@ -115,26 +132,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);
@@ -157,14 +174,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() {
public CoopResidentTicking(@Nonnull ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType) {
this.coopResidentComponentType = coopResidentComponentType;
}
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return componentType;
return this.coopResidentComponentType;
}
@Override
@@ -175,11 +195,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);
}
}
}
@@ -212,35 +233,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() {
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));
}
}
}
@@ -249,150 +282,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() {
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
@@ -401,54 +472,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() {
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);
}
}
@@ -458,17 +542,40 @@ 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() {
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
@@ -479,44 +586,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;
@@ -530,122 +643,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);
@@ -676,15 +795,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;
}
}
}

View File

@@ -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;
@@ -46,19 +47,20 @@ public class FarmingUtil {
}
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())
@@ -93,77 +95,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);
}
}
}
}
@@ -171,22 +175,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) {
@@ -198,7 +202,7 @@ public class FarmingUtil {
meta.setIconPath(modelAsset.getIcon());
}
meta.setRoleIndex(roleIndex);
meta.setNpcNameKey(npcNameKey);
return meta;
}
}
@@ -211,24 +215,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());
@@ -288,7 +287,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);
@@ -305,6 +305,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;
}
}
}
@@ -315,6 +323,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);
}
}
}

View File

@@ -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;
@@ -30,10 +33,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;
}

View File

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

View File

@@ -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
)
@@ -21,17 +23,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;
}
}
}

View File

@@ -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
)
@@ -60,7 +63,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;
@@ -73,19 +76,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) {
@@ -120,6 +130,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
)

View File

@@ -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
)
@@ -87,19 +88,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
);
}
@@ -108,15 +118,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;
@@ -125,31 +148,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);
@@ -159,49 +193,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;

View File

@@ -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)
@@ -32,25 +37,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));
}
}
}
}
}
}

View File

@@ -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)
@@ -33,21 +38,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);
});
}
}
}
}
}

View File

@@ -1,6 +1,5 @@
package com.hypixel.hytale.builtin.adventure.farming.config.stages;
import com.hypixel.hytale.assetstore.AssetPack;
import com.hypixel.hytale.assetstore.AssetRegistry;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlock;
@@ -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(
@@ -80,12 +83,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,
@@ -94,33 +97,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(),
@@ -139,144 +149,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)
);
}
}
);
}
}
}
}
@@ -286,7 +362,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) {
@@ -302,18 +378,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
@@ -329,15 +426,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)
@@ -360,14 +459,12 @@ public class PrefabFarmingStageData extends FarmingStageData {
@Nonnull
public Path getResolvedPath() {
for (AssetPack pack : AssetModule.get().getAssetPacks()) {
Path assetPath = pack.getRoot().resolve("Server").resolve("Prefabs").resolve(this.path);
if (Files.exists(assetPath)) {
return assetPath;
}
Path assetPath = PrefabStore.get().findAssetPrefabPath(this.path);
if (assetPath == null) {
throw new IllegalStateException("Invalid prefab path: " + this.path);
} else {
return assetPath;
}
return PrefabStore.get().getAssetPrefabsPath().resolve(this.path);
}
@Nonnull

View File

@@ -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
)
@@ -95,9 +96,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,
@@ -106,54 +107,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) {
@@ -162,37 +177,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;
}
}
}
@@ -215,7 +251,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(

View File

@@ -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(
@@ -87,50 +87,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);
}

View File

@@ -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)),
@@ -26,9 +29,11 @@ public abstract class SpreadGrowthBehaviour {
public SpreadGrowthBehaviour() {
}
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 {

View File

@@ -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;
public ChangeFarmingStageInteraction() {
}
@@ -273,16 +275,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);

View File

@@ -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
)
@@ -59,40 +60,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;
}
}
}

View File

@@ -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;
public HarvestCropInteraction() {
}
@@ -41,25 +54,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;
}
}
}
}
}

View File

@@ -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
)
@@ -77,20 +79,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);
@@ -98,47 +106,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);
}
}
}
}
@@ -175,46 +192,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 {

View File

@@ -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
)
@@ -46,39 +47,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;
}
}
}

View File

@@ -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
)
@@ -64,45 +65,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;
}
}
}

View File

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

View File

@@ -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='"

View File

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

View File

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

View File

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

View File

@@ -40,6 +40,7 @@ import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.entity.entities.player.windows.Window;
import com.hypixel.hytale.server.core.io.PacketHandler;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.player.PlayerSystems;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
@@ -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
)
@@ -324,9 +339,23 @@ 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() {
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
@@ -345,15 +374,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));
@@ -367,6 +396,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
)
@@ -377,7 +407,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<>();
private RecordedMemories() {

View File

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

View File

@@ -145,7 +145,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());
@@ -159,11 +159,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;
}
}
@@ -175,6 +173,7 @@ public class MemoriesConditionInteraction extends Interaction {
return false;
}
@Nonnull
@Override
public WaitForDataFrom getWaitForDataFrom() {
return WaitForDataFrom.Server;

View File

@@ -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
)
@@ -51,15 +60,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;

View File

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

View File

@@ -13,6 +13,7 @@ import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
@@ -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;
}
}
}

View File

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

View File

@@ -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,6 +375,7 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
MemoriesInfo,
SelectMemory;
@Nonnull
public static final Codec<MemoriesPage.PageAction> CODEC = new EnumCodec<>(MemoriesPage.PageAction.class);
private PageAction() {
@@ -385,9 +383,13 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
}
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
)

View File

@@ -2,11 +2,13 @@ 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 {
@@ -15,7 +17,13 @@ public class MemoriesPageSupplier implements OpenCustomUIInteraction.CustomPageS
@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);
}
}

View File

@@ -51,6 +51,7 @@ public class MemoriesUnlockedPage extends InteractiveCustomUIPage<MemoriesUnlock
public static enum PageAction {
DiscoverMemories;
@Nonnull
public static final Codec<MemoriesUnlockedPage.PageAction> CODEC = new EnumCodec<>(MemoriesUnlockedPage.PageAction.class);
private PageAction() {
@@ -58,7 +59,9 @@ public class MemoriesUnlockedPage extends InteractiveCustomUIPage<MemoriesUnlock
}
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
)

View File

@@ -2,11 +2,13 @@ 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 {
@@ -15,7 +17,13 @@ public class MemoriesUnlockedPageSuplier implements OpenCustomUIInteraction.Cust
@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);
}
}

View File

@@ -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.")

View File

@@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.adventure.memories.temple;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Query;
@@ -18,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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull;
public class BuilderActionCompleteTask extends BuilderActionPlayAnimation {
@Nonnull
protected final BooleanHolder playAnimation = new BooleanHolder();
public BuilderActionCompleteTask() {

View File

@@ -12,6 +12,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull;
public class BuilderActionStartObjective extends BuilderActionBase {
@Nonnull
protected final AssetHolder objectiveId = new AssetHolder();
public BuilderActionStartObjective() {

View File

@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BuilderSensorHasTask extends BuilderSensorBase {
@Nonnull
protected final StringArrayHolder tasksById = new StringArrayHolder();
public BuilderSensorHasTask() {

View File

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

View File

@@ -10,6 +10,7 @@ import java.util.List;
import javax.annotation.Nonnull;
public class KillTrackerResource implements Resource<EntityStore> {
@Nonnull
private final List<KillTaskTransaction> killTasks = new ObjectArrayList<>();
public KillTrackerResource() {
@@ -19,11 +20,11 @@ public class KillTrackerResource implements Resource<EntityStore> {
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);
}

View File

@@ -3,38 +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 {
public KillTrackerSystem() {
@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;
}
@Nullable
@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);
}
}
}
}

View File

@@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.adventure.npcobjectives.systems;
import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.Store;
@@ -11,21 +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> {
public SpawnBeaconCheckRemovalSystem() {
@Nonnull
private final ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType;
public SpawnBeaconCheckRemovalSystem(@Nonnull ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType) {
this.legacySpawnBeaconEntityComponentType = legacySpawnBeaconEntityComponentType;
}
@Nullable
@Nonnull
@Override
public Query<EntityStore> getQuery() {
return LegacySpawnBeaconEntity.getComponentType();
return this.legacySpawnBeaconEntityComponentType;
}
@Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(LegacySpawnBeaconEntity.getComponentType());
LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(this.legacySpawnBeaconEntityComponentType);
assert spawnBeaconComponent != null;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
package com.hypixel.hytale.builtin.adventure.npcreputation;
import com.hypixel.hytale.builtin.adventure.reputation.ReputationPlugin;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.system.StoreSystem;
@@ -11,17 +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() {
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);
});
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,6 +13,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull;
public class BuilderActionOpenBarterShop extends BuilderActionBase {
@Nonnull
protected final AssetHolder shopId = new AssetHolder();
public BuilderActionOpenBarterShop() {

View File

@@ -13,6 +13,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull;
public class BuilderActionOpenShop extends BuilderActionBase {
@Nonnull
protected final AssetHolder shopId = new AssetHolder();
public BuilderActionOpenShop() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -45,10 +45,12 @@ import com.hypixel.hytale.builtin.adventure.objectives.task.ReachLocationTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.TreasureMapObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseBlockObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask;
import com.hypixel.hytale.builtin.weather.components.WeatherTracker;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.common.util.ArrayUtil;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.ResourceType;
@@ -56,6 +58,7 @@ import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.AndQuery;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.function.function.TriFunction;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.protocol.packets.assets.TrackOrUpdateObjective;
@@ -71,7 +74,6 @@ import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
import com.hypixel.hytale.server.core.entity.LivingEntity;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData;
@@ -83,9 +85,11 @@ import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.prefab.PrefabCopyableComponent;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.datastore.DataStoreProvider;
@@ -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
)

View File

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

View File

@@ -76,7 +76,7 @@ public class ObjectiveCompleteCommand extends AbstractCommandCollection {
String objectiveId = this.objectiveArg.get(context);
Objective objective = ObjectiveCompleteCommand.getObjectiveFromId(ref, objectiveId, store);
if (objective == null) {
context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND);
context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND.param("id", objectiveId));
} else {
ObjectiveTask[] tasks = objective.getCurrentTasks();
if (tasks == null) {
@@ -114,7 +114,7 @@ public class ObjectiveCompleteCommand extends AbstractCommandCollection {
int taskIndex = this.taskIndexArg.get(context);
Objective objective = ObjectiveCompleteCommand.getObjectiveFromId(ref, objectiveId, store);
if (objective == null) {
context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND);
context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND.param("id", objectiveId));
} else {
ObjectiveTask[] tasks = objective.getCurrentTasks();
if (taskIndex >= tasks.length) {
@@ -146,7 +146,7 @@ public class ObjectiveCompleteCommand extends AbstractCommandCollection {
String objectiveId = this.objectiveArg.get(context);
Objective objective = ObjectiveCompleteCommand.getObjectiveFromId(ref, objectiveId, store);
if (objective == null) {
context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND);
context.sendMessage(ObjectiveCompleteCommand.MESSAGE_COMMANDS_OBJECTIVE_OBJECTIVE_NOT_FOUND.param("id", objectiveId));
} else {
ObjectiveTask[] tasks = objective.getCurrentTasks();
if (tasks != null && tasks.length != 0) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,6 +9,7 @@ import com.hypixel.hytale.math.vector.Vector3i;
import javax.annotation.Nonnull;
public abstract class CountObjectiveTaskAsset extends ObjectiveTaskAsset {
@Nonnull
public static final BuilderCodec<CountObjectiveTaskAsset> CODEC = BuilderCodec.abstractBuilder(CountObjectiveTaskAsset.class, BASE_CODEC)
.append(new KeyedCodec<>("Count", Codec.INTEGER), (taskAsset, count) -> taskAsset.count = count, taskAsset -> taskAsset.count)
.addValidator(Validators.greaterThan(0))

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