2026.01.29-301e13929
This commit is contained in:
@@ -20,6 +20,7 @@ import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CameraPlugin extends JavaPlugin {
|
||||
@Nonnull
|
||||
private static final String CODEC_CAMERA_SHAKE = "CameraShake";
|
||||
|
||||
public CameraPlugin(@Nonnull JavaPluginInit init) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale.protocol.CameraShakeConfig> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CameraShakeConfig> CODEC = BuilderCodec.builder(CameraShakeConfig.class, CameraShakeConfig::new)
|
||||
.appendInherited(new KeyedCodec<>("Duration", Codec.FLOAT), (o, v) -> o.duration = v, o -> o.duration, (o, p) -> o.duration = p.duration)
|
||||
.documentation("The time period that the camera will shake at full intensity for")
|
||||
@@ -73,6 +74,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
}
|
||||
|
||||
public static class OffsetNoise implements NetworkSerializable<com.hypixel.hytale.protocol.OffsetNoise> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CameraShakeConfig.OffsetNoise> CODEC = BuilderCodec.builder(
|
||||
CameraShakeConfig.OffsetNoise.class, CameraShakeConfig.OffsetNoise::new
|
||||
)
|
||||
@@ -89,6 +91,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
.documentation("The noise used to vary the camera z-offset")
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final CameraShakeConfig.OffsetNoise NONE = new CameraShakeConfig.OffsetNoise();
|
||||
protected NoiseConfig[] x;
|
||||
protected NoiseConfig[] y;
|
||||
@@ -113,6 +116,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
}
|
||||
|
||||
public static class RotationNoise implements NetworkSerializable<com.hypixel.hytale.protocol.RotationNoise> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CameraShakeConfig.RotationNoise> CODEC = BuilderCodec.builder(
|
||||
CameraShakeConfig.RotationNoise.class, CameraShakeConfig.RotationNoise::new
|
||||
)
|
||||
@@ -129,6 +133,7 @@ public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale
|
||||
.documentation("The noise used to vary the camera roll")
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final CameraShakeConfig.RotationNoise NONE = new CameraShakeConfig.RotationNoise();
|
||||
protected NoiseConfig[] pitch;
|
||||
protected NoiseConfig[] yaw;
|
||||
|
||||
@@ -39,7 +39,9 @@ public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<Strin
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected static Packet toCachedPacket(UpdateType type, @Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) {
|
||||
protected static Packet 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()) {
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<Movem
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected static Packet toCachedPacket(UpdateType type, @Nonnull Map<MovementType, ViewBobbing> assets) {
|
||||
protected static Packet toCachedPacket(@Nonnull UpdateType type, @Nonnull Map<MovementType, ViewBobbing> assets) {
|
||||
UpdateViewBobbing packet = new UpdateViewBobbing();
|
||||
packet.type = type;
|
||||
packet.profiles = new EnumMap<>(MovementType.class);
|
||||
|
||||
@@ -80,7 +80,6 @@ public class CameraEffectCommand extends AbstractCommandCollection {
|
||||
}
|
||||
|
||||
protected static class DebugCommand extends AbstractTargetPlayerCommand {
|
||||
private static final String MESSAGE_SUCCESS = "server.commands.camshake.debug.success";
|
||||
@Nonnull
|
||||
protected final RequiredArg<CameraEffect> effectArg = this.withRequiredArg(
|
||||
"effect", "server.commands.camshake.effect.desc", CameraEffectCommand.CAMERA_EFFECT_ARGUMENT_TYPE
|
||||
|
||||
@@ -23,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;
|
||||
@@ -34,6 +35,7 @@ import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
|
||||
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.events.ChunkPreLoadProcessEvent;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
@@ -60,28 +62,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 +100,22 @@ 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);
|
||||
chunkStoreRegistry.registerSystem(new FarmingSystems.OnSoilAdded());
|
||||
chunkStoreRegistry.registerSystem(new FarmingSystems.OnFarmBlockAdded());
|
||||
chunkStoreRegistry.registerSystem(new FarmingSystems.Ticking());
|
||||
chunkStoreRegistry.registerSystem(new FarmingSystems.MigrateFarming());
|
||||
chunkStoreRegistry.registerSystem(new FarmingSystems.OnCoopAdded());
|
||||
entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentEntitySystem());
|
||||
entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentTicking());
|
||||
this.getEventRegistry().registerGlobal(EventPriority.LAST, ChunkPreLoadProcessEvent.class, FarmingPlugin::preventSpreadOnNew);
|
||||
}
|
||||
|
||||
private static void preventSpreadOnNew(ChunkPreLoadProcessEvent event) {
|
||||
private static void preventSpreadOnNew(@Nonnull ChunkPreLoadProcessEvent event) {
|
||||
if (event.isNewlyGenerated()) {
|
||||
BlockComponentChunk components = event.getHolder().getComponent(BlockComponentChunk.getComponentType());
|
||||
if (components != null) {
|
||||
|
||||
@@ -42,13 +42,14 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.core.util.TargetUtil;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FarmingSystems {
|
||||
private static boolean hasCropAbove(BlockChunk blockChunk, int x, int y, int z) {
|
||||
private static boolean hasCropAbove(@Nonnull BlockChunk blockChunk, int x, int y, int z) {
|
||||
if (y + 1 >= 320) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -67,35 +68,42 @@ 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();
|
||||
private static final ComponentType<EntityStore, CoopResidentComponent> COMPONENT_TYPE_COOP_RESIDENT = CoopResidentComponent.getComponentType();
|
||||
|
||||
@Override
|
||||
public Query<EntityStore> getQuery() {
|
||||
return componentType;
|
||||
return COMPONENT_TYPE_COOP_RESIDENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,23 +120,23 @@ public class FarmingSystems {
|
||||
UUIDComponent uuidComponent = commandBuffer.getComponent(ref, UUIDComponent.getComponentType());
|
||||
if (uuidComponent != null) {
|
||||
UUID uuid = uuidComponent.getUuid();
|
||||
CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, componentType);
|
||||
CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, COMPONENT_TYPE_COOP_RESIDENT);
|
||||
if (coopResidentComponent != null) {
|
||||
Vector3i coopPosition = coopResidentComponent.getCoopLocation();
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(coopPosition.x, coopPosition.z);
|
||||
WorldChunk chunk = world.getChunkIfLoaded(chunkIndex);
|
||||
if (chunk != null) {
|
||||
Ref<ChunkStore> chunkReference = world.getChunkStore().getChunkReference(chunkIndex);
|
||||
if (chunkReference != null && chunkReference.isValid()) {
|
||||
WorldChunk worldChunkComponent = world.getChunkIfLoaded(chunkIndex);
|
||||
if (worldChunkComponent != null) {
|
||||
Ref<ChunkStore> chunkRef = world.getChunkStore().getChunkReference(chunkIndex);
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkReference, ChunkColumn.getComponentType());
|
||||
ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkRef, ChunkColumn.getComponentType());
|
||||
if (chunkColumnComponent != null) {
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType());
|
||||
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(coopPosition.y));
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkReference, BlockComponentChunk.getComponentType());
|
||||
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
if (blockComponentChunk != null) {
|
||||
int blockIndexColumn = ChunkUtil.indexBlockInColumn(coopPosition.x, coopPosition.y, coopPosition.z);
|
||||
Ref<ChunkStore> coopEntityReference = blockComponentChunk.getEntityReference(blockIndexColumn);
|
||||
@@ -151,11 +159,11 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class CoopResidentTicking extends EntityTickingSystem<EntityStore> {
|
||||
private static final ComponentType<EntityStore, CoopResidentComponent> componentType = CoopResidentComponent.getComponentType();
|
||||
private static final ComponentType<EntityStore, CoopResidentComponent> COMPONENT_TYPE_COOP_RESIDENT = CoopResidentComponent.getComponentType();
|
||||
|
||||
@Override
|
||||
public Query<EntityStore> getQuery() {
|
||||
return componentType;
|
||||
return COMPONENT_TYPE_COOP_RESIDENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,32 +208,34 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class OnCoopAdded extends RefSystem<ChunkStore> {
|
||||
@Nonnull
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), CoopBlock.getComponentType());
|
||||
|
||||
@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, CoopBlock.getComponentType());
|
||||
|
||||
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, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
assert blockChunk != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
BlockSection blockSection = blockChunk.getSectionAtBlockY(y);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), coopBlock.getNextScheduledTick(worldTimeResource));
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
|
||||
int x = ChunkUtil.xFromBlockInColumn(blockStateInfoComponent.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(blockStateInfoComponent.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(blockStateInfoComponent.getIndex());
|
||||
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
|
||||
if (chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), coopBlockComponent.getNextScheduledTick(worldTimeResource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,43 +244,45 @@ 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, CoopBlock.getComponentType());
|
||||
|
||||
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, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,99 +294,125 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class OnFarmBlockAdded extends RefSystem<ChunkStore> {
|
||||
@Nonnull
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), FarmingBlock.getComponentType());
|
||||
|
||||
@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, FarmingBlock.getComponentType());
|
||||
|
||||
assert farmingBlock != null;
|
||||
assert farmingBlockComponent != null;
|
||||
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
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
|
||||
@@ -391,43 +429,46 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class OnSoilAdded extends RefSystem<ChunkStore> {
|
||||
@Nonnull
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), TilledSoilBlock.getComponentType());
|
||||
|
||||
@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, TilledSoilBlock.getComponentType());
|
||||
|
||||
assert soil != null;
|
||||
assert soilComponent != null;
|
||||
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,6 +486,7 @@ public class FarmingSystems {
|
||||
}
|
||||
|
||||
public static class Ticking extends EntityTickingSystem<ChunkStore> {
|
||||
@Nonnull
|
||||
private static final Query<ChunkStore> QUERY = Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType());
|
||||
|
||||
@Override
|
||||
@@ -455,44 +497,50 @@ public class FarmingSystems {
|
||||
@Nonnull Store<ChunkStore> store,
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||
) {
|
||||
BlockSection blocks = archetypeChunk.getComponent(index, BlockSection.getComponentType());
|
||||
BlockSection blockSectionComponent = archetypeChunk.getComponent(index, BlockSection.getComponentType());
|
||||
|
||||
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, ChunkSection.getComponentType());
|
||||
|
||||
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 farmingBlockComponent = commandBuffer1.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent != null) {
|
||||
FarmingUtil.tickFarming(
|
||||
commandBuffer1, blockChunk, blockSectionComponent, ref, blockRef, farmingBlockComponent, localX, localY, localZ, false
|
||||
);
|
||||
return BlockTickStrategy.SLEEP;
|
||||
} else {
|
||||
TilledSoilBlock soil = commandBuffer1.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null) {
|
||||
tickSoil(commandBuffer1, blockComponentChunk1, blockRef, soil);
|
||||
TilledSoilBlock tilledSoilBlockComponent = commandBuffer1.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilBlockComponent != null) {
|
||||
tickSoil(commandBuffer1, blockRef, tilledSoilBlockComponent);
|
||||
return BlockTickStrategy.SLEEP;
|
||||
} else {
|
||||
CoopBlock coop = commandBuffer1.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coop != null) {
|
||||
tickCoop(commandBuffer1, blockComponentChunk1, blockRef, coop);
|
||||
CoopBlock coopBlockComponent = commandBuffer1.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockComponent != null) {
|
||||
tickCoop(commandBuffer1, blockRef, coopBlockComponent);
|
||||
return BlockTickStrategy.SLEEP;
|
||||
} else {
|
||||
return BlockTickStrategy.IGNORED;
|
||||
@@ -506,122 +554,128 @@ public class FarmingSystems {
|
||||
}
|
||||
}
|
||||
|
||||
private static void tickSoil(
|
||||
CommandBuffer<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, Ref<ChunkStore> blockRef, TilledSoilBlock soilBlock
|
||||
) {
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
private static void tickSoil(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> blockRef, @Nonnull TilledSoilBlock soilBlock) {
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
assert info != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(index);
|
||||
int y = ChunkUtil.yFromBlockInColumn(index);
|
||||
int z = ChunkUtil.zFromBlockInColumn(index);
|
||||
if (y < 320) {
|
||||
assert info.getChunkRef() != null;
|
||||
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunk != null;
|
||||
|
||||
BlockSection blockSection = blockChunk.getSectionAtBlockY(y);
|
||||
boolean hasCrop = FarmingSystems.hasCropAbove(blockChunk, x, y, z);
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockSection.get(x, y, z));
|
||||
Instant currentTime = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType())
|
||||
.getGameTime();
|
||||
Instant decayTime = soilBlock.getDecayTime();
|
||||
if (soilBlock.isPlanted() && !hasCrop) {
|
||||
if (!FarmingSystems.updateSoilDecayTime(commandBuffer, soilBlock, blockType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (decayTime != null) {
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
|
||||
}
|
||||
} else if (!soilBlock.isPlanted() && !hasCrop) {
|
||||
if (decayTime == null || !decayTime.isAfter(currentTime)) {
|
||||
assert info.getChunkRef() != null;
|
||||
|
||||
if (blockType != null && blockType.getFarming() != null && blockType.getFarming().getSoilConfig() != null) {
|
||||
FarmingData.SoilConfig soilConfig = blockType.getFarming().getSoilConfig();
|
||||
String targetBlock = soilConfig.getTargetBlock();
|
||||
if (targetBlock == null) {
|
||||
return;
|
||||
} else {
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
if (targetBlockId == Integer.MIN_VALUE) {
|
||||
return;
|
||||
} else {
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
int rotation = blockSection.getRotationIndex(x, y, z);
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(info.getChunkRef(), WorldChunk.getComponentType());
|
||||
commandBuffer.run(_store -> worldChunk.setBlock(x, y, z, targetBlockId, targetBlockType, rotation, 0, 0));
|
||||
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
|
||||
if (chunkRef.isValid()) {
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent != null) {
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
|
||||
boolean hasCrop = FarmingSystems.hasCropAbove(blockChunkComponent, x, y, z);
|
||||
int blockId = blockSection.get(x, y, z);
|
||||
BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockTypeAsset != null) {
|
||||
Instant currentTime = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType())
|
||||
.getGameTime();
|
||||
Instant decayTime = soilBlock.getDecayTime();
|
||||
if (soilBlock.isPlanted() && !hasCrop) {
|
||||
if (!FarmingSystems.updateSoilDecayTime(commandBuffer, soilBlock, blockTypeAsset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (decayTime != null) {
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
|
||||
}
|
||||
} else if (!soilBlock.isPlanted() && !hasCrop) {
|
||||
if (decayTime == null || !decayTime.isAfter(currentTime)) {
|
||||
if (blockTypeAsset.getFarming() != null && blockTypeAsset.getFarming().getSoilConfig() != null) {
|
||||
FarmingData.SoilConfig soilConfig = blockTypeAsset.getFarming().getSoilConfig();
|
||||
String targetBlock = soilConfig.getTargetBlock();
|
||||
if (targetBlock == null) {
|
||||
return;
|
||||
} else {
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
if (targetBlockId == Integer.MIN_VALUE) {
|
||||
return;
|
||||
} else {
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
int rotationIndex = blockSection.getRotationIndex(x, y, z);
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
commandBuffer.run(_store -> worldChunkComponent.setBlock(x, y, z, targetBlockId, targetBlockType, rotationIndex, 0, 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (hasCrop) {
|
||||
soilBlock.setDecayTime(null);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
|
||||
String targetBlock = soilBlock.computeBlockType(currentTime, blockTypeAsset);
|
||||
if (targetBlock != null && !targetBlock.equals(blockTypeAsset.getId())) {
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
int rotationIndex = blockSection.getRotationIndex(x, y, z);
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
commandBuffer.run(_store -> worldChunkComponent.setBlock(x, y, z, targetBlockId, targetBlockType, rotationIndex, 0, 2));
|
||||
}
|
||||
|
||||
soilBlock.setPlanted(hasCrop);
|
||||
}
|
||||
}
|
||||
} else if (hasCrop) {
|
||||
soilBlock.setDecayTime(null);
|
||||
}
|
||||
|
||||
String targetBlock = soilBlock.computeBlockType(currentTime, blockType);
|
||||
if (targetBlock != null && !targetBlock.equals(blockType.getId())) {
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(info.getChunkRef(), WorldChunk.getComponentType());
|
||||
int rotation = blockSection.getRotationIndex(x, y, z);
|
||||
int targetBlockId = BlockType.getAssetMap().getIndex(targetBlock);
|
||||
BlockType targetBlockType = BlockType.getAssetMap().getAsset(targetBlockId);
|
||||
commandBuffer.run(_store -> worldChunk.setBlock(x, y, z, targetBlockId, targetBlockType, rotation, 0, 2));
|
||||
}
|
||||
|
||||
soilBlock.setPlanted(hasCrop);
|
||||
}
|
||||
}
|
||||
|
||||
private static void tickCoop(
|
||||
CommandBuffer<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, Ref<ChunkStore> blockRef, CoopBlock coopBlock
|
||||
) {
|
||||
BlockModule.BlockStateInfo info = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
private static void tickCoop(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> blockRef, @Nonnull CoopBlock coopBlock) {
|
||||
BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
|
||||
|
||||
assert info != null;
|
||||
assert blockStateInfoComponent != null;
|
||||
|
||||
Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType());
|
||||
FarmingCoopAsset coopAsset = coopBlock.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
|
||||
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
|
||||
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
|
||||
int index = blockStateInfoComponent.getIndex();
|
||||
int x = ChunkUtil.xFromBlockInColumn(index);
|
||||
int y = ChunkUtil.yFromBlockInColumn(index);
|
||||
int z = ChunkUtil.zFromBlockInColumn(index);
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(blockStateInfoComponent.getChunkRef(), BlockChunk.getComponentType());
|
||||
|
||||
assert blockChunk != null;
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
ChunkColumn column = commandBuffer.getComponent(info.getChunkRef(), ChunkColumn.getComponentType());
|
||||
ChunkColumn chunkColumnComponent = commandBuffer.getComponent(blockStateInfoComponent.getChunkRef(), ChunkColumn.getComponentType());
|
||||
|
||||
assert column != null;
|
||||
assert chunkColumnComponent != null;
|
||||
|
||||
Ref<ChunkStore> sectionRef = column.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(y));
|
||||
|
||||
assert sectionRef != null;
|
||||
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert blockSection != null;
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
|
||||
assert chunkSection != null;
|
||||
assert chunkSectionComponent != null;
|
||||
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getZ(), z);
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(worldX, worldZ));
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(worldX, worldZ);
|
||||
WorldChunk chunk = world.getChunkIfInMemory(chunkIndex);
|
||||
double blockRotation = chunk.getRotation(worldX, worldY, worldZ).yaw().getRadians();
|
||||
Vector3d spawnOffset = new Vector3d().assign(coopAsset.getResidentSpawnOffset()).rotateY((float)blockRotation);
|
||||
Vector3i coopLocation = new Vector3i(worldX, worldY, worldZ);
|
||||
@@ -652,7 +706,7 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Farmin
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;
|
||||
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
|
||||
import com.hypixel.hytale.server.core.entity.ItemUtils;
|
||||
import com.hypixel.hytale.server.core.inventory.ItemStack;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.BlockHarvestUtils;
|
||||
@@ -43,19 +44,20 @@ public class FarmingUtil {
|
||||
private static final int BETWEEN_RANDOM = 10;
|
||||
|
||||
public static void tickFarming(
|
||||
CommandBuffer<ChunkStore> commandBuffer,
|
||||
BlockChunk blockChunk,
|
||||
BlockSection blockSection,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
FarmingBlock farmingBlock,
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull BlockChunk blockChunk,
|
||||
@Nonnull BlockSection blockSection,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
@Nonnull FarmingBlock farmingBlock,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
WorldTimeResource worldTimeResource = world.getEntityStore().getStore().getResource(WorldTimeResource.getResourceType());
|
||||
Store<EntityStore> entityStore = world.getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
|
||||
Instant currentTime = worldTimeResource.getGameTime();
|
||||
BlockType blockType = farmingBlock.getPreviousBlockType() != null
|
||||
? BlockType.getAssetMap().getAsset(farmingBlock.getPreviousBlockType())
|
||||
@@ -90,77 +92,79 @@ public class FarmingUtil {
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
} else {
|
||||
long remainingTimeSeconds = currentTime.getEpochSecond() - farmingBlock.getLastTickGameTime().getEpochSecond();
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent != null) {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
|
||||
while (currentStage < stages.length) {
|
||||
FarmingStageData stage = stages[currentStage];
|
||||
if (stage.shouldStop(commandBuffer, sectionRef, blockRef, x, y, z)) {
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGrowthProgress(stages.length);
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
|
||||
Rangef range = stage.getDuration();
|
||||
if (range == null) {
|
||||
blockChunk.markNeedsSaving();
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
|
||||
double rand = HashUtil.random(farmingBlock.getGeneration(), worldX, worldY, worldZ);
|
||||
double baseDuration = range.min + (range.max - range.min) * rand;
|
||||
long remainingDurationSeconds = Math.round(baseDuration * (1.0 - currentProgress % 1.0));
|
||||
double growthMultiplier = 1.0;
|
||||
if (farmingConfig.getGrowthModifiers() != null) {
|
||||
for (String modifierName : farmingConfig.getGrowthModifiers()) {
|
||||
GrowthModifierAsset modifier = GrowthModifierAsset.getAssetMap().getAsset(modifierName);
|
||||
if (modifier != null) {
|
||||
growthMultiplier *= modifier.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainingDurationSeconds = Math.round(remainingDurationSeconds / growthMultiplier);
|
||||
if (remainingTimeSeconds < remainingDurationSeconds) {
|
||||
currentProgress += (float)(remainingTimeSeconds / (baseDuration / growthMultiplier));
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
long nextGrowthInNanos = (remainingDurationSeconds - remainingTimeSeconds) * 1000000000L;
|
||||
long randCap = (long)(
|
||||
(15.0 + 10.0 * HashUtil.random(farmingBlock.getGeneration() ^ 3405692655L, worldX, worldY, worldZ))
|
||||
* world.getTps()
|
||||
* WorldTimeResource.getSecondsPerTick(world)
|
||||
* 1.0E9
|
||||
);
|
||||
long cappedNextGrowthInNanos = Math.min(nextGrowthInNanos, randCap);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), currentTime.plusNanos(cappedNextGrowthInNanos));
|
||||
break;
|
||||
}
|
||||
|
||||
remainingTimeSeconds -= remainingDurationSeconds;
|
||||
currentProgress = ++currentStage;
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGeneration(farmingBlock.getGeneration() + 1);
|
||||
if (currentStage >= stages.length) {
|
||||
if (stages[currentStage - 1].implementsShouldStop()) {
|
||||
currentStage = stages.length - 1;
|
||||
farmingBlock.setGrowthProgress(currentStage);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage]);
|
||||
} else {
|
||||
while (currentStage < stages.length) {
|
||||
FarmingStageData stage = stages[currentStage];
|
||||
if (stage.shouldStop(commandBuffer, sectionRef, blockRef, x, y, z)) {
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGrowthProgress(stages.length);
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
farmingBlock.setExecutions(0);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
farmingBlock.setLastTickGameTime(currentTime);
|
||||
Rangef range = stage.getDuration();
|
||||
if (range == null) {
|
||||
blockChunk.markNeedsSaving();
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
break;
|
||||
}
|
||||
|
||||
double rand = HashUtil.random(farmingBlock.getGeneration(), worldX, worldY, worldZ);
|
||||
double baseDuration = range.min + (range.max - range.min) * rand;
|
||||
long remainingDurationSeconds = Math.round(baseDuration * (1.0 - currentProgress % 1.0));
|
||||
double growthMultiplier = 1.0;
|
||||
if (farmingConfig.getGrowthModifiers() != null) {
|
||||
for (String modifierName : farmingConfig.getGrowthModifiers()) {
|
||||
GrowthModifierAsset modifierAsset = GrowthModifierAsset.getAssetMap().getAsset(modifierName);
|
||||
if (modifierAsset != null) {
|
||||
growthMultiplier *= modifierAsset.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainingDurationSeconds = Math.round(remainingDurationSeconds / growthMultiplier);
|
||||
if (remainingTimeSeconds < remainingDurationSeconds) {
|
||||
currentProgress += (float)(remainingTimeSeconds / (baseDuration / growthMultiplier));
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
long nextGrowthInNanos = (remainingDurationSeconds - remainingTimeSeconds) * 1000000000L;
|
||||
long randCap = (long)(
|
||||
(15.0 + 10.0 * HashUtil.random(farmingBlock.getGeneration() ^ 3405692655L, worldX, worldY, worldZ))
|
||||
* world.getTps()
|
||||
* WorldTimeResource.getSecondsPerTick(world)
|
||||
* 1.0E9
|
||||
);
|
||||
long cappedNextGrowthInNanos = Math.min(nextGrowthInNanos, randCap);
|
||||
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), currentTime.plusNanos(cappedNextGrowthInNanos));
|
||||
break;
|
||||
}
|
||||
|
||||
remainingTimeSeconds -= remainingDurationSeconds;
|
||||
currentProgress = ++currentStage;
|
||||
farmingBlock.setGrowthProgress(currentProgress);
|
||||
blockChunk.markNeedsSaving();
|
||||
farmingBlock.setGeneration(farmingBlock.getGeneration() + 1);
|
||||
if (currentStage >= stages.length) {
|
||||
if (stages[currentStage - 1].implementsShouldStop()) {
|
||||
currentStage = stages.length - 1;
|
||||
farmingBlock.setGrowthProgress(currentStage);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage]);
|
||||
} else {
|
||||
farmingBlock.setGrowthProgress(stages.length);
|
||||
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
|
||||
}
|
||||
} else {
|
||||
farmingBlock.setExecutions(0);
|
||||
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
farmingBlock.setLastTickGameTime(currentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,20 +174,20 @@ public class FarmingUtil {
|
||||
|
||||
public static void 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);
|
||||
harvest0(componentAccessor, ref, blockType, rotationIndex, blockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CapturedNPCMetadata generateCapturedNPCMetadata(
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor, @Nonnull Ref<EntityStore> entityRef, int roleIndex
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor, @Nonnull Ref<EntityStore> entityRef, String npcNameKey
|
||||
) {
|
||||
PersistentModel persistentModel = componentAccessor.getComponent(entityRef, PersistentModel.getComponentType());
|
||||
if (persistentModel == null) {
|
||||
@@ -195,7 +199,7 @@ public class FarmingUtil {
|
||||
meta.setIconPath(modelAsset.getIcon());
|
||||
}
|
||||
|
||||
meta.setRoleIndex(roleIndex);
|
||||
meta.setNpcNameKey(npcNameKey);
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
@@ -285,7 +289,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);
|
||||
@@ -312,6 +317,9 @@ public class FarmingUtil {
|
||||
HarvestingDropType harvest = blockType.getGathering().getHarvest();
|
||||
String itemId = harvest.getItemId();
|
||||
String dropListId = harvest.getDropListId();
|
||||
BlockHarvestUtils.getDrops(blockType, 1, itemId, dropListId).forEach(itemStack -> ItemUtils.interactivelyPickupItem(ref, itemStack, origin, store));
|
||||
|
||||
for (ItemStack itemStack : BlockHarvestUtils.getDrops(blockType, 1, itemId, dropListId)) {
|
||||
ItemUtils.interactivelyPickupItem(ref, itemStack, origin, store);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.ComponentType;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CoopResidentComponent implements Component<EntityStore> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CoopResidentComponent> CODEC = BuilderCodec.builder(CoopResidentComponent.class, CoopResidentComponent::new)
|
||||
.append(new KeyedCodec<>("CoopLocation", Vector3i.CODEC), (comp, ref) -> comp.coopLocation = ref, comp -> comp.coopLocation)
|
||||
.add()
|
||||
@@ -20,6 +22,7 @@ public class CoopResidentComponent implements Component<EntityStore> {
|
||||
)
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private Vector3i coopLocation = new Vector3i();
|
||||
private boolean markedForDespawn;
|
||||
|
||||
@@ -27,10 +30,11 @@ public class CoopResidentComponent implements Component<EntityStore> {
|
||||
return FarmingPlugin.get().getCoopResidentComponentType();
|
||||
}
|
||||
|
||||
public void setCoopLocation(Vector3i coopLocation) {
|
||||
public void setCoopLocation(@Nonnull Vector3i coopLocation) {
|
||||
this.coopLocation = coopLocation;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Vector3i getCoopLocation() {
|
||||
return this.coopLocation;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, FarmingCoopAsset>> {
|
||||
@Nonnull
|
||||
public static final AssetBuilderCodec<String, FarmingCoopAsset> CODEC = AssetBuilderCodec.builder(
|
||||
FarmingCoopAsset.class, FarmingCoopAsset::new, Codec.STRING, (o, v) -> o.id = v, FarmingCoopAsset::getId, (o, data) -> o.data = data, o -> o.data
|
||||
)
|
||||
@@ -87,6 +88,7 @@ public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMa
|
||||
protected int maxResidents;
|
||||
protected Map<String, String> produceDrops = Collections.emptyMap();
|
||||
protected IntRange residentRoamTime;
|
||||
@Nonnull
|
||||
protected Vector3d residentSpawnOffset = new Vector3d();
|
||||
protected String[] acceptedNpcGroupIds;
|
||||
protected int[] acceptedNpcGroupIndexes;
|
||||
@@ -128,6 +130,7 @@ public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMa
|
||||
return this.residentRoamTime;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Vector3d getResidentSpawnOffset() {
|
||||
return this.residentSpawnOffset;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Growth
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class FertilizerGrowthModifierAsset extends GrowthModifierAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<FertilizerGrowthModifierAsset> CODEC = BuilderCodec.builder(
|
||||
FertilizerGrowthModifierAsset.class, FertilizerGrowthModifierAsset::new, ABSTRACT_CODEC
|
||||
)
|
||||
@@ -18,17 +20,37 @@ public class FertilizerGrowthModifierAsset extends GrowthModifierAsset {
|
||||
|
||||
@Override
|
||||
public double getCurrentGrowthMultiplier(
|
||||
CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z, boolean initialTick
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference();
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType());
|
||||
Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z));
|
||||
if (blockRefBelow == null) {
|
||||
return 1.0;
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
|
||||
assert chunkSectionComponent != null;
|
||||
|
||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
if (blockComponentChunk == null) {
|
||||
return 1.0;
|
||||
} else {
|
||||
int chunkIndexBelow = ChunkUtil.indexBlockInColumn(x, y - 1, z);
|
||||
Ref<ChunkStore> blockBelowRef = blockComponentChunk.getEntityReference(chunkIndexBelow);
|
||||
if (blockBelowRef != null && blockBelowRef.isValid()) {
|
||||
TilledSoilBlock belowTilledSoilComponent = commandBuffer.getComponent(blockBelowRef, TilledSoilBlock.getComponentType());
|
||||
return belowTilledSoilComponent != null && belowTilledSoilComponent.isFertilized()
|
||||
? super.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick)
|
||||
: 1.0;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TilledSoilBlock soil = commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType());
|
||||
return soil != null && soil.isFertilized() ? super.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick) : 1.0;
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,15 @@ import com.hypixel.hytale.protocol.Rangef;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;
|
||||
import com.hypixel.hytale.server.core.codec.ProtocolCodecs;
|
||||
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkLightData;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<LightLevelGrowthModifierAsset> CODEC = BuilderCodec.builder(
|
||||
LightLevelGrowthModifierAsset.class, LightLevelGrowthModifierAsset::new, ABSTRACT_CODEC
|
||||
)
|
||||
@@ -57,7 +60,7 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
return isInRange(redRange, red) && isInRange(greenRange, green) && isInRange(blueRange, blue);
|
||||
}
|
||||
|
||||
protected boolean checkSunLight(WorldTimeResource worldTimeResource, byte sky) {
|
||||
protected boolean checkSunLight(@Nonnull WorldTimeResource worldTimeResource, byte sky) {
|
||||
Rangef range = this.sunlight;
|
||||
double sunlightFactor = worldTimeResource.getSunlightFactor();
|
||||
double daylight = sunlightFactor * sky;
|
||||
@@ -70,19 +73,26 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
|
||||
@Override
|
||||
public double getCurrentGrowthMultiplier(
|
||||
CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z, boolean initialTick
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
short lightRaw = blockSection.getGlobalLight().getLightRaw(x, y, z);
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
short lightRaw = blockSectionComponent.getGlobalLight().getLightRaw(x, y, z);
|
||||
byte redLight = ChunkLightData.getLightValue(lightRaw, 0);
|
||||
byte greenLight = ChunkLightData.getLightValue(lightRaw, 1);
|
||||
byte blueLight = ChunkLightData.getLightValue(lightRaw, 2);
|
||||
byte skyLight = ChunkLightData.getLightValue(lightRaw, 3);
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.getEntityStore()
|
||||
.getStore()
|
||||
.getResource(WorldTimeResource.getResourceType());
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
EntityStore entityStore = world.getEntityStore();
|
||||
WorldTimeResource worldTimeResource = entityStore.getStore().getResource(WorldTimeResource.getResourceType());
|
||||
boolean active = false;
|
||||
boolean onlySunlight = false;
|
||||
if (this.requireBoth) {
|
||||
@@ -117,6 +127,7 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
|
||||
}
|
||||
|
||||
public static class ArtificialLight {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<LightLevelGrowthModifierAsset.ArtificialLight> CODEC = BuilderCodec.builder(
|
||||
LightLevelGrowthModifierAsset.ArtificialLight.class, LightLevelGrowthModifierAsset.ArtificialLight::new
|
||||
)
|
||||
|
||||
@@ -28,6 +28,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<WaterGrowthModifierAsset> CODEC = BuilderCodec.builder(
|
||||
WaterGrowthModifierAsset.class, WaterGrowthModifierAsset::new, ABSTRACT_CODEC
|
||||
)
|
||||
@@ -84,19 +85,28 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
|
||||
@Override
|
||||
public double getCurrentGrowthMultiplier(
|
||||
CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z, boolean initialTick
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
boolean initialTick
|
||||
) {
|
||||
boolean hasWaterBlock = this.checkIfWaterSource(commandBuffer, sectionRef, blockRef, x, y, z);
|
||||
boolean hasWaterBlock = this.checkIfWaterSource(commandBuffer, sectionRef, x, y, z);
|
||||
boolean isRaining = this.checkIfRaining(commandBuffer, sectionRef, x, y, z);
|
||||
boolean active = hasWaterBlock || isRaining;
|
||||
TilledSoilBlock soil = getSoil(commandBuffer, sectionRef, x, y, z);
|
||||
if (soil != null) {
|
||||
if (soil.hasExternalWater() != active) {
|
||||
soil.setExternalWater(active);
|
||||
commandBuffer.getComponent(sectionRef, BlockSection.getComponentType()).setTicking(x, y, z, true);
|
||||
BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (blockSectionComponent != null) {
|
||||
blockSectionComponent.setTicking(x, y, z, true);
|
||||
}
|
||||
}
|
||||
|
||||
active |= this.isSoilWaterExpiring(
|
||||
active |= isSoilWaterExpiring(
|
||||
commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()), soil
|
||||
);
|
||||
}
|
||||
@@ -105,15 +115,28 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TilledSoilBlock getSoil(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference();
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType());
|
||||
Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z));
|
||||
return blockRefBelow == null ? null : commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType());
|
||||
private static TilledSoilBlock getSoil(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
return null;
|
||||
} else {
|
||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||
if (chunkRef != null && chunkRef.isValid()) {
|
||||
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkRef, BlockComponentChunk.getComponentType());
|
||||
if (blockComponentChunk == null) {
|
||||
return null;
|
||||
} else {
|
||||
int blockBelowIndex = ChunkUtil.indexBlockInColumn(x, y - 1, z);
|
||||
Ref<ChunkStore> blockBelowRef = blockComponentChunk.getEntityReference(blockBelowIndex);
|
||||
return blockBelowRef == null ? null : commandBuffer.getComponent(blockBelowRef, TilledSoilBlock.getComponentType());
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean checkIfWaterSource(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
protected boolean checkIfWaterSource(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
IntOpenHashSet waterBlocks = this.fluidIds;
|
||||
if (waterBlocks == null) {
|
||||
return false;
|
||||
@@ -122,31 +145,42 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
if (soil == null) {
|
||||
return false;
|
||||
} else {
|
||||
int[] fluids = this.getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z);
|
||||
|
||||
for (int block : fluids) {
|
||||
if (waterBlocks.contains(block)) {
|
||||
return true;
|
||||
int[] fluids = getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z);
|
||||
if (fluids == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (int block : fluids) {
|
||||
if (waterBlocks.contains(block)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getNeighbourFluids(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
return new int[]{
|
||||
this.getFluidAtPos(x - 1, y, z, sectionRef, section, commandBuffer),
|
||||
this.getFluidAtPos(x + 1, y, z, sectionRef, section, commandBuffer),
|
||||
this.getFluidAtPos(x, y, z - 1, sectionRef, section, commandBuffer),
|
||||
this.getFluidAtPos(x, y, z + 1, sectionRef, section, commandBuffer)
|
||||
};
|
||||
@Nullable
|
||||
private static int[] getNeighbourFluids(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
return chunkSectionComponent == null
|
||||
? null
|
||||
: new int[]{
|
||||
getFluidAtPos(x - 1, y, z, sectionRef, chunkSectionComponent, commandBuffer),
|
||||
getFluidAtPos(x + 1, y, z, sectionRef, chunkSectionComponent, commandBuffer),
|
||||
getFluidAtPos(x, y, z - 1, sectionRef, chunkSectionComponent, commandBuffer),
|
||||
getFluidAtPos(x, y, z + 1, sectionRef, chunkSectionComponent, commandBuffer)
|
||||
};
|
||||
}
|
||||
|
||||
private int getFluidAtPos(
|
||||
int posX, int posY, int posZ, Ref<ChunkStore> sectionRef, ChunkSection currentChunkSection, CommandBuffer<ChunkStore> commandBuffer
|
||||
private static int getFluidAtPos(
|
||||
int posX,
|
||||
int posY,
|
||||
int posZ,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull ChunkSection currentChunkSection,
|
||||
@Nonnull CommandBuffer<ChunkStore> commandBuffer
|
||||
) {
|
||||
Ref<ChunkStore> chunkToUse = sectionRef;
|
||||
int chunkX = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getX(), posX);
|
||||
@@ -156,49 +190,59 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
|
||||
chunkToUse = commandBuffer.getExternalData().getChunkSectionReference(chunkX, chunkY, chunkZ);
|
||||
}
|
||||
|
||||
return chunkToUse == null ? Integer.MIN_VALUE : commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType()).getFluidId(posX, posY, posZ);
|
||||
}
|
||||
|
||||
protected boolean checkIfRaining(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
if (this.weatherIds == null) {
|
||||
return false;
|
||||
if (chunkToUse == null) {
|
||||
return Integer.MIN_VALUE;
|
||||
} else {
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
Ref<ChunkStore> chunk = section.getChunkColumnReference();
|
||||
BlockChunk blockChunk = commandBuffer.getComponent(chunk, BlockChunk.getComponentType());
|
||||
int cropId = blockChunk.getBlock(x, y, z);
|
||||
Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType());
|
||||
WeatherResource weatherResource = store.getResource(WeatherResource.getResourceType());
|
||||
int environment = blockChunk.getEnvironment(x, y, z);
|
||||
int weatherId;
|
||||
if (weatherResource.getForcedWeatherIndex() != 0) {
|
||||
weatherId = weatherResource.getForcedWeatherIndex();
|
||||
} else {
|
||||
weatherId = weatherResource.getWeatherIndexForEnvironment(environment);
|
||||
}
|
||||
|
||||
if (this.weatherIds.contains(weatherId)) {
|
||||
boolean unobstructed = true;
|
||||
|
||||
for (int searchY = y + 1; searchY < 320; searchY++) {
|
||||
int block = blockChunk.getBlock(x, searchY, z);
|
||||
if (block != 0 && block != cropId) {
|
||||
unobstructed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unobstructed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
FluidSection fluidSectionComponent = commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType());
|
||||
return fluidSectionComponent == null ? Integer.MIN_VALUE : fluidSectionComponent.getFluidId(posX, posY, posZ);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSoilWaterExpiring(WorldTimeResource worldTimeResource, TilledSoilBlock soilBlock) {
|
||||
protected boolean checkIfRaining(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
|
||||
if (this.weatherIds == null) {
|
||||
return false;
|
||||
} else {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
|
||||
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
|
||||
if (blockChunkComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
int blockId = blockChunkComponent.getBlock(x, y, z);
|
||||
Store<EntityStore> entityStore = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
|
||||
WeatherResource weatherResource = entityStore.getResource(WeatherResource.getResourceType());
|
||||
int environment = blockChunkComponent.getEnvironment(x, y, z);
|
||||
int weatherId;
|
||||
if (weatherResource.getForcedWeatherIndex() != 0) {
|
||||
weatherId = weatherResource.getForcedWeatherIndex();
|
||||
} else {
|
||||
weatherId = weatherResource.getWeatherIndexForEnvironment(environment);
|
||||
}
|
||||
|
||||
if (!this.weatherIds.contains(weatherId)) {
|
||||
return false;
|
||||
} else {
|
||||
boolean unobstructed = true;
|
||||
|
||||
for (int searchY = y + 1; searchY < 320; searchY++) {
|
||||
int block = blockChunkComponent.getBlock(x, searchY, z);
|
||||
if (block != 0 && block != blockId) {
|
||||
unobstructed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return unobstructed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSoilWaterExpiring(@Nonnull WorldTimeResource worldTimeResource, @Nonnull TilledSoilBlock soilBlock) {
|
||||
Instant until = soilBlock.getWateredUntil();
|
||||
if (until == null) {
|
||||
return false;
|
||||
|
||||
@@ -5,17 +5,22 @@ import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.FarmingStageData;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockStateFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
public static BuilderCodec<BlockStateFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BlockStateFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
BlockStateFarmingStageData.class, BlockStateFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(new KeyedCodec<>("State", Codec.STRING), (stage, block) -> stage.state = block, stage -> stage.state)
|
||||
@@ -29,25 +34,49 @@ public class BlockStateFarmingStageData extends FarmingStageData {
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
int origBlockId = worldChunk.getBlock(x, y, z);
|
||||
BlockType origBlockType = BlockType.getAssetMap().getAsset(origBlockId);
|
||||
BlockType blockType = origBlockType.getBlockForState(this.state);
|
||||
if (blockType != null) {
|
||||
int newType = BlockType.getAssetMap().getIndex(blockType.getId());
|
||||
if (origBlockId != newType) {
|
||||
int rotation = worldChunk.getRotationIndex(x, y, z);
|
||||
commandBuffer.getExternalData().getWorld().execute(() -> worldChunk.setBlock(x, y, z, newType, blockType, rotation, 0, 2));
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing chunk section component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
if (worldChunkComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing world chunk component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
int originBlockId = worldChunkComponent.getBlock(x, y, z);
|
||||
BlockType originBlockType = BlockType.getAssetMap().getAsset(originBlockId);
|
||||
if (originBlockType == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing origin block type for block ID '%s' when applying state farming stage at (%d, %d, %d)", String.valueOf(originBlockId), x, y, z);
|
||||
} else {
|
||||
BlockType blockType = originBlockType.getBlockForState(this.state);
|
||||
if (blockType == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing new block type '%s' when applying state farming stage at (%d, %d, %d)", this.state, x, y, z);
|
||||
} else {
|
||||
int newBlockId = BlockType.getAssetMap().getIndex(blockType.getId());
|
||||
if (originBlockId != newBlockId) {
|
||||
int rotationIndex = worldChunkComponent.getRotationIndex(x, y, z);
|
||||
commandBuffer.getExternalData()
|
||||
.getWorld()
|
||||
.execute(() -> worldChunkComponent.setBlock(x, y, z, newBlockId, blockType, rotationIndex, 0, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,22 @@ import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
||||
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.FarmingStageData;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
||||
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockTypeFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
public static BuilderCodec<BlockTypeFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BlockTypeFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
BlockTypeFarmingStageData.class, BlockTypeFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(new KeyedCodec<>("Block", Codec.STRING), (stage, block) -> stage.block = block, stage -> stage.block)
|
||||
@@ -30,21 +35,42 @@ public class BlockTypeFarmingStageData extends FarmingStageData {
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
int blockId = BlockType.getAssetMap().getIndex(this.block);
|
||||
if (blockId != worldChunk.getBlock(x, y, z)) {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
commandBuffer.getExternalData().getWorld().execute(() -> worldChunk.setBlock(x, y, z, blockId, blockType, worldChunk.getRotationIndex(x, y, z), 0, 2));
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing chunk section component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
|
||||
if (worldChunkComponent == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Missing world chunk component when applying state farming stage at (%d, %d, %d)", x, y, z);
|
||||
} else {
|
||||
int blockId = BlockType.getAssetMap().getIndex(this.block);
|
||||
if (blockId != worldChunkComponent.getBlock(x, y, z)) {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
|
||||
if (blockType == null) {
|
||||
LOGGER.at(Level.WARNING)
|
||||
.atMostEvery(1, TimeUnit.MINUTES)
|
||||
.log("Invalid block type '%s' when applying block type farming stage at (%d, %d, %d)", this.block, x, y, z);
|
||||
} else {
|
||||
commandBuffer.getExternalData().getWorld().execute(() -> {
|
||||
int rotationIndex = worldChunkComponent.getRotationIndex(x, y, z);
|
||||
worldChunkComponent.setBlock(x, y, z, blockId, blockType, rotationIndex, 0, 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
@@ -40,17 +41,22 @@ import com.hypixel.hytale.server.core.util.PrefabUtil;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PrefabFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
public static final float MIN_VOLUME_PREFAB = 125.0F;
|
||||
public static final float MAX_VOLUME_PREFAB = 1000.0F;
|
||||
public static final float MIN_BROKEN_PARTICLE_RATE = 0.25F;
|
||||
public static final float MAX_BROKEN_PARTICLE_RATE = 0.75F;
|
||||
@Nonnull
|
||||
private static final String[] EMPTY_REPLACE_MASK = new String[0];
|
||||
@Nonnull
|
||||
public static BuilderCodec<PrefabFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
public static final BuilderCodec<PrefabFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
PrefabFarmingStageData.class, PrefabFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(
|
||||
@@ -77,12 +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,
|
||||
@@ -91,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(),
|
||||
@@ -136,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)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,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) {
|
||||
@@ -299,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
|
||||
@@ -326,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)
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<DirectionalGrowthBehaviour> CODEC = BuilderCodec.builder(
|
||||
DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour::new, BASE_CODEC
|
||||
)
|
||||
@@ -92,9 +93,9 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
|
||||
@Override
|
||||
public void execute(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> componentAccessor,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int worldX,
|
||||
int worldY,
|
||||
int worldZ,
|
||||
@@ -103,54 +104,68 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
int x = 0;
|
||||
int z = 0;
|
||||
FastRandom random = new FastRandom();
|
||||
String blockTypeKey = this.blockTypes.get(random).getBlockTypeKey();
|
||||
World world = commandBuffer.getExternalData().getWorld();
|
||||
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, worldX, worldZ, 1);
|
||||
DirectionalGrowthBehaviour.BlockTypeWeight blockTypeWeight = this.blockTypes.get(random);
|
||||
if (blockTypeWeight != null) {
|
||||
String blockTypeKey = blockTypeWeight.getBlockTypeKey();
|
||||
World world = componentAccessor.getExternalData().getWorld();
|
||||
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, worldX, worldZ, 1);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (this.horizontalRange != null) {
|
||||
double angle = (float) (Math.PI * 2) * random.nextFloat();
|
||||
int radius = this.horizontalRange.getInt(random.nextFloat());
|
||||
x = MathUtil.fastRound(radius * TrigMathUtil.cos(angle));
|
||||
z = MathUtil.fastRound(radius * TrigMathUtil.sin(angle));
|
||||
}
|
||||
|
||||
int targetX = worldX + x;
|
||||
int targetZ = worldZ + z;
|
||||
int chunkX = ChunkUtil.chunkCoordinate(targetX);
|
||||
int chunkZ = ChunkUtil.chunkCoordinate(targetZ);
|
||||
WorldChunk chunk = chunkAccessor.getChunkIfInMemory(ChunkUtil.indexChunk(chunkX, chunkZ));
|
||||
if (chunk != null) {
|
||||
int targetY;
|
||||
if (this.verticalRange != null) {
|
||||
int directionValue = switch (this.verticalDirection) {
|
||||
case DOWNWARDS, UPWARDS -> this.verticalDirection.getValue();
|
||||
case BOTH -> random.nextBoolean() ? 1 : -1;
|
||||
};
|
||||
targetY = worldY + this.verticalRange.getInt(random.nextFloat()) * directionValue;
|
||||
} else {
|
||||
targetY = chunk.getHeight(targetX, targetZ) + 1;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (this.horizontalRange != null) {
|
||||
double angle = (float) (Math.PI * 2) * random.nextFloat();
|
||||
int radius = this.horizontalRange.getInt(random.nextFloat());
|
||||
x = MathUtil.fastRound(radius * TrigMathUtil.cos(angle));
|
||||
z = MathUtil.fastRound(radius * TrigMathUtil.sin(angle));
|
||||
}
|
||||
|
||||
if (this.tryPlaceBlock(world, chunk, targetX, targetY, targetZ, blockTypeKey, 0)) {
|
||||
int finalTargetY = targetY;
|
||||
world.execute(() -> {
|
||||
WorldChunk loadedChunk = chunkAccessor.getChunk(ChunkUtil.indexChunk(chunkX, chunkZ));
|
||||
if (loadedChunk != null) {
|
||||
loadedChunk.placeBlock(targetX, finalTargetY, targetZ, blockTypeKey, Rotation.None, Rotation.None, Rotation.None);
|
||||
decaySpread(commandBuffer, loadedChunk.getBlockComponentChunk(), targetX, finalTargetY, targetZ, newSpreadRate);
|
||||
}
|
||||
});
|
||||
return;
|
||||
int targetX = worldX + x;
|
||||
int targetZ = worldZ + z;
|
||||
int chunkX = ChunkUtil.chunkCoordinate(targetX);
|
||||
int chunkZ = ChunkUtil.chunkCoordinate(targetZ);
|
||||
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
WorldChunk worldChunkComponent = chunkAccessor.getChunkIfInMemory(chunkIndex);
|
||||
if (worldChunkComponent != null) {
|
||||
int targetY;
|
||||
if (this.verticalRange != null) {
|
||||
int directionValue = switch (this.verticalDirection) {
|
||||
case DOWNWARDS, UPWARDS -> this.verticalDirection.getValue();
|
||||
case BOTH -> random.nextBoolean() ? 1 : -1;
|
||||
};
|
||||
targetY = worldY + this.verticalRange.getInt(random.nextFloat()) * directionValue;
|
||||
} else {
|
||||
targetY = worldChunkComponent.getHeight(targetX, targetZ) + 1;
|
||||
}
|
||||
|
||||
if (this.tryPlaceBlock(world, worldChunkComponent, targetX, targetY, targetZ, blockTypeKey, 0)) {
|
||||
int finalTargetY = targetY;
|
||||
world.execute(() -> {
|
||||
long loadedChunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
|
||||
WorldChunk loadedChunk = chunkAccessor.getChunk(loadedChunkIndex);
|
||||
if (loadedChunk != null) {
|
||||
loadedChunk.placeBlock(targetX, finalTargetY, targetZ, blockTypeKey, Rotation.None, Rotation.None, Rotation.None);
|
||||
BlockComponentChunk blockComponentChunk = loadedChunk.getBlockComponentChunk();
|
||||
if (blockComponentChunk != null) {
|
||||
decaySpread(componentAccessor, blockComponentChunk, targetX, finalTargetY, targetZ, newSpreadRate);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void decaySpread(
|
||||
ComponentAccessor<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, int worldX, int worldY, int worldZ, float newSpreadRate
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull BlockComponentChunk blockComponentChunk,
|
||||
int worldX,
|
||||
int worldY,
|
||||
int worldZ,
|
||||
float newSpreadRate
|
||||
) {
|
||||
Ref<ChunkStore> blockRefPlaced = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(worldX, worldY, worldZ));
|
||||
int blockIndex = ChunkUtil.indexBlockInColumn(worldX, worldY, worldZ);
|
||||
Ref<ChunkStore> blockRefPlaced = blockComponentChunk.getEntityReference(blockIndex);
|
||||
if (blockRefPlaced != null) {
|
||||
FarmingBlock farmingPlaced = commandBuffer.getComponent(blockRefPlaced, FarmingBlock.getComponentType());
|
||||
if (farmingPlaced != null) {
|
||||
@@ -159,37 +174,58 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tryPlaceBlock(@Nonnull World world, @Nonnull WorldChunk chunk, int worldX, int worldY, int worldZ, String blockTypeKey, int rotation) {
|
||||
private boolean tryPlaceBlock(
|
||||
@Nonnull World world, @Nonnull WorldChunk chunk, int worldX, int worldY, int worldZ, @Nonnull String blockTypeKey, int rotation
|
||||
) {
|
||||
if (chunk.getBlock(worldX, worldY, worldZ) != 0) {
|
||||
return false;
|
||||
} else if (!this.validatePosition(world, worldX, worldY, worldZ)) {
|
||||
return false;
|
||||
} else {
|
||||
BlockType blockType = BlockType.getAssetMap().getAsset(blockTypeKey);
|
||||
if (blockType == null) {
|
||||
BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockTypeKey);
|
||||
if (blockTypeAsset == null) {
|
||||
return false;
|
||||
} else if (!chunk.testPlaceBlock(worldX, worldY, worldZ, blockType, rotation)) {
|
||||
} else if (!chunk.testPlaceBlock(worldX, worldY, worldZ, blockTypeAsset, rotation)) {
|
||||
return false;
|
||||
} else {
|
||||
int cx = chunk.getX();
|
||||
int cz = chunk.getZ();
|
||||
int cy = ChunkUtil.indexSection(worldY);
|
||||
Ref<ChunkStore> sectionRef = world.getChunkStore().getChunkSectionReference(cx, cy, cz);
|
||||
if (sectionRef == null) {
|
||||
return false;
|
||||
} else {
|
||||
Store<ChunkStore> store = world.getChunkStore().getStore();
|
||||
BlockPhysics blockPhysics = store.getComponent(sectionRef, BlockPhysics.getComponentType());
|
||||
FluidSection fluidSection = store.getComponent(sectionRef, FluidSection.getComponentType());
|
||||
BlockSection blockSection = store.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
int filler = blockSection.getFiller(worldX, worldY, worldZ);
|
||||
int chunkX = chunk.getX();
|
||||
int chunkY = ChunkUtil.indexSection(worldY);
|
||||
int chunkZ = chunk.getZ();
|
||||
ChunkStore chunkStore = world.getChunkStore();
|
||||
Ref<ChunkStore> sectionRef = chunkStore.getChunkSectionReference(chunkX, chunkY, chunkZ);
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
Store<ChunkStore> store = chunkStore.getStore();
|
||||
BlockPhysics blockPhysicsComponent = store.getComponent(sectionRef, BlockPhysics.getComponentType());
|
||||
|
||||
assert blockPhysicsComponent != null;
|
||||
|
||||
FluidSection fluidSectionComponent = store.getComponent(sectionRef, FluidSection.getComponentType());
|
||||
|
||||
assert fluidSectionComponent != null;
|
||||
|
||||
BlockSection blockSectionComponent = store.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
|
||||
assert blockSectionComponent != null;
|
||||
|
||||
int filler = blockSectionComponent.getFiller(worldX, worldY, worldZ);
|
||||
BlockPhysicsSystems.CachedAccessor cachedAccessor = BlockPhysicsSystems.CachedAccessor.of(
|
||||
store, blockSection, blockPhysics, fluidSection, cx, cy, cz, 14
|
||||
store, blockSectionComponent, blockPhysicsComponent, fluidSectionComponent, chunkX, chunkY, chunkZ, 14
|
||||
);
|
||||
return BlockPhysicsUtil.testBlockPhysics(
|
||||
cachedAccessor, blockSection, blockPhysics, fluidSection, worldX, worldY, worldZ, blockType, rotation, filler
|
||||
cachedAccessor,
|
||||
blockSectionComponent,
|
||||
blockPhysicsComponent,
|
||||
fluidSectionComponent,
|
||||
worldX,
|
||||
worldY,
|
||||
worldZ,
|
||||
blockTypeAsset,
|
||||
rotation,
|
||||
filler
|
||||
)
|
||||
!= 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -212,7 +248,7 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
|
||||
|
||||
public static class BlockTypeWeight implements IWeightedElement {
|
||||
@Nonnull
|
||||
public static BuilderCodec<DirectionalGrowthBehaviour.BlockTypeWeight> CODEC = BuilderCodec.builder(
|
||||
public static final BuilderCodec<DirectionalGrowthBehaviour.BlockTypeWeight> CODEC = BuilderCodec.builder(
|
||||
DirectionalGrowthBehaviour.BlockTypeWeight.class, DirectionalGrowthBehaviour.BlockTypeWeight::new
|
||||
)
|
||||
.append(
|
||||
|
||||
@@ -19,7 +19,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class SpreadFarmingStageData extends FarmingStageData {
|
||||
@Nonnull
|
||||
public static BuilderCodec<SpreadFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
public static final BuilderCodec<SpreadFarmingStageData> CODEC = BuilderCodec.builder(
|
||||
SpreadFarmingStageData.class, SpreadFarmingStageData::new, FarmingStageData.BASE_CODEC
|
||||
)
|
||||
.append(
|
||||
@@ -84,50 +84,67 @@ public class SpreadFarmingStageData extends FarmingStageData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldStop(ComponentAccessor<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
float spreadRate = farming.getSpreadRate();
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
float executions = this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farming.getGeneration())) * spreadRate;
|
||||
int executed = farming.getExecutions();
|
||||
return spreadRate <= 0.0F || executed >= executions;
|
||||
public boolean shouldStop(
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> blockRef, int x, int y, int z
|
||||
) {
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
return true;
|
||||
} else {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent == null) {
|
||||
return true;
|
||||
} else {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
float spreadRate = farmingBlockComponent.getSpreadRate();
|
||||
float executions = this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farmingBlockComponent.getGeneration())) * spreadRate;
|
||||
int executed = farmingBlockComponent.getExecutions();
|
||||
return spreadRate <= 0.0F || executed >= executions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
ComponentAccessor<ChunkStore> commandBuffer,
|
||||
Ref<ChunkStore> sectionRef,
|
||||
Ref<ChunkStore> blockRef,
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer,
|
||||
@Nonnull Ref<ChunkStore> sectionRef,
|
||||
@Nonnull Ref<ChunkStore> blockRef,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
@Nullable FarmingStageData previousStage
|
||||
) {
|
||||
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
|
||||
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z);
|
||||
float spreadRate = farming.getSpreadRate();
|
||||
double executions = Math.floor(this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farming.getGeneration())) * spreadRate);
|
||||
int executed = farming.getExecutions();
|
||||
if (!(spreadRate <= 0.0F) && !(executed >= executions)) {
|
||||
for (int i = 0; i < this.spreadGrowthBehaviours.length; i++) {
|
||||
SpreadGrowthBehaviour spreadGrowthBehaviour = this.spreadGrowthBehaviours[i];
|
||||
float decayRate = this.spreadDecayPercent.getInt(HashUtil.random(i | (long)farming.getGeneration() << 32, worldX, worldY, worldZ)) / 100.0F;
|
||||
spreadGrowthBehaviour.execute(commandBuffer, sectionRef, blockRef, worldX, worldY, worldZ, spreadRate - decayRate);
|
||||
}
|
||||
FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent != null) {
|
||||
ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
|
||||
if (chunkSectionComponent != null) {
|
||||
int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
|
||||
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
|
||||
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
|
||||
float spreadRate = farmingBlockComponent.getSpreadRate();
|
||||
int generation = farmingBlockComponent.getGeneration();
|
||||
double executions = Math.floor(this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, generation)) * spreadRate);
|
||||
int executed = farmingBlockComponent.getExecutions();
|
||||
if (!(spreadRate <= 0.0F) && !(executed >= executions)) {
|
||||
for (int i = 0; i < this.spreadGrowthBehaviours.length; i++) {
|
||||
SpreadGrowthBehaviour spreadGrowthBehaviour = this.spreadGrowthBehaviours[i];
|
||||
float decayRate = this.spreadDecayPercent.getInt(HashUtil.random(i | (long)generation << 32, worldX, worldY, worldZ)) / 100.0F;
|
||||
spreadGrowthBehaviour.execute(commandBuffer, sectionRef, blockRef, worldX, worldY, worldZ, spreadRate - decayRate);
|
||||
}
|
||||
|
||||
farming.setExecutions(++executed);
|
||||
farmingBlockComponent.setExecutions(++executed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(ComponentAccessor<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) {
|
||||
public void remove(
|
||||
@Nonnull ComponentAccessor<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> blockRef, int x, int y, int z
|
||||
) {
|
||||
super.remove(commandBuffer, sectionRef, blockRef, x, y, z);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,12 @@ import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import com.hypixel.hytale.server.core.universe.world.worldlocationcondition.WorldLocationCondition;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class SpreadGrowthBehaviour {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<SpreadGrowthBehaviour> CODEC = new CodecMapCodec<>("Type");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SpreadGrowthBehaviour> BASE_CODEC = BuilderCodec.abstractBuilder(SpreadGrowthBehaviour.class)
|
||||
.append(
|
||||
new KeyedCodec<>("LocationConditions", new ArrayCodec<>(WorldLocationCondition.CODEC, WorldLocationCondition[]::new)),
|
||||
@@ -23,9 +26,11 @@ public abstract class SpreadGrowthBehaviour {
|
||||
.build();
|
||||
protected WorldLocationCondition[] worldLocationConditions;
|
||||
|
||||
public abstract void execute(ComponentAccessor<ChunkStore> var1, Ref<ChunkStore> var2, Ref<ChunkStore> var3, int var4, int var5, int var6, float var7);
|
||||
public abstract void execute(
|
||||
@Nonnull ComponentAccessor<ChunkStore> var1, @Nonnull Ref<ChunkStore> var2, @Nonnull Ref<ChunkStore> var3, int var4, int var5, int var6, float var7
|
||||
);
|
||||
|
||||
protected boolean validatePosition(World world, int worldX, int worldY, int worldZ) {
|
||||
protected boolean validatePosition(@Nonnull World world, int worldX, int worldY, int worldZ) {
|
||||
if (this.worldLocationConditions == null) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -35,7 +35,9 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ChangeFarmingStageInteraction> CODEC = BuilderCodec.builder(
|
||||
ChangeFarmingStageInteraction.class, ChangeFarmingStageInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -75,11 +77,11 @@ public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
|
||||
.build();
|
||||
protected int targetStage = -1;
|
||||
@Nullable
|
||||
protected Integer increaseBy = null;
|
||||
protected Integer increaseBy;
|
||||
@Nullable
|
||||
protected Integer decreaseBy = null;
|
||||
protected Integer decreaseBy;
|
||||
@Nullable
|
||||
protected String targetStageSet = null;
|
||||
protected String targetStageSet;
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@@ -270,16 +272,16 @@ public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
|
||||
);
|
||||
Ref<ChunkStore> sectionRef = world.getChunkStore()
|
||||
.getChunkSectionReference(ChunkUtil.chunkCoordinate(x), ChunkUtil.chunkCoordinate(y), ChunkUtil.chunkCoordinate(z));
|
||||
if (sectionRef != null) {
|
||||
BlockSection section = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (section != null) {
|
||||
section.scheduleTick(ChunkUtil.indexBlock(x, y, z), now);
|
||||
if (sectionRef != null && sectionRef.isValid()) {
|
||||
BlockSection blockSectionComponent = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
|
||||
if (blockSectionComponent != null) {
|
||||
blockSectionComponent.scheduleTick(ChunkUtil.indexBlock(x, y, z), now);
|
||||
}
|
||||
|
||||
stages[stageIndex].apply(chunkStore, sectionRef, blockRef, x, y, z, previousStage);
|
||||
LOGGER.atInfo().log("[ChangeFarmingStage] Applied stage %d via stages[%d].apply()", stageIndex, stageIndex);
|
||||
} else {
|
||||
LOGGER.atWarning().log("[ChangeFarmingStage] sectionRef was null - could not apply stage!");
|
||||
LOGGER.atWarning().log("[ChangeFarmingStage] sectionRef was null or invalid - could not apply stage!");
|
||||
}
|
||||
|
||||
worldChunk.setTicking(x, y, z, true);
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FertilizeSoilInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<FertilizeSoilInteraction> CODEC = BuilderCodec.builder(
|
||||
FertilizeSoilInteraction.class, FertilizeSoilInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -56,40 +57,45 @@ public class FertilizeSoilInteraction extends SimpleBlockInteraction {
|
||||
) {
|
||||
int x = targetBlock.getX();
|
||||
int z = targetBlock.getZ();
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef == null) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
|
||||
WorldChunk worldChunkComponent = world.getChunk(chunkIndex);
|
||||
if (worldChunkComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
TilledSoilBlock soil = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null && !soil.isFertilized()) {
|
||||
soil.setFertilized(true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
FarmingBlock farmingState = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingState == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
Ref<ChunkStore> blockRef = worldChunkComponent.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null || !blockRef.isValid()) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunkComponent, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
TilledSoilBlock tilledSoilComponent = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilComponent != null && !tilledSoilComponent.isFertilized()) {
|
||||
tilledSoilComponent.setFertilized(true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
Ref<ChunkStore> soilRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilRef == null) {
|
||||
FarmingBlock farmingBlockComponent = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
soil = chunkStore.getComponent(soilRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null && !soil.isFertilized()) {
|
||||
soil.setFertilized(true);
|
||||
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
Ref<ChunkStore> soilBlockRef = worldChunkComponent.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilBlockRef != null && soilBlockRef.isValid()) {
|
||||
tilledSoilComponent = chunkStore.getComponent(soilBlockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilComponent != null && !tilledSoilComponent.isFertilized()) {
|
||||
tilledSoilComponent.setFertilized(true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunkComponent.setTicking(x, targetBlock.getY(), z, true);
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ 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
|
||||
)
|
||||
@@ -47,15 +48,15 @@ public class HarvestCropInteraction extends SimpleBlockInteraction {
|
||||
|
||||
assert blockChunkComponent != null;
|
||||
|
||||
BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.y);
|
||||
if (section != null) {
|
||||
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(targetBlock.y);
|
||||
if (blockSection != null) {
|
||||
WorldChunk worldChunkComponent = chunkStore.getStore().getComponent(chunkRef, WorldChunk.getComponentType());
|
||||
|
||||
assert worldChunkComponent != null;
|
||||
|
||||
BlockType blockType = worldChunkComponent.getBlockType(targetBlock);
|
||||
if (blockType != null) {
|
||||
int rotationIndex = section.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
int rotationIndex = blockSection.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
FarmingUtil.harvest(world, commandBuffer, ref, blockType, rotationIndex, targetBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.hypixel.hytale.server.core.inventory.Inventory;
|
||||
import com.hypixel.hytale.server.core.inventory.ItemStack;
|
||||
import com.hypixel.hytale.server.core.modules.block.BlockModule;
|
||||
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInteraction;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction;
|
||||
@@ -41,6 +42,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<UseCaptureCrateInteraction> CODEC = BuilderCodec.builder(
|
||||
UseCaptureCrateInteraction.class, UseCaptureCrateInteraction::new, SimpleInteraction.CODEC
|
||||
)
|
||||
@@ -74,20 +76,26 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
boolean firstRun, float time, @Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler
|
||||
) {
|
||||
CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer();
|
||||
if (commandBuffer == null) {
|
||||
|
||||
assert commandBuffer != null;
|
||||
|
||||
ItemStack item = context.getHeldItem();
|
||||
if (item == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
ItemStack item = context.getHeldItem();
|
||||
if (item == null) {
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
if (!(EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity)) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
if (!(EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity)) {
|
||||
Inventory inventory = livingEntity.getInventory();
|
||||
byte activeHotbarSlot = inventory.getActiveHotbarSlot();
|
||||
ItemStack inHandItemStack = inventory.getActiveHotbarItem();
|
||||
if (inHandItemStack == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
Inventory inventory = livingEntity.getInventory();
|
||||
byte activeHotbarSlot = inventory.getActiveHotbarSlot();
|
||||
ItemStack inHandItemStack = inventory.getActiveHotbarItem();
|
||||
CapturedNPCMetadata existingMeta = item.getFromMetadataOrNull("CapturedEntity", CapturedNPCMetadata.CODEC);
|
||||
if (existingMeta != null) {
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
@@ -95,47 +103,56 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
Ref<EntityStore> targetEntity = context.getTargetEntity();
|
||||
if (targetEntity == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
NPCEntity npcComponent = commandBuffer.getComponent(targetEntity, NPCEntity.getComponentType());
|
||||
if (npcComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
|
||||
boolean tagFound = false;
|
||||
|
||||
for (int group : this.acceptedNpcGroupIndexes) {
|
||||
if (tagSetPlugin.tagInSet(group, npcComponent.getRoleIndex())) {
|
||||
tagFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tagFound) {
|
||||
DeathComponent deathComponent = commandBuffer.getComponent(targetEntity, DeathComponent.getComponentType());
|
||||
if (deathComponent != null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
PersistentModel persistentModel = commandBuffer.getComponent(targetEntity, PersistentModel.getComponentType());
|
||||
if (persistentModel == null) {
|
||||
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
|
||||
boolean tagFound = false;
|
||||
|
||||
for (int group : this.acceptedNpcGroupIndexes) {
|
||||
if (tagSetPlugin.tagInSet(group, npcComponent.getRoleIndex())) {
|
||||
tagFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tagFound) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(persistentModel.getModelReference().getModelAssetId());
|
||||
CapturedNPCMetadata meta = inHandItemStack.getFromMetadataOrDefault("CapturedEntity", CapturedNPCMetadata.CODEC);
|
||||
if (modelAsset != null) {
|
||||
meta.setIconPath(modelAsset.getIcon());
|
||||
}
|
||||
PersistentModel persistentModelComponent = commandBuffer.getComponent(targetEntity, PersistentModel.getComponentType());
|
||||
if (persistentModelComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
super.tick0(firstRun, time, type, context, cooldownHandler);
|
||||
} else {
|
||||
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(persistentModelComponent.getModelReference().getModelAssetId());
|
||||
CapturedNPCMetadata itemMetaData = inHandItemStack.getFromMetadataOrDefault("CapturedEntity", CapturedNPCMetadata.CODEC);
|
||||
if (modelAsset != null) {
|
||||
itemMetaData.setIconPath(modelAsset.getIcon());
|
||||
}
|
||||
|
||||
meta.setRoleIndex(npcComponent.getRoleIndex());
|
||||
String npcName = NPCPlugin.get().getName(npcComponent.getRoleIndex());
|
||||
if (npcName != null) {
|
||||
meta.setNpcNameKey(npcName);
|
||||
}
|
||||
String npcName = NPCPlugin.get().getName(npcComponent.getRoleIndex());
|
||||
if (npcName != null) {
|
||||
itemMetaData.setNpcNameKey(npcName);
|
||||
}
|
||||
|
||||
if (this.fullIcon != null) {
|
||||
meta.setFullItemIcon(this.fullIcon);
|
||||
}
|
||||
if (this.fullIcon != null) {
|
||||
itemMetaData.setFullItemIcon(this.fullIcon);
|
||||
}
|
||||
|
||||
ItemStack itemWithNPC = inHandItemStack.withMetadata(CapturedNPCMetadata.KEYED_CODEC, meta);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, itemWithNPC);
|
||||
commandBuffer.removeEntity(targetEntity, RemoveReason.REMOVE);
|
||||
ItemStack itemWithNPC = inHandItemStack.withMetadata(CapturedNPCMetadata.KEYED_CODEC, itemMetaData);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, itemWithNPC);
|
||||
commandBuffer.removeEntity(targetEntity, RemoveReason.REMOVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,46 +189,51 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
|
||||
if (pos == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(pos.x, pos.z));
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(pos.x, pos.y, pos.z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, pos.x, pos.y, pos.z);
|
||||
}
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(pos.x, pos.z);
|
||||
WorldChunk worldChunk = world.getChunk(chunkIndex);
|
||||
if (worldChunk == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(pos.x, pos.y, pos.z);
|
||||
if (blockRef == null || !blockRef.isValid()) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
ItemStack noMetaItemStack = item.withMetadata(null);
|
||||
if (blockRef != null) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
CoopBlock coopBlockState = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockState != null) {
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
if (coopBlockState.tryPutResident(existingMeta, worldTimeResource)) {
|
||||
world.execute(
|
||||
() -> coopBlockState.ensureSpawnResidentsInWorld(
|
||||
world, world.getEntityStore().getStore(), new Vector3d(pos.x, pos.y, pos.z), new Vector3d().assign(Vector3d.FORWARD)
|
||||
)
|
||||
);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
ItemStack noMetaItemStack = item.withMetadata(null);
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
CoopBlock coopBlockComponent = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockComponent != null) {
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
if (coopBlockComponent.tryPutResident(existingMeta, worldTimeResource)) {
|
||||
world.execute(
|
||||
() -> coopBlockComponent.ensureSpawnResidentsInWorld(
|
||||
world, world.getEntityStore().getStore(), new Vector3d(pos.x, pos.y, pos.z), new Vector3d().assign(Vector3d.FORWARD)
|
||||
)
|
||||
);
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
context.getState().state = InteractionState.Finished;
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3d spawnPos = new Vector3d(pos.x + 0.5F, pos.y, pos.z + 0.5F);
|
||||
if (context.getClientState() != null) {
|
||||
BlockFace blockFace = BlockFace.fromProtocolFace(context.getClientState().blockFace);
|
||||
if (blockFace != null) {
|
||||
spawnPos.add(blockFace.getDirection());
|
||||
Vector3d spawnPos = new Vector3d(pos.x + 0.5F, pos.y, pos.z + 0.5F);
|
||||
if (context.getClientState() != null) {
|
||||
BlockFace blockFace = BlockFace.fromProtocolFace(context.getClientState().blockFace);
|
||||
if (blockFace != null) {
|
||||
spawnPos.add(blockFace.getDirection());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NPCPlugin npcModule = NPCPlugin.get();
|
||||
Store<EntityStore> store = context.getCommandBuffer().getStore();
|
||||
int roleIndex = existingMeta.getRoleIndex();
|
||||
commandBuffer.run(_store -> npcModule.spawnEntity(store, roleIndex, spawnPos, Vector3f.ZERO, null, null));
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
String roleId = existingMeta.getNpcNameKey();
|
||||
int roleIndex = NPCPlugin.get().getIndex(roleId);
|
||||
commandBuffer.run(_store -> NPCPlugin.get().spawnEntity(_store, roleIndex, spawnPos, Vector3f.ZERO, null, null));
|
||||
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UseCoopInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<UseCoopInteraction> CODEC = BuilderCodec.builder(
|
||||
UseCoopInteraction.class, UseCoopInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -43,39 +44,39 @@ public class UseCoopInteraction extends SimpleBlockInteraction {
|
||||
) {
|
||||
int x = targetBlock.getX();
|
||||
int z = targetBlock.getZ();
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
|
||||
WorldChunk worldChunk = world.getChunk(chunkIndex);
|
||||
if (worldChunk == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
if (blockRef == null || !blockRef.isValid()) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
CoopBlock coopBlockState = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockState == null) {
|
||||
CoopBlock coopBlockComponent = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
|
||||
if (coopBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Ref<EntityStore> playerRef = context.getEntity();
|
||||
LivingEntity playerEntity = (LivingEntity)EntityUtils.getEntity(playerRef, commandBuffer);
|
||||
if (playerEntity == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
CombinedItemContainer playerInventoryContainer = playerEntity.getInventory().getCombinedHotbarFirst();
|
||||
if (playerInventoryContainer != null) {
|
||||
coopBlockState.gatherProduceFromInventory(playerInventoryContainer);
|
||||
Ref<EntityStore> ref = context.getEntity();
|
||||
if (EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity) {
|
||||
CombinedItemContainer inventoryContainer = livingEntity.getInventory().getCombinedHotbarFirst();
|
||||
if (inventoryContainer != null) {
|
||||
coopBlockComponent.gatherProduceFromContainer(inventoryContainer);
|
||||
BlockType currentBlockType = worldChunk.getBlockType(targetBlock);
|
||||
|
||||
assert currentBlockType != null;
|
||||
|
||||
worldChunk.setBlockInteractionState(targetBlock, currentBlockType, coopBlockState.hasProduce() ? "Produce_Ready" : "default");
|
||||
worldChunk.setBlockInteractionState(targetBlock, currentBlockType, coopBlockComponent.hasProduce() ? "Produce_Ready" : "default");
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UseWateringCanInteraction extends SimpleBlockInteraction {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<UseWateringCanInteraction> CODEC = BuilderCodec.builder(
|
||||
UseWateringCanInteraction.class, UseWateringCanInteraction::new, SimpleBlockInteraction.CODEC
|
||||
)
|
||||
@@ -61,45 +62,52 @@ public class UseWateringCanInteraction extends SimpleBlockInteraction {
|
||||
) {
|
||||
int x = targetBlock.getX();
|
||||
int z = targetBlock.getZ();
|
||||
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef == null) {
|
||||
long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
|
||||
WorldChunk worldChunk = world.getChunk(chunkIndex);
|
||||
if (worldChunk == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
TilledSoilBlock soil = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (soil != null) {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
soil.setWateredUntil(wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
FarmingBlock farmingState = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingState == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
|
||||
if (blockRef == null) {
|
||||
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
}
|
||||
|
||||
if (blockRef != null && blockRef.isValid()) {
|
||||
Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
|
||||
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
|
||||
TilledSoilBlock tilledSoilBlockComponent = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilBlockComponent != null) {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
tilledSoilBlockComponent.setWateredUntil(wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true);
|
||||
} else {
|
||||
Ref<ChunkStore> soilRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilRef == null) {
|
||||
FarmingBlock farmingBlockComponent = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
|
||||
if (farmingBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
soil = chunkStore.getComponent(soilRef, TilledSoilBlock.getComponentType());
|
||||
if (soil == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
Ref<ChunkStore> soilBlockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
|
||||
if (soilBlockRef != null && soilBlockRef.isValid()) {
|
||||
tilledSoilBlockComponent = chunkStore.getComponent(soilBlockRef, TilledSoilBlock.getComponentType());
|
||||
if (tilledSoilBlockComponent == null) {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
} else {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
tilledSoilBlockComponent.setWateredUntil(wateredUntil);
|
||||
worldChunk.getBlockChunk()
|
||||
.getSectionAtBlockY(targetBlock.y - 1)
|
||||
.scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y - 1, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
}
|
||||
} else {
|
||||
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
|
||||
soil.setWateredUntil(wateredUntil);
|
||||
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y - 1).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y - 1, z), wateredUntil);
|
||||
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true);
|
||||
worldChunk.setTicking(x, targetBlock.getY(), z, true);
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.getState().state = InteractionState.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CoopBlock implements Component<ChunkStore> {
|
||||
@Nonnull
|
||||
public static final String STATE_PRODUCE = "Produce_Ready";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CoopBlock> CODEC = BuilderCodec.builder(CoopBlock.class, CoopBlock::new)
|
||||
.append(new KeyedCodec<>("FarmingCoopId", Codec.STRING, true), (coop, s) -> coop.coopAssetId = s, coop -> coop.coopAssetId)
|
||||
.add()
|
||||
@@ -73,7 +76,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
.add()
|
||||
.build();
|
||||
protected String coopAssetId;
|
||||
protected List<CoopBlock.CoopResident> residents = new ArrayList<>();
|
||||
@Nonnull
|
||||
protected List<CoopBlock.CoopResident> residents = new ObjectArrayList<>();
|
||||
@Nonnull
|
||||
protected ItemContainer itemContainer = EmptyItemContainer.INSTANCE;
|
||||
|
||||
public static ComponentType<ChunkStore, CoopBlock> getComponentType() {
|
||||
@@ -81,7 +86,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
public CoopBlock() {
|
||||
ArrayList<ItemStack> remainder = new ArrayList<>();
|
||||
List<ItemStack> remainder = new ObjectArrayList<>();
|
||||
this.itemContainer = ItemContainer.ensureContainerCapacity(this.itemContainer, (short)5, SimpleItemContainer::new, remainder);
|
||||
}
|
||||
|
||||
@@ -90,7 +95,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
return FarmingCoopAsset.getAssetMap().getAsset(this.coopAssetId);
|
||||
}
|
||||
|
||||
public CoopBlock(String farmingCoopId, List<CoopBlock.CoopResident> residents, ItemContainer itemContainer) {
|
||||
public CoopBlock(@Nonnull String farmingCoopId, @Nonnull List<CoopBlock.CoopResident> residents, @Nonnull ItemContainer itemContainer) {
|
||||
this.coopAssetId = farmingCoopId;
|
||||
this.residents.addAll(residents);
|
||||
this.itemContainer = itemContainer.clone();
|
||||
@@ -98,13 +103,13 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
this.itemContainer = ItemContainer.ensureContainerCapacity(this.itemContainer, (short)5, SimpleItemContainer::new, remainder);
|
||||
}
|
||||
|
||||
public boolean tryPutResident(CapturedNPCMetadata metadata, WorldTimeResource worldTimeResource) {
|
||||
public boolean tryPutResident(@Nonnull CapturedNPCMetadata metadata, @Nonnull WorldTimeResource worldTimeResource) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return false;
|
||||
} else if (this.residents.size() >= coopAsset.getMaxResidents()) {
|
||||
return false;
|
||||
} else if (!this.getCoopAcceptsNPCGroup(metadata.getRoleIndex())) {
|
||||
} else if (!this.getCoopAcceptsNPC(metadata.getNpcNameKey())) {
|
||||
return false;
|
||||
} else {
|
||||
this.residents.add(new CoopBlock.CoopResident(metadata, null, worldTimeResource.getGameTime()));
|
||||
@@ -112,7 +117,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryPutWildResidentFromWild(Store<EntityStore> store, Ref<EntityStore> entityRef, WorldTimeResource worldTimeResource, Vector3i coopLocation) {
|
||||
public boolean tryPutWildResidentFromWild(
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> entityRef, @Nonnull WorldTimeResource worldTimeResource, @Nonnull Vector3i coopLocation
|
||||
) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return false;
|
||||
@@ -124,7 +131,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
|
||||
if (coopResidentComponent != null) {
|
||||
return false;
|
||||
} else if (!this.getCoopAcceptsNPCGroup(npcComponent.getRoleIndex())) {
|
||||
} else if (!this.getCoopAcceptsNPC(npcComponent.getRoleName())) {
|
||||
return false;
|
||||
} else if (this.residents.size() >= coopAsset.getMaxResidents()) {
|
||||
return false;
|
||||
@@ -137,7 +144,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
} else {
|
||||
PersistentRef persistentRef = new PersistentRef();
|
||||
persistentRef.setEntity(entityRef, uuidComponent.getUuid());
|
||||
CapturedNPCMetadata metadata = FarmingUtil.generateCapturedNPCMetadata(store, entityRef, npcComponent.getRoleIndex());
|
||||
CapturedNPCMetadata metadata = FarmingUtil.generateCapturedNPCMetadata(store, entityRef, npcComponent.getRoleName());
|
||||
CoopBlock.CoopResident residentRecord = new CoopBlock.CoopResident(metadata, persistentRef, worldTimeResource.getGameTime());
|
||||
residentRecord.deployedToWorld = true;
|
||||
this.residents.add(residentRecord);
|
||||
@@ -148,8 +155,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getCoopAcceptsNPCGroup(int npcRoleIndex) {
|
||||
public boolean getCoopAcceptsNPC(String npcNameKey) {
|
||||
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
|
||||
int roleIndex = NPCPlugin.get().getIndex(npcNameKey);
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return false;
|
||||
@@ -159,7 +167,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
return true;
|
||||
} else {
|
||||
for (int group : acceptedNpcGroupIndexes) {
|
||||
if (tagSetPlugin.tagInSet(group, npcRoleIndex)) {
|
||||
if (tagSetPlugin.tagInSet(group, roleIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +177,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void generateProduceToInventory(WorldTimeResource worldTimeResource) {
|
||||
public void generateProduceToInventory(@Nonnull WorldTimeResource worldTimeResource) {
|
||||
Instant currentTime = worldTimeResource.getGameTime();
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
@@ -184,8 +192,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
resident.setLastProduced(currentTime);
|
||||
} else {
|
||||
CapturedNPCMetadata residentMeta = resident.getMetadata();
|
||||
int npcRoleIndex = residentMeta.getRoleIndex();
|
||||
String npcName = NPCPlugin.get().getName(npcRoleIndex);
|
||||
String npcName = residentMeta.getNpcNameKey();
|
||||
String npcDropListName = produceDropsMap.get(npcName);
|
||||
if (npcDropListName != null) {
|
||||
ItemDropList dropListAsset = ItemDropList.getAssetMap().getAsset(npcDropListName);
|
||||
@@ -225,14 +232,15 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void gatherProduceFromInventory(ItemContainer playerInventory) {
|
||||
public void gatherProduceFromContainer(@Nonnull ItemContainer playerInventory) {
|
||||
for (ItemStack item : this.itemContainer.removeAllItemStacks()) {
|
||||
playerInventory.addItemStack(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureSpawnResidentsInWorld(World world, Store<EntityStore> store, Vector3d coopLocation, Vector3d spawnOffset) {
|
||||
NPCPlugin npcModule = NPCPlugin.get();
|
||||
public void ensureSpawnResidentsInWorld(
|
||||
@Nonnull World world, @Nonnull Store<EntityStore> store, @Nonnull Vector3d coopLocation, @Nonnull Vector3d spawnOffset
|
||||
) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
float radiansPerSpawn = (float) (Math.PI * 2) / coopAsset.getMaxResidents();
|
||||
@@ -241,7 +249,8 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
CapturedNPCMetadata residentMeta = resident.getMetadata();
|
||||
int npcRoleIndex = residentMeta.getRoleIndex();
|
||||
String npcNameKey = residentMeta.getNpcNameKey();
|
||||
int npcRoleIndex = NPCPlugin.get().getIndex(npcNameKey);
|
||||
boolean residentDeployed = resident.getDeployedToWorld();
|
||||
PersistentRef residentEntityId = resident.getPersistentRef();
|
||||
if (!residentDeployed && residentEntityId == null) {
|
||||
@@ -251,9 +260,8 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
spawningContext.setSpawnable((ISpawnableWithModel)roleBuilder);
|
||||
if (spawningContext.set(world, residentSpawnLocation.x, residentSpawnLocation.y, residentSpawnLocation.z)
|
||||
&& spawningContext.canSpawn() == SpawnTestResult.TEST_OK) {
|
||||
Pair<Ref<EntityStore>, NPCEntity> npcPair = npcModule.spawnEntity(
|
||||
store, npcRoleIndex, spawningContext.newPosition(), Vector3f.ZERO, null, null
|
||||
);
|
||||
Pair<Ref<EntityStore>, NPCEntity> npcPair = NPCPlugin.get()
|
||||
.spawnEntity(store, npcRoleIndex, spawningContext.newPosition(), Vector3f.ZERO, null, null);
|
||||
if (npcPair == null) {
|
||||
resident.setPersistentRef(null);
|
||||
resident.setDeployedToWorld(false);
|
||||
@@ -288,40 +296,45 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureNoResidentsInWorld(Store<EntityStore> store) {
|
||||
ArrayList<CoopBlock.CoopResident> residentsToRemove = new ArrayList<>();
|
||||
public void ensureNoResidentsInWorld(@Nonnull Store<EntityStore> store) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset != null) {
|
||||
ObjectArrayList<CoopBlock.CoopResident> residentsToRemove = new ObjectArrayList<>();
|
||||
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
boolean deployed = resident.getDeployedToWorld();
|
||||
PersistentRef entityUuid = resident.getPersistentRef();
|
||||
if (deployed || entityUuid != null) {
|
||||
Ref<EntityStore> entityRef = entityUuid.getEntity(store);
|
||||
if (entityRef == null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
|
||||
if (coopResidentComponent == null) {
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
boolean deployed = resident.getDeployedToWorld();
|
||||
PersistentRef entityUuid = resident.getPersistentRef();
|
||||
if (deployed || entityUuid != null) {
|
||||
Ref<EntityStore> entityRef = entityUuid.getEntity(store);
|
||||
if (entityRef == null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
DeathComponent deathComponent = store.getComponent(entityRef, DeathComponent.getComponentType());
|
||||
if (deathComponent != null) {
|
||||
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
|
||||
if (coopResidentComponent == null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
coopResidentComponent.setMarkedForDespawn(true);
|
||||
resident.setPersistentRef(null);
|
||||
resident.setDeployedToWorld(false);
|
||||
DeathComponent deathComponent = store.getComponent(entityRef, DeathComponent.getComponentType());
|
||||
if (deathComponent != null) {
|
||||
residentsToRemove.add(resident);
|
||||
} else if (!this.getCoopAcceptsNPC(resident.metadata.getNpcNameKey())) {
|
||||
residentsToRemove.add(resident);
|
||||
} else {
|
||||
coopResidentComponent.setMarkedForDespawn(true);
|
||||
resident.setPersistentRef(null);
|
||||
resident.setDeployedToWorld(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (CoopBlock.CoopResident residentx : residentsToRemove) {
|
||||
this.residents.remove(residentx);
|
||||
for (CoopBlock.CoopResident residentx : residentsToRemove) {
|
||||
this.residents.remove(residentx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldResidentsBeInCoop(WorldTimeResource worldTimeResource) {
|
||||
public boolean shouldResidentsBeInCoop(@Nonnull WorldTimeResource worldTimeResource) {
|
||||
FarmingCoopAsset coopAsset = this.getCoopAsset();
|
||||
if (coopAsset == null) {
|
||||
return true;
|
||||
@@ -337,7 +350,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Instant getNextScheduledTick(WorldTimeResource worldTimeResource) {
|
||||
public Instant getNextScheduledTick(@Nonnull WorldTimeResource worldTimeResource) {
|
||||
Instant gameTime = worldTimeResource.getGameTime();
|
||||
LocalDateTime gameDateTime = worldTimeResource.getGameDateTime();
|
||||
int gameHour = worldTimeResource.getCurrentHour();
|
||||
@@ -366,7 +379,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleResidentDespawn(UUID entityUuid) {
|
||||
public void handleResidentDespawn(@Nonnull UUID entityUuid) {
|
||||
CoopBlock.CoopResident removedResident = null;
|
||||
|
||||
for (CoopBlock.CoopResident resident : this.residents) {
|
||||
@@ -381,7 +394,9 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleBlockBroken(World world, WorldTimeResource worldTimeResource, Store<EntityStore> store, int blockX, int blockY, int blockZ) {
|
||||
public void handleBlockBroken(
|
||||
@Nonnull World world, @Nonnull WorldTimeResource worldTimeResource, @Nonnull Store<EntityStore> store, int blockX, int blockY, int blockZ
|
||||
) {
|
||||
Vector3i location = new Vector3i(blockX, blockY, blockZ);
|
||||
world.execute(() -> this.ensureSpawnResidentsInWorld(world, store, location.toVector3d(), new Vector3d().assign(Vector3d.FORWARD)));
|
||||
this.generateProduceToInventory(worldTimeResource);
|
||||
@@ -416,6 +431,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
public static class CoopResident {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CoopBlock.CoopResident> CODEC = BuilderCodec.builder(CoopBlock.CoopResident.class, CoopBlock.CoopResident::new)
|
||||
.append(new KeyedCodec<>("Metadata", CapturedNPCMetadata.CODEC), (coop, meta) -> coop.metadata = meta, coop -> coop.metadata)
|
||||
.add()
|
||||
@@ -439,7 +455,7 @@ public class CoopBlock implements Component<ChunkStore> {
|
||||
public CoopResident() {
|
||||
}
|
||||
|
||||
public CoopResident(CapturedNPCMetadata metadata, PersistentRef persistentRef, Instant lastProduced) {
|
||||
public CoopResident(CapturedNPCMetadata metadata, @Nullable PersistentRef persistentRef, @Nonnull Instant lastProduced) {
|
||||
this.metadata = metadata;
|
||||
this.persistentRef = persistentRef;
|
||||
this.lastProduced = lastProduced;
|
||||
|
||||
@@ -8,10 +8,13 @@ import com.hypixel.hytale.component.Component;
|
||||
import com.hypixel.hytale.component.ComponentType;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import java.time.Instant;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FarmingBlock implements Component<ChunkStore> {
|
||||
@Nonnull
|
||||
public static final String DEFAULT_STAGE_SET = "Default";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<FarmingBlock> CODEC = BuilderCodec.builder(FarmingBlock.class, FarmingBlock::new)
|
||||
.append(
|
||||
new KeyedCodec<>("CurrentStageSet", Codec.STRING),
|
||||
@@ -56,13 +59,14 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
)
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private String currentStageSet = "Default";
|
||||
private float growthProgress;
|
||||
private Instant lastTickGameTime;
|
||||
private int generation;
|
||||
private String previousBlockType;
|
||||
private float spreadRate = 1.0F;
|
||||
private int executions = 0;
|
||||
private int executions;
|
||||
|
||||
public static ComponentType<ChunkStore, FarmingBlock> getComponentType() {
|
||||
return FarmingPlugin.get().getFarmingBlockComponentType();
|
||||
@@ -72,7 +76,13 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
}
|
||||
|
||||
public FarmingBlock(
|
||||
String currentStageSet, float growthProgress, Instant lastTickGameTime, int generation, String previousBlockType, float spreadRate, int executions
|
||||
@Nonnull String currentStageSet,
|
||||
float growthProgress,
|
||||
Instant lastTickGameTime,
|
||||
int generation,
|
||||
String previousBlockType,
|
||||
float spreadRate,
|
||||
int executions
|
||||
) {
|
||||
this.currentStageSet = currentStageSet;
|
||||
this.growthProgress = growthProgress;
|
||||
@@ -83,11 +93,12 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
this.executions = executions;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getCurrentStageSet() {
|
||||
return this.currentStageSet;
|
||||
}
|
||||
|
||||
public void setCurrentStageSet(String currentStageSet) {
|
||||
public void setCurrentStageSet(@Nullable String currentStageSet) {
|
||||
this.currentStageSet = currentStageSet != null ? currentStageSet : "Default";
|
||||
}
|
||||
|
||||
@@ -147,6 +158,7 @@ public class FarmingBlock implements Component<ChunkStore> {
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FarmingBlock{currentStageSet='"
|
||||
|
||||
@@ -13,7 +13,7 @@ import javax.annotation.Nullable;
|
||||
@Deprecated(forRemoval = true)
|
||||
public class FarmingBlockState implements Component<ChunkStore> {
|
||||
@Nonnull
|
||||
public static BuilderCodec<FarmingBlockState> CODEC = BuilderCodec.builder(FarmingBlockState.class, FarmingBlockState::new)
|
||||
public static final BuilderCodec<FarmingBlockState> CODEC = BuilderCodec.builder(FarmingBlockState.class, FarmingBlockState::new)
|
||||
.append(new KeyedCodec<>("BaseCrop", Codec.STRING), (state, crop) -> state.baseCrop = crop, state -> state.baseCrop)
|
||||
.add()
|
||||
.append(new KeyedCodec<>("StageStart", Codec.INSTANT), (state, start) -> state.stageStart = start, state -> state.stageStart)
|
||||
|
||||
@@ -13,10 +13,12 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TilledSoilBlock implements Component<ChunkStore> {
|
||||
public static int VERSION = 1;
|
||||
@Nonnull
|
||||
public static final BuilderCodec<TilledSoilBlock> CODEC = BuilderCodec.builder(TilledSoilBlock.class, TilledSoilBlock::new)
|
||||
.versioned()
|
||||
.codecVersion(VERSION)
|
||||
@@ -116,7 +118,8 @@ public class TilledSoilBlock implements Component<ChunkStore> {
|
||||
this.decayTime = decayTime;
|
||||
}
|
||||
|
||||
public String computeBlockType(Instant gameTime, BlockType type) {
|
||||
@Nullable
|
||||
public String computeBlockType(@Nonnull Instant gameTime, @Nonnull BlockType type) {
|
||||
boolean watered = this.hasExternalWater() || this.wateredUntil != null && this.wateredUntil.isAfter(gameTime);
|
||||
if (this.fertilized && watered) {
|
||||
return type.getBlockKeyForState("Fertilized_Watered");
|
||||
@@ -127,6 +130,7 @@ public class TilledSoilBlock implements Component<ChunkStore> {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TilledSoilBlock{planted="
|
||||
|
||||
@@ -11,7 +11,9 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesGameplayConfig {
|
||||
@Nonnull
|
||||
public static final String ID = "Memories";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesGameplayConfig> CODEC = BuilderCodec.builder(MemoriesGameplayConfig.class, MemoriesGameplayConfig::new)
|
||||
.appendInherited(
|
||||
new KeyedCodec<>("MemoriesAmountPerLevel", Codec.INT_ARRAY),
|
||||
|
||||
@@ -69,9 +69,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
|
||||
@@ -169,6 +174,7 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
this.providers.add(memoryProvider);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<String, Set<Memory>> getAllMemories() {
|
||||
return this.allMemories;
|
||||
}
|
||||
@@ -299,6 +305,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
|
||||
)
|
||||
@@ -361,6 +368,7 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
private static class RecordedMemories {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesPlugin.RecordedMemories> CODEC = BuilderCodec.builder(
|
||||
MemoriesPlugin.RecordedMemories.class, MemoriesPlugin.RecordedMemories::new
|
||||
)
|
||||
@@ -371,7 +379,9 @@ public class MemoriesPlugin extends JavaPlugin {
|
||||
}, recordedMemories -> recordedMemories.memories.toArray(Memory[]::new))
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
@Nonnull
|
||||
private final Set<Memory> memories = new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class PlayerMemories implements Component<EntityStore> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<PlayerMemories> CODEC = BuilderCodec.builder(PlayerMemories.class, PlayerMemories::new)
|
||||
.append(
|
||||
new KeyedCodec<>("Capacity", Codec.INTEGER),
|
||||
@@ -29,6 +30,7 @@ public class PlayerMemories implements Component<EntityStore> {
|
||||
}, playerMemories -> playerMemories.memories.toArray(Memory[]::new))
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
private final Set<Memory> memories = new LinkedHashSet<>();
|
||||
private int memoriesCapacity;
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ public class MemoriesConditionInteraction extends Interaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configurePacket(com.hypixel.hytale.protocol.Interaction packet) {
|
||||
protected void configurePacket(@Nonnull com.hypixel.hytale.protocol.Interaction packet) {
|
||||
super.configurePacket(packet);
|
||||
com.hypixel.hytale.protocol.MemoriesConditionInteraction p = (com.hypixel.hytale.protocol.MemoriesConditionInteraction)packet;
|
||||
p.memoriesNext = new Int2IntOpenHashMap(this.next.size());
|
||||
@@ -156,11 +156,9 @@ public class MemoriesConditionInteraction extends Interaction {
|
||||
|
||||
@Override
|
||||
public boolean walk(@Nonnull Collector collector, @Nonnull InteractionContext context) {
|
||||
if (this.next != null) {
|
||||
for (Entry<String> entry : this.next.int2ObjectEntrySet()) {
|
||||
if (InteractionManager.walkInteraction(collector, context, new MemoriesConditionInteraction.MemoriesTag(entry.getIntKey()), entry.getValue())) {
|
||||
return true;
|
||||
}
|
||||
for (Entry<String> entry : this.next.int2ObjectEntrySet()) {
|
||||
if (InteractionManager.walkInteraction(collector, context, new MemoriesConditionInteraction.MemoriesTag(entry.getIntKey()), entry.getValue())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +170,7 @@ public class MemoriesConditionInteraction extends Interaction {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public WaitForDataFrom getWaitForDataFrom() {
|
||||
return WaitForDataFrom.Server;
|
||||
|
||||
@@ -21,6 +21,15 @@ import com.hypixel.hytale.server.core.util.NotificationUtil;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SetMemoriesCapacityInteraction extends SimpleInstantInteraction {
|
||||
@Nonnull
|
||||
private static final String NOTIFICATION_ICON_MEMORIES = "NotificationIcons/MemoriesIcon.png";
|
||||
@Nonnull
|
||||
private static final Message MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_NOTIFICATION = Message.translation(
|
||||
"server.memories.general.featureUnlockedNotification"
|
||||
);
|
||||
@Nonnull
|
||||
private static final Message MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_MESSAGE = Message.translation("server.memories.general.featureUnlockedMessage");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SetMemoriesCapacityInteraction> CODEC = BuilderCodec.builder(
|
||||
SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction::new, SimpleInstantInteraction.CODEC
|
||||
)
|
||||
@@ -48,15 +57,14 @@ public class SetMemoriesCapacityInteraction extends SimpleInstantInteraction {
|
||||
memoriesComponent.setMemoriesCapacity(this.capacity);
|
||||
if (previousCapacity <= 0) {
|
||||
PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
|
||||
|
||||
assert playerRefComponent != null;
|
||||
|
||||
PacketHandler playerConnection = playerRefComponent.getPacketHandler();
|
||||
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(true));
|
||||
NotificationUtil.sendNotification(
|
||||
playerConnection, Message.translation("server.memories.general.featureUnlockedNotification"), null, "NotificationIcons/MemoriesIcon.png"
|
||||
);
|
||||
playerRefComponent.sendMessage(Message.translation("server.memories.general.featureUnlockedMessage"));
|
||||
if (playerRefComponent != null) {
|
||||
PacketHandler playerConnection = playerRefComponent.getPacketHandler();
|
||||
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(true));
|
||||
NotificationUtil.sendNotification(
|
||||
playerConnection, MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_NOTIFICATION, null, "NotificationIcons/MemoriesIcon.png"
|
||||
);
|
||||
playerRefComponent.sendMessage(MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
context.getState().state = InteractionState.Finished;
|
||||
|
||||
@@ -6,6 +6,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class Memory {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<Memory> CODEC = new CodecMapCodec<>();
|
||||
|
||||
public abstract String getId();
|
||||
|
||||
@@ -53,6 +53,8 @@ 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())
|
||||
@@ -119,7 +121,7 @@ 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";
|
||||
@@ -157,6 +159,7 @@ public class NPCMemory extends Memory {
|
||||
return this.foundLocationZoneNameKey;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Message getLocationMessage() {
|
||||
if (this.foundLocationGeneralNameKey != null) {
|
||||
return Message.translation(this.foundLocationGeneralNameKey);
|
||||
@@ -166,7 +169,7 @@ 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)) {
|
||||
@@ -184,6 +187,7 @@ public class NPCMemory extends Memory {
|
||||
return 31 * result + Boolean.hashCode(this.isMemoriesNameOverridden);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NPCMemory{npcRole='"
|
||||
@@ -200,7 +204,7 @@ 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()
|
||||
TransformComponent.getComponentType(), Player.getComponentType(), PlayerRef.getComponentType(), PlayerMemories.getComponentType()
|
||||
);
|
||||
private final double radius;
|
||||
|
||||
@@ -248,10 +252,7 @@ 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()) {
|
||||
if (role != null && role.isMemory()) {
|
||||
temp.isMemoriesNameOverridden = role.isMemoriesNameOverriden();
|
||||
temp.npcRole = temp.isMemoriesNameOverridden ? role.getMemoriesNameOverride() : npcComponent.getRoleName();
|
||||
temp.memoryTitleKey = role.getNameTranslationKey();
|
||||
@@ -268,29 +269,30 @@ public class NPCMemory extends Memory {
|
||||
);
|
||||
temp = new NPCMemory();
|
||||
TransformComponent npcTransformComponent = commandBuffer.getComponent(npcRef, TransformComponent.getComponentType());
|
||||
|
||||
assert npcTransformComponent != null;
|
||||
|
||||
MemoriesGameplayConfig memoriesGameplayConfig = MemoriesGameplayConfig.get(store.getExternalData().getWorld().getGameplayConfig());
|
||||
if (memoriesGameplayConfig != null) {
|
||||
ItemStack memoryItemStack = new ItemStack(memoriesGameplayConfig.getMemoriesCatchItemId());
|
||||
Vector3d memoryItemHolderPosition = npcTransformComponent.getPosition().clone();
|
||||
BoundingBox boundingBoxComponent = commandBuffer.getComponent(npcRef, BoundingBox.getComponentType());
|
||||
if (boundingBoxComponent != null) {
|
||||
memoryItemHolderPosition.y = memoryItemHolderPosition.y + boundingBoxComponent.getBoundingBox().middleY();
|
||||
}
|
||||
|
||||
Holder<EntityStore> memoryItemHolder = ItemComponent.generatePickedUpItem(
|
||||
memoryItemStack, memoryItemHolderPosition, commandBuffer, ref
|
||||
if (npcTransformComponent != null) {
|
||||
MemoriesGameplayConfig memoriesGameplayConfig = MemoriesGameplayConfig.get(
|
||||
store.getExternalData().getWorld().getGameplayConfig()
|
||||
);
|
||||
float memoryCatchItemLifetimeS = 0.62F;
|
||||
PickupItemComponent pickupItemComponent = memoryItemHolder.getComponent(PickupItemComponent.getComponentType());
|
||||
if (memoriesGameplayConfig != null) {
|
||||
ItemStack memoryItemStack = new ItemStack(memoriesGameplayConfig.getMemoriesCatchItemId());
|
||||
Vector3d memoryItemHolderPosition = npcTransformComponent.getPosition().clone();
|
||||
BoundingBox boundingBoxComponent = commandBuffer.getComponent(npcRef, BoundingBox.getComponentType());
|
||||
if (boundingBoxComponent != null) {
|
||||
memoryItemHolderPosition.y = memoryItemHolderPosition.y + boundingBoxComponent.getBoundingBox().middleY();
|
||||
}
|
||||
|
||||
assert pickupItemComponent != null;
|
||||
Holder<EntityStore> memoryItemHolder = ItemComponent.generatePickedUpItem(
|
||||
memoryItemStack, memoryItemHolderPosition, commandBuffer, ref
|
||||
);
|
||||
float memoryCatchItemLifetimeS = 0.62F;
|
||||
PickupItemComponent pickupItemComponent = memoryItemHolder.getComponent(PickupItemComponent.getComponentType());
|
||||
|
||||
pickupItemComponent.setInitialLifeTime(0.62F);
|
||||
commandBuffer.addEntity(memoryItemHolder, AddReason.SPAWN);
|
||||
displayCatchEntityParticles(memoriesGameplayConfig, memoryItemHolderPosition, npcRef, commandBuffer);
|
||||
assert pickupItemComponent != null;
|
||||
|
||||
pickupItemComponent.setInitialLifeTime(0.62F);
|
||||
commandBuffer.addEntity(memoryItemHolder, AddReason.SPAWN);
|
||||
displayCatchEntityParticles(memoriesGameplayConfig, memoryItemHolderPosition, npcRef, commandBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,7 +303,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 +322,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 +340,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -356,10 +354,9 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
|
||||
if (memory instanceof NPCMemory npcMemory) {
|
||||
Message locationNameKey = npcMemory.getLocationMessage();
|
||||
long capturedTimestamp = npcMemory.getCapturedTimestamp();
|
||||
String timeString = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(Locale.getDefault())
|
||||
.format(Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC));
|
||||
Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn").param("location", locationNameKey).param("time", timeString);
|
||||
Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn")
|
||||
.param("location", locationNameKey)
|
||||
.param("dateValue", Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC).toString());
|
||||
commandBuilder.set("#MemoryTimeLocation.TextSpans", memoryLocationTimeText);
|
||||
}
|
||||
|
||||
@@ -378,13 +375,18 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
|
||||
MemoriesInfo,
|
||||
SelectMemory;
|
||||
|
||||
@Nonnull
|
||||
public static final Codec<MemoriesPage.PageAction> CODEC = new EnumCodec<>(MemoriesPage.PageAction.class);
|
||||
}
|
||||
|
||||
public static class PageEventData {
|
||||
@Nonnull
|
||||
public static final String KEY_ACTION = "Action";
|
||||
@Nonnull
|
||||
public static final String KEY_CATEGORY = "Category";
|
||||
@Nonnull
|
||||
public static final String KEY_MEMORY_ID = "MemoryId";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesPage.PageEventData> CODEC = BuilderCodec.builder(
|
||||
MemoriesPage.PageEventData.class, MemoriesPage.PageEventData::new
|
||||
)
|
||||
|
||||
@@ -2,17 +2,25 @@ package com.hypixel.hytale.builtin.adventure.memories.page;
|
||||
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.protocol.BlockPosition;
|
||||
import com.hypixel.hytale.server.core.entity.InteractionContext;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesPageSupplier implements OpenCustomUIInteraction.CustomPageSupplier {
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomUIPage tryCreate(Ref<EntityStore> ref, ComponentAccessor<EntityStore> componentAccessor, PlayerRef playerRef, InteractionContext context) {
|
||||
return new MemoriesPage(playerRef, context.getTargetBlock());
|
||||
public CustomUIPage tryCreate(
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
|
||||
@Nonnull PlayerRef playerRef,
|
||||
@Nonnull InteractionContext context
|
||||
) {
|
||||
BlockPosition targetBlock = context.getTargetBlock();
|
||||
return targetBlock == null ? null : new MemoriesPage(playerRef, targetBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,11 +51,14 @@ public class MemoriesUnlockedPage extends InteractiveCustomUIPage<MemoriesUnlock
|
||||
public static enum PageAction {
|
||||
DiscoverMemories;
|
||||
|
||||
@Nonnull
|
||||
public static final Codec<MemoriesUnlockedPage.PageAction> CODEC = new EnumCodec<>(MemoriesUnlockedPage.PageAction.class);
|
||||
}
|
||||
|
||||
public static class PageEventData {
|
||||
@Nonnull
|
||||
public static final String KEY_ACTION = "Action";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<MemoriesUnlockedPage.PageEventData> CODEC = BuilderCodec.builder(
|
||||
MemoriesUnlockedPage.PageEventData.class, MemoriesUnlockedPage.PageEventData::new
|
||||
)
|
||||
|
||||
@@ -2,17 +2,25 @@ package com.hypixel.hytale.builtin.adventure.memories.page;
|
||||
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.protocol.BlockPosition;
|
||||
import com.hypixel.hytale.server.core.entity.InteractionContext;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesUnlockedPageSuplier implements OpenCustomUIInteraction.CustomPageSupplier {
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomUIPage tryCreate(Ref<EntityStore> ref, ComponentAccessor<EntityStore> componentAccessor, PlayerRef playerRef, InteractionContext context) {
|
||||
return new MemoriesUnlockedPage(playerRef, context.getTargetBlock());
|
||||
public CustomUIPage tryCreate(
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
|
||||
@Nonnull PlayerRef playerRef,
|
||||
@Nonnull InteractionContext context
|
||||
) {
|
||||
BlockPosition targetBlock = context.getTargetBlock();
|
||||
return targetBlock == null ? null : new MemoriesUnlockedPage(playerRef, targetBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.hypixel.hytale.codec.Codec;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ForgottenTempleConfig {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ForgottenTempleConfig> CODEC = BuilderCodec.builder(ForgottenTempleConfig.class, ForgottenTempleConfig::new)
|
||||
.append(new KeyedCodec<>("MinYRespawn", Codec.DOUBLE), (config, o) -> config.minYRespawn = o, config -> config.minYRespawn)
|
||||
.documentation("The Y at which players are teleported back to spawn.")
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TempleRespawnPlayersSystem extends DelayedEntitySystem<EntityStore> {
|
||||
@Nonnull
|
||||
public static final Query<EntityStore> QUERY = Query.and(PlayerRef.getComponentType(), TransformComponent.getComponentType());
|
||||
|
||||
public TempleRespawnPlayersSystem() {
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MemoriesWindow extends Window {
|
||||
@Nonnull
|
||||
private final JsonObject windowData = new JsonObject();
|
||||
|
||||
public MemoriesWindow() {
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.Ref;
|
||||
import com.hypixel.hytale.component.ResourceType;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
@@ -56,45 +57,43 @@ 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
|
||||
);
|
||||
entityStoreRegistry.registerSystem(new SpawnBeaconCheckRemovalSystem());
|
||||
this.killTrackerResourceType = entityStoreRegistry.registerResource(KillTrackerResource.class, KillTrackerResource::new);
|
||||
entityStoreRegistry.registerSystem(new KillTrackerSystem());
|
||||
NPCPlugin.get()
|
||||
.registerCoreComponentType("CompleteTask", BuilderActionCompleteTask::new)
|
||||
.registerCoreComponentType("StartObjective", BuilderActionStartObjective::new)
|
||||
@@ -114,48 +113,51 @@ public class NPCObjectivesPlugin extends JavaPlugin {
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull UUID npcId, @Nonnull String taskId
|
||||
) {
|
||||
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
|
||||
ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore();
|
||||
Map<String, Set<UUID>> entityObjectiveUUIDs = objectiveDataStore.getEntityTasksForPlayer(uuidComponent.getUuid());
|
||||
if (entityObjectiveUUIDs == null) {
|
||||
if (uuidComponent == null) {
|
||||
return null;
|
||||
} else {
|
||||
Set<UUID> objectiveUUIDsForTaskId = entityObjectiveUUIDs.get(taskId);
|
||||
if (objectiveUUIDsForTaskId == null) {
|
||||
ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore();
|
||||
Map<String, Set<UUID>> entityObjectiveUUIDs = objectiveDataStore.getEntityTasksForPlayer(uuidComponent.getUuid());
|
||||
if (entityObjectiveUUIDs == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (UUID objectiveUUID : objectiveUUIDsForTaskId) {
|
||||
Objective objective = objectiveDataStore.getObjective(objectiveUUID);
|
||||
if (objective != null) {
|
||||
for (ObjectiveTask task : objective.getCurrentTasks()) {
|
||||
if (task instanceof UseEntityObjectiveTask useEntityTask) {
|
||||
UseEntityObjectiveTaskAsset taskAsset = useEntityTask.getAsset();
|
||||
if (taskAsset.getTaskId().equals(taskId)) {
|
||||
if (!useEntityTask.increaseTaskCompletion(store, ref, 1, objective, playerRef, npcId)) {
|
||||
return null;
|
||||
}
|
||||
Set<UUID> objectiveUUIDsForTaskId = entityObjectiveUUIDs.get(taskId);
|
||||
if (objectiveUUIDsForTaskId == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (UUID objectiveUUID : objectiveUUIDsForTaskId) {
|
||||
Objective objective = objectiveDataStore.getObjective(objectiveUUID);
|
||||
if (objective != null) {
|
||||
ObjectiveTask[] currentTasks = objective.getCurrentTasks();
|
||||
if (currentTasks != null) {
|
||||
for (ObjectiveTask task : currentTasks) {
|
||||
if (task instanceof UseEntityObjectiveTask useEntityTask) {
|
||||
UseEntityObjectiveTaskAsset taskAsset = useEntityTask.getAsset();
|
||||
if (taskAsset.getTaskId().equals(taskId)) {
|
||||
if (!useEntityTask.increaseTaskCompletion(store, ref, 1, objective, playerRef, npcId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return taskAsset.getAnimationIdToPlay();
|
||||
return taskAsset.getAnimationIdToPlay();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void startObjective(@Nonnull Ref<EntityStore> playerReference, @Nonnull String taskId, @Nonnull Store<EntityStore> store) {
|
||||
UUIDComponent uuidComponent = store.getComponent(playerReference, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
|
||||
World world = store.getExternalData().getWorld();
|
||||
ObjectivePlugin.get().startObjective(taskId, Set.of(uuidComponent.getUuid()), world.getWorldConfig().getUuid(), null, store);
|
||||
public static void startObjective(@Nonnull Ref<EntityStore> playerRef, @Nonnull String taskId, @Nonnull Store<EntityStore> store) {
|
||||
UUIDComponent uuidComponent = store.getComponent(playerRef, UUIDComponent.getComponentType());
|
||||
if (uuidComponent != null) {
|
||||
World world = store.getExternalData().getWorld();
|
||||
ObjectivePlugin.get().startObjective(taskId, Set.of(uuidComponent.getUuid()), world.getWorldConfig().getUuid(), null, store);
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceType<EntityStore, KillTrackerResource> getKillTrackerResourceType() {
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BountyObjectiveTaskAsset extends ObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BountyObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
BountyObjectiveTaskAsset.class, BountyObjectiveTaskAsset::new, ObjectiveTaskAsset.BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
KillObjectiveTaskAsset.class, KillObjectiveTaskAsset::new, CountObjectiveTaskAsset.CODEC
|
||||
)
|
||||
@@ -45,7 +46,7 @@ public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset {
|
||||
if (!super.matchesAsset0(task)) {
|
||||
return false;
|
||||
} else {
|
||||
return !(task instanceof KillObjectiveTaskAsset) ? false : ((KillObjectiveTaskAsset)task).npcGroupId.equals(this.npcGroupId);
|
||||
return task instanceof KillObjectiveTaskAsset killObjectiveTaskAsset ? killObjectiveTaskAsset.npcGroupId.equals(this.npcGroupId) : false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
KillSpawnBeaconObjectiveTaskAsset.class, KillSpawnBeaconObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC
|
||||
)
|
||||
@@ -56,9 +57,9 @@ public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
if (!super.matchesAsset0(task)) {
|
||||
return false;
|
||||
} else {
|
||||
return !(task instanceof KillSpawnBeaconObjectiveTaskAsset)
|
||||
? false
|
||||
: Arrays.equals((Object[])((KillSpawnBeaconObjectiveTaskAsset)task).spawnBeacons, (Object[])this.spawnBeacons);
|
||||
return task instanceof KillSpawnBeaconObjectiveTaskAsset killSpawnBeaconObjectiveTaskAsset
|
||||
? Arrays.equals((Object[])killSpawnBeaconObjectiveTaskAsset.spawnBeacons, (Object[])this.spawnBeacons)
|
||||
: false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +70,7 @@ public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
}
|
||||
|
||||
public static class ObjectiveSpawnBeacon {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon> CODEC = BuilderCodec.builder(
|
||||
KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon.class, KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon::new
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillSpawnMarkerObjectiveTaskAsset extends KillObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnMarkerObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
KillSpawnMarkerObjectiveTaskAsset.class, KillSpawnMarkerObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC
|
||||
)
|
||||
|
||||
@@ -25,41 +25,42 @@ public class ActionCompleteTask extends ActionPlayAnimation {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
|
||||
Ref<EntityStore> target = role.getStateSupport().getInteractionIterationTarget();
|
||||
boolean targetExists = target != null && !store.getArchetype(target).contains(DeathComponent.getComponentType());
|
||||
Ref<EntityStore> targetRef = role.getStateSupport().getInteractionIterationTarget();
|
||||
boolean targetExists = targetRef != null && targetRef.isValid() && !store.getArchetype(targetRef).contains(DeathComponent.getComponentType());
|
||||
return super.canExecute(ref, role, sensorInfo, dt, store) && targetExists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
|
||||
UUIDComponent parentUuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
|
||||
assert parentUuidComponent != null;
|
||||
|
||||
Ref<EntityStore> targetPlayerReference = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (targetPlayerReference == null) {
|
||||
if (parentUuidComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
PlayerRef targetPlayerRefComponent = store.getComponent(targetPlayerReference, PlayerRef.getComponentType());
|
||||
if (targetPlayerRefComponent == null) {
|
||||
Ref<EntityStore> targetPlayerReference = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (targetPlayerReference == null) {
|
||||
return false;
|
||||
} else {
|
||||
List<String> activeTasks = role.getEntitySupport().getTargetPlayerActiveTasks();
|
||||
String animation = null;
|
||||
if (activeTasks != null) {
|
||||
for (int i = 0; i < activeTasks.size(); i++) {
|
||||
animation = NPCObjectivesPlugin.updateTaskCompletion(
|
||||
store, targetPlayerReference, targetPlayerRefComponent, parentUuidComponent.getUuid(), activeTasks.get(i)
|
||||
);
|
||||
PlayerRef targetPlayerRefComponent = store.getComponent(targetPlayerReference, PlayerRef.getComponentType());
|
||||
if (targetPlayerRefComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
List<String> activeTasks = role.getEntitySupport().getTargetPlayerActiveTasks();
|
||||
String animation = null;
|
||||
if (activeTasks != null) {
|
||||
for (int i = 0; i < activeTasks.size(); i++) {
|
||||
animation = NPCObjectivesPlugin.updateTaskCompletion(
|
||||
store, targetPlayerReference, targetPlayerRefComponent, parentUuidComponent.getUuid(), activeTasks.get(i)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.playAnimation && animation != null) {
|
||||
this.setAnimationId(animation);
|
||||
super.execute(ref, role, sensorInfo, dt, store);
|
||||
}
|
||||
if (this.playAnimation && animation != null) {
|
||||
this.setAnimationId(animation);
|
||||
super.execute(ref, role, sensorInfo, dt, store);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,12 @@ public class ActionStartObjective extends ActionBase {
|
||||
@Override
|
||||
public boolean execute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
|
||||
super.execute(ref, role, sensorInfo, dt, store);
|
||||
NPCObjectivesPlugin.startObjective(role.getStateSupport().getInteractionIterationTarget(), this.objectiveId, store);
|
||||
return true;
|
||||
Ref<EntityStore> interactionIterationTarget = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (interactionIterationTarget == null) {
|
||||
return false;
|
||||
} else {
|
||||
NPCObjectivesPlugin.startObjective(interactionIterationTarget, this.objectiveId, store);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,39 +30,42 @@ public class SensorHasTask extends SensorBase {
|
||||
public boolean matches(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, double dt, @Nonnull Store<EntityStore> store) {
|
||||
if (!super.matches(ref, role, dt, store)) {
|
||||
return false;
|
||||
} else {
|
||||
Ref<EntityStore> target = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (target == null) {
|
||||
return false;
|
||||
} else {
|
||||
Archetype<EntityStore> targetArchetype = store.getArchetype(target);
|
||||
} else if (this.tasksById != null && this.tasksById.length != 0) {
|
||||
Ref<EntityStore> targetRef = role.getStateSupport().getInteractionIterationTarget();
|
||||
if (targetRef != null && targetRef.isValid()) {
|
||||
Archetype<EntityStore> targetArchetype = store.getArchetype(targetRef);
|
||||
if (targetArchetype.contains(DeathComponent.getComponentType())) {
|
||||
return false;
|
||||
} else {
|
||||
UUIDComponent targetUuidComponent = store.getComponent(target, UUIDComponent.getComponentType());
|
||||
UUIDComponent targetUuidComponent = store.getComponent(targetRef, UUIDComponent.getComponentType());
|
||||
if (targetUuidComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
UUID targetUuid = targetUuidComponent.getUuid();
|
||||
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
if (uuidComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
UUID uuid = uuidComponent.getUuid();
|
||||
EntitySupport entitySupport = role.getEntitySupport();
|
||||
boolean match = false;
|
||||
|
||||
assert targetUuidComponent != null;
|
||||
for (String taskById : this.tasksById) {
|
||||
if (NPCObjectivesPlugin.hasTask(targetUuid, uuid, taskById)) {
|
||||
match = true;
|
||||
entitySupport.addTargetPlayerActiveTask(taskById);
|
||||
}
|
||||
}
|
||||
|
||||
UUID targetUuid = targetUuidComponent.getUuid();
|
||||
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
|
||||
UUID uuid = uuidComponent.getUuid();
|
||||
NPCObjectivesPlugin objectiveSystem = NPCObjectivesPlugin.get();
|
||||
EntitySupport entitySupport = role.getEntitySupport();
|
||||
boolean match = false;
|
||||
|
||||
for (String taskById : this.tasksById) {
|
||||
if (NPCObjectivesPlugin.hasTask(targetUuid, uuid, taskById)) {
|
||||
match = true;
|
||||
entitySupport.addTargetPlayerActiveTask(taskById);
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionCompleteTask extends BuilderActionPlayAnimation {
|
||||
@Nonnull
|
||||
protected final BooleanHolder playAnimation = new BooleanHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionStartObjective extends BuilderActionBase {
|
||||
@Nonnull
|
||||
protected final AssetHolder objectiveId = new AssetHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BuilderSensorHasTask extends BuilderSensorBase {
|
||||
@Nonnull
|
||||
protected final StringArrayHolder tasksById = new StringArrayHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveExistsValidator extends AssetValidator {
|
||||
@Nonnull
|
||||
private static final ObjectiveExistsValidator DEFAULT_INSTANCE = new ObjectiveExistsValidator();
|
||||
|
||||
private ObjectiveExistsValidator() {
|
||||
@@ -38,6 +39,7 @@ public class ObjectiveExistsValidator extends AssetValidator {
|
||||
return ObjectiveAsset.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ObjectiveExistsValidator required() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
@@ -10,17 +10,18 @@ import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillTrackerResource implements Resource<EntityStore> {
|
||||
@Nonnull
|
||||
private final List<KillTaskTransaction> killTasks = new ObjectArrayList<>();
|
||||
|
||||
public static ResourceType<EntityStore, KillTrackerResource> getResourceType() {
|
||||
return NPCObjectivesPlugin.get().getKillTrackerResourceType();
|
||||
}
|
||||
|
||||
public void watch(KillTaskTransaction task) {
|
||||
public void watch(@Nonnull KillTaskTransaction task) {
|
||||
this.killTasks.add(task);
|
||||
}
|
||||
|
||||
public void unwatch(KillTaskTransaction task) {
|
||||
public void unwatch(@Nonnull KillTaskTransaction task) {
|
||||
this.killTasks.remove(task);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
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;
|
||||
@@ -24,14 +25,20 @@ public class KillTrackerSystem extends DeathSystems.OnDeathSystem {
|
||||
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, NPCEntity.getComponentType());
|
||||
|
||||
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(KillTrackerResource.getResourceType());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.hypixel.hytale.builtin.adventure.npcobjectives.transaction.KillTaskTr
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.Objective;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.config.task.ObjectiveTaskAsset;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.markers.ObjectiveTaskMarker;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.task.ObjectiveTask;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.transaction.RegistrationTransactionRecord;
|
||||
import com.hypixel.hytale.builtin.adventure.objectives.transaction.SpawnEntityTransactionRecord;
|
||||
@@ -15,25 +16,29 @@ import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Transform;
|
||||
import com.hypixel.hytale.math.vector.Vector3d;
|
||||
import com.hypixel.hytale.math.vector.Vector3f;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.protocol.packets.worldmap.MapMarker;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.entity.UUIDComponent;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.npc.INonPlayerCharacter;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.core.util.PositionUtil;
|
||||
import com.hypixel.hytale.server.npc.NPCPlugin;
|
||||
import com.hypixel.hytale.server.npc.entities.NPCEntity;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
@Nonnull
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BountyObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
BountyObjectiveTask.class, BountyObjectiveTask::new, ObjectiveTask.BASE_CODEC
|
||||
)
|
||||
@@ -65,36 +70,47 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
return (BountyObjectiveTaskAsset)super.getAsset();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Nullable
|
||||
@Override
|
||||
protected TransactionRecord[] setup0(@Nonnull Objective objective, @Nonnull World world, @Nonnull Store<EntityStore> store) {
|
||||
if (this.serializedTransactionRecords != null) {
|
||||
return RegistrationTransactionRecord.append(this.serializedTransactionRecords, this.eventRegistry);
|
||||
} else {
|
||||
Vector3d objectivePosition = objective.getPosition(store);
|
||||
|
||||
assert objectivePosition != null;
|
||||
|
||||
Vector3i spawnPosition = this.getAsset().getWorldLocationProvider().runCondition(world, objectivePosition.clone().floor().toVector3i());
|
||||
TransactionRecord[] transactionRecords = new TransactionRecord[2];
|
||||
Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair = NPCPlugin.get()
|
||||
.spawnNPC(store, this.getAsset().getNpcId(), null, spawnPosition.toVector3d(), Vector3f.ZERO);
|
||||
Ref<EntityStore> npcReference = npcPair.first();
|
||||
UUIDComponent npcUuidComponent = store.getComponent(npcReference, UUIDComponent.getComponentType());
|
||||
|
||||
assert npcUuidComponent != null;
|
||||
|
||||
UUID npcUuid = npcUuidComponent.getUuid();
|
||||
ObjectivePlugin.get().getLogger().at(Level.INFO).log("Spawned Entity '" + this.getAsset().getNpcId() + "' at position: " + spawnPosition);
|
||||
transactionRecords[0] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), npcUuid);
|
||||
this.entityUuid = npcUuid;
|
||||
this.addMarker(
|
||||
new MapMarker(getBountyMarkerIDFromUUID(npcUuid), "Bounty Target", "Home.png", PositionUtil.toTransformPacket(new Transform(spawnPosition)), null)
|
||||
);
|
||||
KillTaskTransaction transaction = new KillTaskTransaction(this, objective, store);
|
||||
store.getResource(KillTrackerResource.getResourceType()).watch(transaction);
|
||||
transactionRecords[1] = transaction;
|
||||
return transactionRecords;
|
||||
if (objectivePosition == null) {
|
||||
return null;
|
||||
} else {
|
||||
Vector3i spawnPosition = this.getAsset().getWorldLocationProvider().runCondition(world, objectivePosition.clone().floor().toVector3i());
|
||||
if (spawnPosition == null) {
|
||||
return null;
|
||||
} else {
|
||||
TransactionRecord[] transactionRecords = new TransactionRecord[2];
|
||||
String npcId = this.getAsset().getNpcId();
|
||||
Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair = NPCPlugin.get().spawnNPC(store, npcId, null, spawnPosition.toVector3d(), Vector3f.ZERO);
|
||||
if (npcPair == null) {
|
||||
return null;
|
||||
} else {
|
||||
Ref<EntityStore> npcReference = npcPair.first();
|
||||
UUIDComponent npcUuidComponent = store.getComponent(npcReference, UUIDComponent.getComponentType());
|
||||
if (npcUuidComponent == null) {
|
||||
return null;
|
||||
} else {
|
||||
UUID npcUuid = npcUuidComponent.getUuid();
|
||||
ObjectivePlugin.get().getLogger().at(Level.INFO).log("Spawned Entity '" + npcId + "' at position: " + spawnPosition);
|
||||
transactionRecords[0] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), npcUuid);
|
||||
this.entityUuid = npcUuid;
|
||||
ObjectiveTaskMarker marker = new ObjectiveTaskMarker(
|
||||
getBountyMarkerIDFromUUID(npcUuid), new Transform(spawnPosition), "Home.png", Message.translation("server.objectives.bounty.marker")
|
||||
);
|
||||
this.addMarker(marker);
|
||||
KillTaskTransaction transaction = new KillTaskTransaction(this, objective, store);
|
||||
store.getResource(KillTrackerResource.getResourceType()).watch(transaction);
|
||||
transactionRecords[1] = transaction;
|
||||
return transactionRecords;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +126,7 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
|
||||
@Override
|
||||
public void checkKilledEntity(
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> npcRef, @Nonnull Objective objective, NPCEntity npc, Damage damageInfo
|
||||
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> npcRef, @Nonnull Objective objective, @Nonnull NPCEntity npc, @Nonnull Damage damageInfo
|
||||
) {
|
||||
UUIDComponent uuidComponent = store.getComponent(npcRef, UUIDComponent.getComponentType());
|
||||
|
||||
@@ -129,7 +145,8 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
|
||||
@Nonnull
|
||||
public com.hypixel.hytale.protocol.ObjectiveTask toPacket(@Nonnull Objective objective) {
|
||||
com.hypixel.hytale.protocol.ObjectiveTask packet = new com.hypixel.hytale.protocol.ObjectiveTask();
|
||||
packet.taskDescriptionKey = this.asset.getDescriptionKey(objective.getObjectiveId(), this.taskSetIndex, this.taskIndex);
|
||||
packet.taskDescriptionKey = Message.translation(this.asset.getDescriptionKey(objective.getObjectiveId(), this.taskSetIndex, this.taskIndex))
|
||||
.getFormattedMessage();
|
||||
packet.currentCompletion = this.completed ? 1 : 0;
|
||||
packet.completionNeeded = 1;
|
||||
return packet;
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillNPCObjectiveTask extends KillObjectiveTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillNPCObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
KillNPCObjectiveTask.class, KillNPCObjectiveTask::new, KillObjectiveTask.CODEC
|
||||
)
|
||||
|
||||
@@ -8,8 +8,6 @@ import com.hypixel.hytale.builtin.tagset.config.NPCGroup;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.entity.Entity;
|
||||
import com.hypixel.hytale.server.core.entity.EntityUtils;
|
||||
import com.hypixel.hytale.server.core.entity.UUIDComponent;
|
||||
import com.hypixel.hytale.server.core.entity.entities.Player;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
|
||||
@@ -18,6 +16,7 @@ import com.hypixel.hytale.server.npc.entities.NPCEntity;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class KillObjectiveTask extends CountObjectiveTask implements KillTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillObjectiveTask> CODEC = BuilderCodec.abstractBuilder(KillObjectiveTask.class, CountObjectiveTask.CODEC).build();
|
||||
|
||||
public KillObjectiveTask(@Nonnull KillObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) {
|
||||
@@ -41,16 +40,14 @@ public abstract class KillObjectiveTask extends CountObjectiveTask implements Ki
|
||||
if (index == Integer.MIN_VALUE) {
|
||||
throw new IllegalArgumentException("Unknown npc group! " + key);
|
||||
} else if (TagSetPlugin.get(NPCGroup.class).tagInSet(index, npc.getNPCTypeIndex())) {
|
||||
if (info.getSource() instanceof Damage.EntitySource) {
|
||||
Ref<EntityStore> attackerEntityRef = ((Damage.EntitySource)info.getSource()).getRef();
|
||||
Entity attackerEntity = EntityUtils.getEntity(attackerEntityRef, attackerEntityRef.getStore());
|
||||
if (attackerEntity instanceof Player) {
|
||||
UUIDComponent attackerUuidComponent = store.getComponent(attackerEntityRef, UUIDComponent.getComponentType());
|
||||
|
||||
assert attackerUuidComponent != null;
|
||||
|
||||
if (objective.getActivePlayerUUIDs().contains(attackerUuidComponent.getUuid())) {
|
||||
this.increaseTaskCompletion(store, npcRef, 1, objective);
|
||||
if (info.getSource() instanceof Damage.EntitySource entitySource) {
|
||||
Ref var11 = entitySource.getRef();
|
||||
if (store.getArchetype(var11).contains(Player.getComponentType())) {
|
||||
UUIDComponent sourceUuidComponent = store.getComponent(var11, UUIDComponent.getComponentType());
|
||||
if (sourceUuidComponent != null) {
|
||||
if (objective.getActivePlayerUUIDs().contains(sourceUuidComponent.getUuid())) {
|
||||
this.increaseTaskCompletion(store, npcRef, 1, objective);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Vector3d;
|
||||
import com.hypixel.hytale.math.vector.Vector3f;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.server.core.entity.UUIDComponent;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
@@ -31,6 +32,7 @@ import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnBeaconObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
KillSpawnBeaconObjectiveTask.class, KillSpawnBeaconObjectiveTask::new, KillObjectiveTask.CODEC
|
||||
)
|
||||
@@ -91,7 +93,12 @@ public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
|
||||
|
||||
WorldLocationProvider worldLocationCondition = spawnBeaconConfig.getWorldLocationProvider();
|
||||
if (worldLocationCondition != null) {
|
||||
spawnPosition = worldLocationCondition.runCondition(world, spawnPosition.toVector3i()).toVector3d();
|
||||
Vector3i potentialSpawnLocation = worldLocationCondition.runCondition(world, spawnPosition.toVector3i());
|
||||
if (potentialSpawnLocation != null) {
|
||||
spawnPosition = potentialSpawnLocation.toVector3d();
|
||||
} else {
|
||||
spawnPosition = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnPosition == null) {
|
||||
@@ -103,11 +110,12 @@ public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
|
||||
);
|
||||
spawnBeaconPair.second().setObjectiveUUID(objective.getObjectiveUUID());
|
||||
UUIDComponent spawnBeaconUuidComponent = componentAccessor.getComponent(spawnBeaconPair.first(), UUIDComponent.getComponentType());
|
||||
|
||||
assert spawnBeaconUuidComponent != null;
|
||||
|
||||
logger.at(Level.INFO).log("Spawned SpawnBeacon '" + spawnBeaconId + "' at position: " + position);
|
||||
transactionRecords[i] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), spawnBeaconUuidComponent.getUuid());
|
||||
if (spawnBeaconUuidComponent == null) {
|
||||
transactionRecords[i] = new WorldTransactionRecord().fail("Failed to retrieve UUID component for spawned beacon " + spawnBeaconId);
|
||||
} else {
|
||||
logger.at(Level.INFO).log("Spawned SpawnBeacon '" + spawnBeaconId + "' at position: " + position);
|
||||
transactionRecords[i] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), spawnBeaconUuidComponent.getUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,13 @@ import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<KillSpawnMarkerObjectiveTask> CODEC = BuilderCodec.builder(
|
||||
KillSpawnMarkerObjectiveTask.class, KillSpawnMarkerObjectiveTask::new, KillObjectiveTask.CODEC
|
||||
)
|
||||
.build();
|
||||
private static final ComponentType<EntityStore, SpawnMarkerEntity> SPAWN_MARKER_COMPONENT_TYPE = SpawnMarkerEntity.getComponentType();
|
||||
@Nonnull
|
||||
private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
|
||||
|
||||
public KillSpawnMarkerObjectiveTask(@Nonnull KillSpawnMarkerObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) {
|
||||
@@ -55,21 +57,17 @@ public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask {
|
||||
String[] spawnMarkerIds = asset.getSpawnMarkerIds();
|
||||
HytaleLogger logger = ObjectivePlugin.get().getLogger();
|
||||
|
||||
for (Ref<EntityStore> entityReference : results) {
|
||||
SpawnMarkerEntity entitySpawnMarkerComponent = store.getComponent(entityReference, SPAWN_MARKER_COMPONENT_TYPE);
|
||||
|
||||
assert entitySpawnMarkerComponent != null;
|
||||
|
||||
String spawnMarkerId = entitySpawnMarkerComponent.getSpawnMarkerId();
|
||||
if (ArrayUtil.contains(spawnMarkerIds, spawnMarkerId)) {
|
||||
world.execute(() -> entitySpawnMarkerComponent.trigger(entityReference, store));
|
||||
logger.at(Level.INFO)
|
||||
.log(
|
||||
"Triggered SpawnMarker '"
|
||||
+ spawnMarkerId
|
||||
+ "' at position: "
|
||||
+ store.getComponent(entityReference, TRANSFORM_COMPONENT_TYPE).getPosition()
|
||||
);
|
||||
for (Ref<EntityStore> ref : results) {
|
||||
SpawnMarkerEntity entitySpawnMarkerComponent = store.getComponent(ref, SPAWN_MARKER_COMPONENT_TYPE);
|
||||
if (entitySpawnMarkerComponent != null) {
|
||||
String spawnMarkerId = entitySpawnMarkerComponent.getSpawnMarkerId();
|
||||
if (ArrayUtil.contains(spawnMarkerIds, spawnMarkerId)) {
|
||||
world.execute(() -> entitySpawnMarkerComponent.trigger(ref, store));
|
||||
TransformComponent transformComponent = store.getComponent(ref, TRANSFORM_COMPONENT_TYPE);
|
||||
if (transformComponent != null) {
|
||||
logger.at(Level.INFO).log("Triggered SpawnMarker '" + spawnMarkerId + "' at position: " + transformComponent.getPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@ import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.hypixel.hytale.server.npc.entities.NPCEntity;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface KillTask {
|
||||
void checkKilledEntity(Store<EntityStore> var1, Ref<EntityStore> var2, Objective var3, NPCEntity var4, Damage var5);
|
||||
void checkKilledEntity(
|
||||
@Nonnull Store<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull Objective var3, @Nonnull NPCEntity var4, @Nonnull Damage var5
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ import java.util.Map.Entry;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class NPCReputationHolderSystem extends HolderSystem<EntityStore> {
|
||||
@Nonnull
|
||||
private final ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType;
|
||||
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, ComponentType<EntityStore, NPCEntity> npcEntityComponentType
|
||||
) {
|
||||
this.reputationGroupComponentType = reputationGroupComponentType;
|
||||
this.npcEntityComponentType = npcEntityComponentType;
|
||||
@@ -38,8 +39,11 @@ public class NPCReputationHolderSystem extends HolderSystem<EntityStore> {
|
||||
|
||||
@Override
|
||||
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
|
||||
NPCEntity npcEntity = holder.getComponent(this.npcEntityComponentType);
|
||||
int npcTypeIndex = npcEntity.getNPCTypeIndex();
|
||||
NPCEntity npcComponent = holder.getComponent(this.npcEntityComponentType);
|
||||
|
||||
assert npcComponent != null;
|
||||
|
||||
int npcTypeIndex = npcComponent.getNPCTypeIndex();
|
||||
|
||||
for (Entry<String, ReputationGroup> reputationEntry : ReputationGroup.getAssetMap().getAssetMap().entrySet()) {
|
||||
for (String npcGroup : reputationEntry.getValue().getNpcGroups()) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
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.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.entities.NPCEntity;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -13,7 +15,8 @@ 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();
|
||||
entityStoreRegistry.registerSystem(new ReputationAttitudeSystem());
|
||||
entityStoreRegistry.registerSystem(new NPCReputationHolderSystem(ReputationGroupComponent.getComponentType(), NPCEntity.getComponentType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,14 @@ import com.hypixel.hytale.server.npc.blackboard.view.attitude.AttitudeView;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReputationAttitudeSystem extends StoreSystem<EntityStore> {
|
||||
@Nonnull
|
||||
private final ResourceType<EntityStore, Blackboard> resourceType = Blackboard.getResourceType();
|
||||
|
||||
@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) -> {
|
||||
Blackboard blackboardResource = store.getResource(this.resourceType);
|
||||
AttitudeView attitudeView = blackboardResource.getView(AttitudeView.class, 0L);
|
||||
attitudeView.registerProvider(100, (ref, role, targetRef, accessor) -> {
|
||||
Player playerComponent = store.getComponent(targetRef, Player.getComponentType());
|
||||
return playerComponent == null ? null : ReputationPlugin.get().getAttitude(store, targetRef, ref);
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ActionOpenBarterShop extends ActionBase {
|
||||
@Nonnull
|
||||
protected final String shopId;
|
||||
|
||||
public ActionOpenBarterShop(@Nonnull BuilderActionOpenBarterShop builder, @Nonnull BuilderSupport support) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ActionOpenShop extends ActionBase {
|
||||
@Nonnull
|
||||
protected final String shopId;
|
||||
|
||||
public ActionOpenShop(@Nonnull BuilderActionOpenShop builder, @Nonnull BuilderSupport support) {
|
||||
@@ -34,15 +35,17 @@ public class ActionOpenShop extends ActionBase {
|
||||
return false;
|
||||
} else {
|
||||
PlayerRef playerRefComponent = store.getComponent(playerReference, PlayerRef.getComponentType());
|
||||
|
||||
assert playerRefComponent != null;
|
||||
|
||||
Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
|
||||
|
||||
assert playerComponent != null;
|
||||
|
||||
playerComponent.getPageManager().openCustomPage(ref, store, new ShopPage(playerRefComponent, this.shopId));
|
||||
return true;
|
||||
if (playerRefComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
|
||||
if (playerComponent == null) {
|
||||
return false;
|
||||
} else {
|
||||
playerComponent.getPageManager().openCustomPage(ref, store, new ShopPage(playerRefComponent, this.shopId));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BarterShopExistsValidator extends AssetValidator {
|
||||
@Nonnull
|
||||
private static final BarterShopExistsValidator DEFAULT_INSTANCE = new BarterShopExistsValidator();
|
||||
|
||||
private BarterShopExistsValidator() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ShopExistsValidator extends AssetValidator {
|
||||
@Nonnull
|
||||
private static final ShopExistsValidator DEFAULT_INSTANCE = new ShopExistsValidator();
|
||||
|
||||
private ShopExistsValidator() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionOpenBarterShop extends BuilderActionBase {
|
||||
@Nonnull
|
||||
protected final AssetHolder shopId = new AssetHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.EnumSet;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuilderActionOpenShop extends BuilderActionBase {
|
||||
@Nonnull
|
||||
protected final AssetHolder shopId = new AssetHolder();
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -28,8 +28,9 @@ public class ReputationCompletion extends ObjectiveCompletion {
|
||||
Player playerComponent = componentAccessor.getComponent(participantReference, Player.getComponentType());
|
||||
if (playerComponent != null) {
|
||||
UUIDComponent uuidComponent = componentAccessor.getComponent(participantReference, UUIDComponent.getComponentType());
|
||||
|
||||
assert uuidComponent != null;
|
||||
if (uuidComponent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String reputationGroupId = asset.getReputationGroupId();
|
||||
int amount = asset.getAmount();
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReputationCompletionAsset extends ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ReputationCompletionAsset> CODEC = BuilderCodec.builder(
|
||||
ReputationCompletionAsset.class, ReputationCompletionAsset::new, ObjectiveCompletionAsset.BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class ReputationObjectiveRewardHistoryData extends ObjectiveRewardHistoryData {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ReputationObjectiveRewardHistoryData> CODEC = BuilderCodec.builder(
|
||||
ReputationObjectiveRewardHistoryData.class, ReputationObjectiveRewardHistoryData::new, ObjectiveRewardHistoryData.BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DialogPage extends InteractiveCustomUIPage<DialogPage.DialogPageEventData> {
|
||||
@Nonnull
|
||||
public static final String LAYOUT = "Pages/DialogPage.ui";
|
||||
private final UseEntityObjectiveTaskAsset.DialogOptions dialogOptions;
|
||||
|
||||
@@ -37,10 +38,13 @@ public class DialogPage extends InteractiveCustomUIPage<DialogPage.DialogPageEve
|
||||
|
||||
public void handleDataEvent(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull DialogPage.DialogPageEventData data) {
|
||||
Player playerComponent = store.getComponent(ref, Player.getComponentType());
|
||||
playerComponent.getPageManager().setPage(ref, store, Page.None);
|
||||
if (playerComponent != null) {
|
||||
playerComponent.getPageManager().setPage(ref, store, Page.None);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DialogPageEventData {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<DialogPage.DialogPageEventData> CODEC = BuilderCodec.builder(
|
||||
DialogPage.DialogPageEventData.class, DialogPage.DialogPageEventData::new
|
||||
)
|
||||
|
||||
@@ -43,6 +43,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class Objective implements NetworkSerializable<com.hypixel.hytale.protocol.Objective> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<Objective> CODEC = BuilderCodec.builder(Objective.class, Objective::new)
|
||||
.append(new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY), (objective, uuid) -> objective.objectiveUUID = uuid, objective -> objective.objectiveUUID)
|
||||
.add()
|
||||
@@ -225,39 +226,47 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
}
|
||||
|
||||
public boolean setupCurrentTasks(@Nonnull Store<EntityStore> store) {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
TransactionRecord[] taskTransactions = task.setup(this, store);
|
||||
if (taskTransactions != null && TransactionUtil.anyFailed(taskTransactions)) {
|
||||
ObjectivePlugin.get()
|
||||
.getLogger()
|
||||
.at(Level.WARNING)
|
||||
.log("Failed to setup objective tasks, transaction records:%s", Arrays.toString((Object[])taskTransactions));
|
||||
if (this.currentTasks == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
TransactionRecord[] taskTransactions = task.setup(this, store);
|
||||
if (taskTransactions != null && TransactionUtil.anyFailed(taskTransactions)) {
|
||||
ObjectivePlugin.get()
|
||||
.getLogger()
|
||||
.at(Level.WARNING)
|
||||
.log("Failed to setup objective tasks, transaction records:%s", Arrays.toString((Object[])taskTransactions));
|
||||
|
||||
for (ObjectiveTask taskSetup : this.currentTasks) {
|
||||
taskSetup.revertTransactionRecords();
|
||||
if (taskSetup == task) {
|
||||
break;
|
||||
for (ObjectiveTask taskSetup : this.currentTasks) {
|
||||
taskSetup.revertTransactionRecords();
|
||||
if (taskSetup == task) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkTaskSetCompletion(@Nonnull Store<EntityStore> store) {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
return false;
|
||||
if (this.currentTasks == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
if (!task.isComplete()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.taskSetComplete(store);
|
||||
return true;
|
||||
this.taskSetComplete(store);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void taskSetComplete(@Nonnull Store<EntityStore> store) {
|
||||
@@ -269,13 +278,12 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
this.taskSetComplete(store);
|
||||
} else {
|
||||
TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(this.toPacket());
|
||||
this.forEachParticipant((participantReference, message, trackOrUpdateObjective) -> {
|
||||
this.forEachParticipant((participantReference, trackOrUpdateObjective) -> {
|
||||
PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
|
||||
if (playerRefComponent != null) {
|
||||
playerRefComponent.sendMessage(message);
|
||||
playerRefComponent.getPacketHandler().writeNoCache(trackOrUpdateObjective);
|
||||
}
|
||||
}, this.getTaskInfoMessage(), trackObjectivePacket);
|
||||
}, trackObjectivePacket);
|
||||
this.checkTaskSetCompletion(store);
|
||||
}
|
||||
} else {
|
||||
@@ -304,28 +312,21 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.revertTransactionRecords();
|
||||
if (this.currentTasks != null) {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.revertTransactionRecords();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.unloadTransactionRecords();
|
||||
if (this.currentTasks != null) {
|
||||
for (ObjectiveTask currentTask : this.currentTasks) {
|
||||
currentTask.unloadTransactionRecords();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Message getTaskInfoMessage() {
|
||||
Message info = Message.translation(this.getCurrentDescription());
|
||||
|
||||
for (ObjectiveTask task : this.currentTasks) {
|
||||
info.insert("\n").insert(task.getInfoMessage(this));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public void reloadObjectiveAsset(@Nonnull Map<String, ObjectiveAsset> reloadedAssets) {
|
||||
ObjectiveTaskAsset[] taskAssets = this.checkPossibleAssetReload(reloadedAssets);
|
||||
if (taskAssets != null) {
|
||||
@@ -404,13 +405,17 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
|
||||
@Nullable
|
||||
private ObjectiveTask findMatchingObjectiveTask(@Nonnull ObjectiveTaskAsset taskAsset) {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
if (objectiveTask.getAsset().matchesAsset(taskAsset)) {
|
||||
return objectiveTask;
|
||||
if (this.currentTasks == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
if (objectiveTask.getAsset().matchesAsset(taskAsset)) {
|
||||
return objectiveTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelReload(@Nonnull ObjectiveTask[] newTasks) {
|
||||
@@ -425,18 +430,20 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
}
|
||||
|
||||
private void revertRemovedTasks(@Nonnull ObjectiveTask[] newTasks) {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
boolean foundMatchingTask = false;
|
||||
if (this.currentTasks != null) {
|
||||
for (ObjectiveTask objectiveTask : this.currentTasks) {
|
||||
boolean foundMatchingTask = false;
|
||||
|
||||
for (ObjectiveTask newTask : newTasks) {
|
||||
if (newTask.equals(objectiveTask)) {
|
||||
foundMatchingTask = true;
|
||||
break;
|
||||
for (ObjectiveTask newTask : newTasks) {
|
||||
if (newTask.equals(objectiveTask)) {
|
||||
foundMatchingTask = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatchingTask) {
|
||||
objectiveTask.revertTransactionRecords();
|
||||
if (!foundMatchingTask) {
|
||||
objectiveTask.revertTransactionRecords();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,7 +470,10 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
for (UUID playerUUID : this.playerUUIDs) {
|
||||
PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
|
||||
if (playerRef != null) {
|
||||
consumer.accept(playerRef.getReference(), t, u);
|
||||
Ref<EntityStore> ref = playerRef.getReference();
|
||||
if (ref != null && ref.isValid()) {
|
||||
consumer.accept(playerRef.getReference(), t, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,8 +524,8 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
|
||||
ObjectiveAsset objectiveAsset = Objects.requireNonNull(this.getObjectiveAsset());
|
||||
com.hypixel.hytale.protocol.Objective packet = new com.hypixel.hytale.protocol.Objective();
|
||||
packet.objectiveUuid = this.objectiveUUID;
|
||||
packet.objectiveTitleKey = objectiveAsset.getTitleKey();
|
||||
packet.objectiveDescriptionKey = this.getCurrentDescription();
|
||||
packet.objectiveTitleKey = Message.translation(objectiveAsset.getTitleKey()).getFormattedMessage();
|
||||
packet.objectiveDescriptionKey = Message.translation(this.getCurrentDescription()).getFormattedMessage();
|
||||
if (this.objectiveLineHistoryData != null) {
|
||||
packet.objectiveLineId = this.objectiveLineHistoryData.getId();
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ObjectiveDataStore {
|
||||
@Nonnull
|
||||
private final Map<UUID, Objective> objectives = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final Map<UUID, Map<String, Set<UUID>>> entityObjectiveUUIDsPerPlayer = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final DataStore<Objective> dataStore;
|
||||
@Nonnull
|
||||
private final Map<Class<? extends ObjectiveTask>, Set<ObjectiveTaskRef<? extends ObjectiveTask>>> taskRefByType = new ConcurrentHashMap<>();
|
||||
@Nonnull
|
||||
private final HytaleLogger logger;
|
||||
|
||||
@@ -110,10 +110,14 @@ 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;
|
||||
@@ -391,7 +395,6 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -605,8 +608,8 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
ObjectiveTask[] currentTasks = objective.getCurrentTasks();
|
||||
|
||||
for (ObjectiveTask task : currentTasks) {
|
||||
if (task instanceof UseEntityObjectiveTask) {
|
||||
this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, ((UseEntityObjectiveTask)task).getAsset().getTaskId(), playerUUID);
|
||||
if (task instanceof UseEntityObjectiveTask useEntityObjectiveTask) {
|
||||
this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, useEntityObjectiveTask.getAsset().getTaskId(), playerUUID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,7 +863,7 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private void onWorldAdded(AddWorldEvent event) {
|
||||
private void onWorldAdded(@Nonnull AddWorldEvent event) {
|
||||
event.getWorld().getWorldMapManager().addMarkerProvider("objectives", ObjectiveMarkerProvider.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -887,6 +890,7 @@ public class ObjectivePlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
public static class ObjectivePluginConfig {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectivePlugin.ObjectivePluginConfig> CODEC = BuilderCodec.builder(
|
||||
ObjectivePlugin.ObjectivePluginConfig.class, ObjectivePlugin.ObjectivePluginConfig::new
|
||||
)
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.UUID;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TreasureChestState extends ItemContainerState implements BreakValidatedBlockState {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<TreasureChestState> CODEC = BuilderCodec.builder(TreasureChestState.class, TreasureChestState::new, BlockState.BASE_CODEC)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY),
|
||||
|
||||
@@ -53,38 +53,36 @@ public class ObjectiveLocationMarkerCommand extends AbstractCommandCollection {
|
||||
protected void execute(
|
||||
@Nonnull CommandContext context, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull World world
|
||||
) {
|
||||
Ref<EntityStore> playerReference = playerRef.getReference();
|
||||
TransformComponent playerTransformComponent = store.getComponent(playerReference, TransformComponent.getComponentType());
|
||||
|
||||
assert playerTransformComponent != null;
|
||||
|
||||
String objectiveLocationMarkerId = this.locationMarkerArg.get(context);
|
||||
if (ObjectiveLocationMarkerAsset.getAssetMap().getAsset(objectiveLocationMarkerId) == null) {
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.notFound").param("id", objectiveLocationMarkerId));
|
||||
context.sendMessage(
|
||||
Message.translation("server.general.failed.didYouMean")
|
||||
.param(
|
||||
"choices",
|
||||
StringUtil.sortByFuzzyDistance(
|
||||
objectiveLocationMarkerId, ObjectiveLocationMarkerAsset.getAssetMap().getAssetMap().keySet(), CommandUtil.RECOMMEND_COUNT
|
||||
)
|
||||
.toString()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
|
||||
holder.addComponent(ObjectiveLocationMarker.getComponentType(), new ObjectiveLocationMarker(objectiveLocationMarkerId));
|
||||
Model model = ObjectivePlugin.get().getObjectiveLocationMarkerModel();
|
||||
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
|
||||
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
|
||||
holder.addComponent(Nameplate.getComponentType(), new Nameplate(objectiveLocationMarkerId));
|
||||
TransformComponent transform = new TransformComponent(playerTransformComponent.getPosition(), playerTransformComponent.getRotation());
|
||||
holder.addComponent(TransformComponent.getComponentType(), transform);
|
||||
holder.ensureComponent(UUIDComponent.getComponentType());
|
||||
holder.ensureComponent(Intangible.getComponentType());
|
||||
holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType());
|
||||
store.addEntity(holder, AddReason.SPAWN);
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.added").param("id", objectiveLocationMarkerId));
|
||||
TransformComponent playerTransformComponent = store.getComponent(ref, TransformComponent.getComponentType());
|
||||
if (playerTransformComponent != null) {
|
||||
String objectiveLocationMarkerId = this.locationMarkerArg.get(context);
|
||||
if (ObjectiveLocationMarkerAsset.getAssetMap().getAsset(objectiveLocationMarkerId) == null) {
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.notFound").param("id", objectiveLocationMarkerId));
|
||||
context.sendMessage(
|
||||
Message.translation("server.general.failed.didYouMean")
|
||||
.param(
|
||||
"choices",
|
||||
StringUtil.sortByFuzzyDistance(
|
||||
objectiveLocationMarkerId, ObjectiveLocationMarkerAsset.getAssetMap().getAssetMap().keySet(), CommandUtil.RECOMMEND_COUNT
|
||||
)
|
||||
.toString()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
|
||||
holder.addComponent(ObjectiveLocationMarker.getComponentType(), new ObjectiveLocationMarker(objectiveLocationMarkerId));
|
||||
Model model = ObjectivePlugin.get().getObjectiveLocationMarkerModel();
|
||||
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
|
||||
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
|
||||
holder.addComponent(Nameplate.getComponentType(), new Nameplate(objectiveLocationMarkerId));
|
||||
TransformComponent transform = new TransformComponent(playerTransformComponent.getPosition(), playerTransformComponent.getRotation());
|
||||
holder.addComponent(TransformComponent.getComponentType(), transform);
|
||||
holder.ensureComponent(UUIDComponent.getComponentType());
|
||||
holder.ensureComponent(Intangible.getComponentType());
|
||||
holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType());
|
||||
store.addEntity(holder, AddReason.SPAWN);
|
||||
context.sendMessage(Message.translation("server.commands.objective.locationMarker.added").param("id", objectiveLocationMarkerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveHistoryComponent implements Component<EntityStore> {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveHistoryComponent> CODEC = BuilderCodec.builder(ObjectiveHistoryComponent.class, ObjectiveHistoryComponent::new)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveHistory", new MapCodec<>(ObjectiveHistoryData.CODEC, Object2ObjectOpenHashMap::new, false)),
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveAsset>> {
|
||||
@Nonnull
|
||||
public static final AssetBuilderCodec<String, ObjectiveAsset> CODEC = AssetBuilderCodec.builder(
|
||||
ObjectiveAsset.class,
|
||||
ObjectiveAsset::new,
|
||||
@@ -87,6 +88,7 @@ public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveAsset::getAssetStore));
|
||||
private static AssetStore<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> ASSET_STORE;
|
||||
protected AssetExtraInfo.Data extraData;
|
||||
|
||||
@@ -79,6 +79,7 @@ public class ObjectiveLineAsset implements JsonAssetWithMap<String, DefaultAsset
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLineAsset::getAssetStore));
|
||||
private static AssetStore<String, ObjectiveLineAsset, DefaultAssetMap<String, ObjectiveLineAsset>> ASSET_STORE;
|
||||
protected AssetExtraInfo.Data extraData;
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> {
|
||||
@Nonnull
|
||||
public static final AssetBuilderCodec<String, ObjectiveLocationMarkerAsset> CODEC = AssetBuilderCodec.builder(
|
||||
ObjectiveLocationMarkerAsset.class,
|
||||
ObjectiveLocationMarkerAsset::new,
|
||||
@@ -74,6 +75,7 @@ public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, De
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLocationMarkerAsset::getAssetStore));
|
||||
private static AssetStore<String, ObjectiveLocationMarkerAsset, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> ASSET_STORE;
|
||||
protected AssetExtraInfo.Data data;
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ClearObjectiveItemsCompletionAsset extends ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ClearObjectiveItemsCompletionAsset> CODEC = BuilderCodec.builder(
|
||||
ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset::new, BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GiveItemsCompletionAsset extends ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<GiveItemsCompletionAsset> CODEC = BuilderCodec.builder(
|
||||
GiveItemsCompletionAsset.class, GiveItemsCompletionAsset::new, BASE_CODEC
|
||||
)
|
||||
|
||||
@@ -5,7 +5,9 @@ import com.hypixel.hytale.codec.lookup.CodecMapCodec;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class ObjectiveCompletionAsset {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<ObjectiveCompletionAsset> CODEC = new CodecMapCodec<>("Type");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveCompletionAsset> BASE_CODEC = BuilderCodec.abstractBuilder(ObjectiveCompletionAsset.class).build();
|
||||
|
||||
protected ObjectiveCompletionAsset() {
|
||||
|
||||
@@ -12,7 +12,9 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ObjectiveGameplayConfig {
|
||||
@Nonnull
|
||||
public static final String ID = "Objective";
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveGameplayConfig> CODEC = BuilderCodec.builder(ObjectiveGameplayConfig.class, ObjectiveGameplayConfig::new)
|
||||
.appendInherited(
|
||||
new KeyedCodec<>("StarterObjectiveLinePerWorld", new MapCodec<>(Codec.STRING, Object2ObjectOpenHashMap::new, true)),
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveLocationAreaBox> CODEC = BuilderCodec.builder(ObjectiveLocationAreaBox.class, ObjectiveLocationAreaBox::new)
|
||||
.append(
|
||||
new KeyedCodec<>("EntryBox", Box.CODEC),
|
||||
@@ -33,7 +34,9 @@ public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
|
||||
.add()
|
||||
.afterDecode(ObjectiveLocationAreaBox::computeAreaBoxes)
|
||||
.build();
|
||||
@Nonnull
|
||||
private static final Box DEFAULT_ENTRY_BOX = new Box(-5.0, -5.0, -5.0, 5.0, 5.0, 5.0);
|
||||
@Nonnull
|
||||
private static final Box DEFAULT_EXIT_BOX = new Box(-10.0, -10.0, -10.0, 10.0, 10.0, 10.0);
|
||||
private Box entryArea;
|
||||
private Box exitArea;
|
||||
@@ -115,7 +118,7 @@ public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
|
||||
|
||||
private static void getPlayersInArea(
|
||||
@Nonnull SpatialResource<Ref<EntityStore>, EntityStore> spatialComponent,
|
||||
List<Ref<EntityStore>> results,
|
||||
@Nonnull List<Ref<EntityStore>> results,
|
||||
@Nonnull Vector3d markerPosition,
|
||||
@Nonnull Box box
|
||||
) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ObjectiveLocationAreaRadius extends ObjectiveLocationMarkerArea {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveLocationAreaRadius> CODEC = BuilderCodec.builder(
|
||||
ObjectiveLocationAreaRadius.class, ObjectiveLocationAreaRadius::new
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SetupObjective extends ObjectiveTypeSetup {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SetupObjective> CODEC = BuilderCodec.builder(SetupObjective.class, SetupObjective::new)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveId", Codec.STRING), (setupObjective, s) -> setupObjective.objectiveId = s, setupObjective -> setupObjective.objectiveId
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SetupObjectiveLine extends ObjectiveTypeSetup {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<SetupObjectiveLine> CODEC = BuilderCodec.builder(SetupObjectiveLine.class, SetupObjectiveLine::new)
|
||||
.append(
|
||||
new KeyedCodec<>("ObjectiveLineId", Codec.STRING),
|
||||
|
||||
@@ -11,6 +11,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockTagOrItemIdField {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<BlockTagOrItemIdField> CODEC = BuilderCodec.builder(BlockTagOrItemIdField.class, BlockTagOrItemIdField::new)
|
||||
.append(
|
||||
new KeyedCodec<>("BlockTag", Codec.STRING),
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.hypixel.hytale.server.core.asset.type.item.config.Item;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CraftObjectiveTaskAsset extends CountObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<CraftObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
CraftObjectiveTaskAsset.class, CraftObjectiveTaskAsset::new, CountObjectiveTaskAsset.CODEC
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GatherObjectiveTaskAsset extends CountObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<GatherObjectiveTaskAsset> CODEC = BuilderCodec.builder(
|
||||
GatherObjectiveTaskAsset.class, GatherObjectiveTaskAsset::new, CountObjectiveTaskAsset.CODEC
|
||||
)
|
||||
|
||||
@@ -10,9 +10,12 @@ import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class ObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final CodecMapCodec<ObjectiveTaskAsset> CODEC = new CodecMapCodec<>("Type");
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ObjectiveTaskAsset> BASE_CODEC = BuilderCodec.abstractBuilder(ObjectiveTaskAsset.class)
|
||||
.append(
|
||||
new KeyedCodec<>("DescriptionId", Codec.STRING),
|
||||
@@ -27,12 +30,13 @@ public abstract class ObjectiveTaskAsset {
|
||||
)
|
||||
.add()
|
||||
.append(
|
||||
new KeyedCodec<>("MapMarkers", new ArrayCodec<>(Vector3i.CODEC, Vector3i[]::new)),
|
||||
(taskAsset, vector3is) -> taskAsset.mapMarkers = vector3is,
|
||||
new KeyedCodec<>("MapMarkerPositions", new ArrayCodec<>(Vector3i.CODEC, Vector3i[]::new)),
|
||||
(taskAsset, positions) -> taskAsset.mapMarkers = positions,
|
||||
taskAsset -> taskAsset.mapMarkers
|
||||
)
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final String TASK_DESCRIPTION_KEY = "server.objectives.{0}.taskSet.{1}.task.{2}";
|
||||
protected String descriptionId;
|
||||
protected TaskConditionAsset[] taskConditions;
|
||||
@@ -42,7 +46,6 @@ public abstract class ObjectiveTaskAsset {
|
||||
public ObjectiveTaskAsset(String descriptionId, TaskConditionAsset[] taskConditions, Vector3i[] mapMarkers) {
|
||||
this.descriptionId = descriptionId;
|
||||
this.taskConditions = taskConditions;
|
||||
this.mapMarkers = mapMarkers;
|
||||
}
|
||||
|
||||
protected ObjectiveTaskAsset() {
|
||||
@@ -69,6 +72,7 @@ public abstract class ObjectiveTaskAsset {
|
||||
return this.taskConditions;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Vector3i[] getMapMarkers() {
|
||||
return this.mapMarkers;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReachLocationTaskAsset extends ObjectiveTaskAsset {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<ReachLocationTaskAsset> CODEC = BuilderCodec.builder(ReachLocationTaskAsset.class, ReachLocationTaskAsset::new, BASE_CODEC)
|
||||
.append(
|
||||
new KeyedCodec<>("TargetLocation", Codec.STRING),
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TaskSet {
|
||||
@Nonnull
|
||||
public static final BuilderCodec<TaskSet> CODEC = BuilderCodec.builder(TaskSet.class, TaskSet::new)
|
||||
.append(new KeyedCodec<>("DescriptionId", Codec.STRING), (taskSet, s) -> taskSet.descriptionId = s, taskSet -> taskSet.descriptionId)
|
||||
.add()
|
||||
@@ -21,6 +22,7 @@ public class TaskSet {
|
||||
.addValidator(Validators.nonEmptyArray())
|
||||
.add()
|
||||
.build();
|
||||
@Nonnull
|
||||
public static final String TASKSET_DESCRIPTION_KEY = "server.objectives.{0}.taskSet.{1}";
|
||||
protected String descriptionId;
|
||||
protected ObjectiveTaskAsset[] tasks;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user