Compare commits

..

6 Commits

Author SHA1 Message Date
Intege-rs
4dcc723c9c 2026.02.11-255364b8e 2026-02-11 18:06:52 -05:00
Intege-rs
8988b1dc65 2026.02.06-0baf7c5aa 2026-02-06 23:08:15 -05:00
Intege-rs
72c1df79ca 2026.01.29-301e13929 2026-01-29 19:59:39 -05:00
Intege-rs
480cf742c8 2026.01.28-87d03be09 2026-01-28 08:30:21 -05:00
Intege-rs
66b236b50e 2026.01.27-734d39026 2026-01-27 21:50:02 -05:00
Intege-rs
3fbbfeb54b 2026.01.24-6e2d4fc36 2026-01-27 21:48:16 -05:00
1485 changed files with 32716 additions and 14589 deletions

7
.gitignore vendored
View File

@@ -1,5 +1,4 @@
build/ build/
bin/
.kotlin .kotlin
.idea .idea
@@ -15,6 +14,12 @@ out/
!**/src/main/**/out/ !**/src/main/**/out/
!**/src/test/**/out/ !**/src/test/**/out/
### MCP adds eclipser
bin/
.classpath
.project
.eclipse
# Gradle Wrapper # Gradle Wrapper
gradlew gradlew
gradlew.bat gradlew.bat

View File

@@ -1,10 +1,12 @@
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$branch = git rev-parse --abbrev-ref HEAD
# Move to the git root if we arn't already there # Move to the git root if we arn't already there
git rev-parse --show-toplevel | Set-Location git rev-parse --show-toplevel | Set-Location
# get the server jar from the install directory ( in future support pre-release ) # get the server jar from the install directory ( in future support pre-release )
$server_jar = resolve-path "$env:APPDATA/Hytale/install/release/package/game/latest/Server/HytaleServer.jar" $server_jar = resolve-path "$env:APPDATA/Hytale/install/$branch/package/game/latest/Server/HytaleServer.jar"
# clear the source directory # clear the source directory
Get-ChildItem -Path "src" | Remove-Item -Recurse -Force -Confirm:$false Get-ChildItem -Path "src" | Remove-Item -Recurse -Force -Confirm:$false

View File

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

View File

@@ -10,16 +10,21 @@ import com.hypixel.hytale.builtin.adventure.camera.asset.viewbobbing.ViewBobbing
import com.hypixel.hytale.builtin.adventure.camera.command.CameraEffectCommand; import com.hypixel.hytale.builtin.adventure.camera.command.CameraEffectCommand;
import com.hypixel.hytale.builtin.adventure.camera.interaction.CameraShakeInteraction; import com.hypixel.hytale.builtin.adventure.camera.interaction.CameraShakeInteraction;
import com.hypixel.hytale.builtin.adventure.camera.system.CameraEffectSystem; import com.hypixel.hytale.builtin.adventure.camera.system.CameraEffectSystem;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.protocol.MovementType; import com.hypixel.hytale.protocol.MovementType;
import com.hypixel.hytale.server.core.asset.HytaleAssetStore; import com.hypixel.hytale.server.core.asset.HytaleAssetStore;
import com.hypixel.hytale.server.core.asset.type.camera.CameraEffect; import com.hypixel.hytale.server.core.asset.type.camera.CameraEffect;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry; import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class CameraPlugin extends JavaPlugin { public class CameraPlugin extends JavaPlugin {
@Nonnull
private static final String CODEC_CAMERA_SHAKE = "CameraShake"; private static final String CODEC_CAMERA_SHAKE = "CameraShake";
public CameraPlugin(@Nonnull JavaPluginInit init) { public CameraPlugin(@Nonnull JavaPluginInit init) {
@@ -54,6 +59,8 @@ public class CameraPlugin extends JavaPlugin {
.build() .build()
); );
this.getCommandRegistry().registerCommand(new CameraEffectCommand()); this.getCommandRegistry().registerCommand(new CameraEffectCommand());
this.getEntityStoreRegistry().registerSystem(new CameraEffectSystem()); ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ComponentType<EntityStore, EntityStatMap> entityStatMapComponentType = EntityStatMap.getComponentType();
this.getEntityStoreRegistry().registerSystem(new CameraEffectSystem(playerRefComponentType, entityStatMapComponentType));
} }
} }

View File

@@ -9,6 +9,7 @@ import java.util.Arrays;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale.protocol.CameraShakeConfig> { public class CameraShakeConfig implements NetworkSerializable<com.hypixel.hytale.protocol.CameraShakeConfig> {
@Nonnull
public static final BuilderCodec<CameraShakeConfig> CODEC = BuilderCodec.builder(CameraShakeConfig.class, CameraShakeConfig::new) 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) .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") .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> { public static class OffsetNoise implements NetworkSerializable<com.hypixel.hytale.protocol.OffsetNoise> {
@Nonnull
public static final BuilderCodec<CameraShakeConfig.OffsetNoise> CODEC = BuilderCodec.builder( public static final BuilderCodec<CameraShakeConfig.OffsetNoise> CODEC = BuilderCodec.builder(
CameraShakeConfig.OffsetNoise.class, CameraShakeConfig.OffsetNoise::new 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") .documentation("The noise used to vary the camera z-offset")
.add() .add()
.build(); .build();
@Nonnull
public static final CameraShakeConfig.OffsetNoise NONE = new CameraShakeConfig.OffsetNoise(); public static final CameraShakeConfig.OffsetNoise NONE = new CameraShakeConfig.OffsetNoise();
protected NoiseConfig[] x; protected NoiseConfig[] x;
protected NoiseConfig[] y; 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> { public static class RotationNoise implements NetworkSerializable<com.hypixel.hytale.protocol.RotationNoise> {
@Nonnull
public static final BuilderCodec<CameraShakeConfig.RotationNoise> CODEC = BuilderCodec.builder( public static final BuilderCodec<CameraShakeConfig.RotationNoise> CODEC = BuilderCodec.builder(
CameraShakeConfig.RotationNoise.class, CameraShakeConfig.RotationNoise::new 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") .documentation("The noise used to vary the camera roll")
.add() .add()
.build(); .build();
@Nonnull
public static final CameraShakeConfig.RotationNoise NONE = new CameraShakeConfig.RotationNoise(); public static final CameraShakeConfig.RotationNoise NONE = new CameraShakeConfig.RotationNoise();
protected NoiseConfig[] pitch; protected NoiseConfig[] pitch;
protected NoiseConfig[] yaw; protected NoiseConfig[] yaw;

View File

@@ -2,7 +2,7 @@ package com.hypixel.hytale.builtin.adventure.camera.asset.camerashake;
import com.hypixel.hytale.assetstore.map.IndexedAssetMap; import com.hypixel.hytale.assetstore.map.IndexedAssetMap;
import com.hypixel.hytale.protocol.CachedPacket; import com.hypixel.hytale.protocol.CachedPacket;
import com.hypixel.hytale.protocol.Packet; import com.hypixel.hytale.protocol.ToClientPacket;
import com.hypixel.hytale.protocol.UpdateType; import com.hypixel.hytale.protocol.UpdateType;
import com.hypixel.hytale.protocol.packets.assets.UpdateCameraShake; import com.hypixel.hytale.protocol.packets.assets.UpdateCameraShake;
import com.hypixel.hytale.server.core.asset.packet.SimpleAssetPacketGenerator; import com.hypixel.hytale.server.core.asset.packet.SimpleAssetPacketGenerator;
@@ -14,17 +14,17 @@ import javax.annotation.Nonnull;
public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<String, CameraShake, IndexedAssetMap<String, CameraShake>> { public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<String, CameraShake, IndexedAssetMap<String, CameraShake>> {
@Nonnull @Nonnull
public Packet generateInitPacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) { public ToClientPacket generateInitPacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) {
return toCachedPacket(UpdateType.Init, assetMap, assets); return toCachedPacket(UpdateType.Init, assetMap, assets);
} }
@Nonnull @Nonnull
protected Packet generateUpdatePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> loadedAssets) { protected ToClientPacket generateUpdatePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> loadedAssets) {
return toCachedPacket(UpdateType.AddOrUpdate, assetMap, loadedAssets); return toCachedPacket(UpdateType.AddOrUpdate, assetMap, loadedAssets);
} }
@Nonnull @Nonnull
protected Packet generateRemovePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Set<String> removed) { protected ToClientPacket generateRemovePacket(@Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Set<String> removed) {
Int2ObjectOpenHashMap<com.hypixel.hytale.protocol.CameraShake> profiles = new Int2ObjectOpenHashMap<>(); Int2ObjectOpenHashMap<com.hypixel.hytale.protocol.CameraShake> profiles = new Int2ObjectOpenHashMap<>();
for (String key : removed) { for (String key : removed) {
@@ -39,7 +39,9 @@ public class CameraShakePacketGenerator extends SimpleAssetPacketGenerator<Strin
} }
@Nonnull @Nonnull
protected static Packet toCachedPacket(UpdateType type, @Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets) { protected static ToClientPacket toCachedPacket(
@Nonnull UpdateType type, @Nonnull IndexedAssetMap<String, CameraShake> assetMap, @Nonnull Map<String, CameraShake> assets
) {
Int2ObjectOpenHashMap<com.hypixel.hytale.protocol.CameraShake> profiles = new Int2ObjectOpenHashMap<>(); Int2ObjectOpenHashMap<com.hypixel.hytale.protocol.CameraShake> profiles = new Int2ObjectOpenHashMap<>();
for (Entry<String, CameraShake> entry : assets.entrySet()) { for (Entry<String, CameraShake> entry : assets.entrySet()) {

View File

@@ -3,7 +3,7 @@ package com.hypixel.hytale.builtin.adventure.camera.asset.viewbobbing;
import com.hypixel.hytale.assetstore.AssetMap; import com.hypixel.hytale.assetstore.AssetMap;
import com.hypixel.hytale.protocol.CachedPacket; import com.hypixel.hytale.protocol.CachedPacket;
import com.hypixel.hytale.protocol.MovementType; import com.hypixel.hytale.protocol.MovementType;
import com.hypixel.hytale.protocol.Packet; import com.hypixel.hytale.protocol.ToClientPacket;
import com.hypixel.hytale.protocol.UpdateType; import com.hypixel.hytale.protocol.UpdateType;
import com.hypixel.hytale.protocol.packets.assets.UpdateViewBobbing; import com.hypixel.hytale.protocol.packets.assets.UpdateViewBobbing;
import com.hypixel.hytale.server.core.asset.packet.SimpleAssetPacketGenerator; import com.hypixel.hytale.server.core.asset.packet.SimpleAssetPacketGenerator;
@@ -16,19 +16,19 @@ import javax.annotation.Nonnull;
public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<MovementType, ViewBobbing, AssetMap<MovementType, ViewBobbing>> { public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<MovementType, ViewBobbing, AssetMap<MovementType, ViewBobbing>> {
@Nonnull @Nonnull
@Override @Override
public Packet generateInitPacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> assets) { public ToClientPacket generateInitPacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> assets) {
return toCachedPacket(UpdateType.Init, assets); return toCachedPacket(UpdateType.Init, assets);
} }
@Nonnull @Nonnull
@Override @Override
protected Packet generateUpdatePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> loadedAssets) { protected ToClientPacket generateUpdatePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Map<MovementType, ViewBobbing> loadedAssets) {
return toCachedPacket(UpdateType.AddOrUpdate, loadedAssets); return toCachedPacket(UpdateType.AddOrUpdate, loadedAssets);
} }
@Nonnull @Nonnull
@Override @Override
protected Packet generateRemovePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Set<MovementType> removed) { protected ToClientPacket generateRemovePacket(AssetMap<MovementType, ViewBobbing> assetMap, @Nonnull Set<MovementType> removed) {
UpdateViewBobbing packet = new UpdateViewBobbing(); UpdateViewBobbing packet = new UpdateViewBobbing();
packet.type = UpdateType.Remove; packet.type = UpdateType.Remove;
packet.profiles = new EnumMap<>(MovementType.class); packet.profiles = new EnumMap<>(MovementType.class);
@@ -41,7 +41,7 @@ public class ViewBobbingPacketGenerator extends SimpleAssetPacketGenerator<Movem
} }
@Nonnull @Nonnull
protected static Packet toCachedPacket(UpdateType type, @Nonnull Map<MovementType, ViewBobbing> assets) { protected static ToClientPacket toCachedPacket(@Nonnull UpdateType type, @Nonnull Map<MovementType, ViewBobbing> assets) {
UpdateViewBobbing packet = new UpdateViewBobbing(); UpdateViewBobbing packet = new UpdateViewBobbing();
packet.type = type; packet.type = type;
packet.profiles = new EnumMap<>(MovementType.class); packet.profiles = new EnumMap<>(MovementType.class);

View File

@@ -80,7 +80,6 @@ public class CameraEffectCommand extends AbstractCommandCollection {
} }
protected static class DebugCommand extends AbstractTargetPlayerCommand { protected static class DebugCommand extends AbstractTargetPlayerCommand {
private static final String MESSAGE_SUCCESS = "server.commands.camshake.debug.success";
@Nonnull @Nonnull
protected final RequiredArg<CameraEffect> effectArg = this.withRequiredArg( protected final RequiredArg<CameraEffect> effectArg = this.withRequiredArg(
"effect", "server.commands.camshake.effect.desc", CameraEffectCommand.CAMERA_EFFECT_ARGUMENT_TYPE "effect", "server.commands.camshake.effect.desc", CameraEffectCommand.CAMERA_EFFECT_ARGUMENT_TYPE

View File

@@ -23,10 +23,19 @@ import javax.annotation.Nullable;
public class CameraEffectSystem extends DamageEventSystem { public class CameraEffectSystem extends DamageEventSystem {
@Nonnull @Nonnull
private static final ComponentType<EntityStore, PlayerRef> PLAYER_REF_COMPONENT_TYPE = PlayerRef.getComponentType(); private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
private static final ComponentType<EntityStore, EntityStatMap> ENTITY_STAT_MAP_COMPONENT_TYPE = EntityStatMap.getComponentType();
@Nonnull @Nonnull
private static final Query<EntityStore> QUERY = Query.and(PLAYER_REF_COMPONENT_TYPE, ENTITY_STAT_MAP_COMPONENT_TYPE); private final ComponentType<EntityStore, EntityStatMap> entityStatMapComponentType;
@Nonnull
private final Query<EntityStore> query;
public CameraEffectSystem(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType, @Nonnull ComponentType<EntityStore, EntityStatMap> entityStatMapComponentType
) {
this.playerRefComponentType = playerRefComponentType;
this.entityStatMapComponentType = entityStatMapComponentType;
this.query = Query.and(playerRefComponentType, entityStatMapComponentType);
}
@Nullable @Nullable
@Override @Override
@@ -37,7 +46,7 @@ public class CameraEffectSystem extends DamageEventSystem {
@Nonnull @Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return QUERY; return this.query;
} }
public void handle( public void handle(
@@ -47,7 +56,7 @@ public class CameraEffectSystem extends DamageEventSystem {
@Nonnull CommandBuffer<EntityStore> commandBuffer, @Nonnull CommandBuffer<EntityStore> commandBuffer,
@Nonnull Damage damage @Nonnull Damage damage
) { ) {
EntityStatMap entityStatMapComponent = archetypeChunk.getComponent(index, ENTITY_STAT_MAP_COMPONENT_TYPE); EntityStatMap entityStatMapComponent = archetypeChunk.getComponent(index, this.entityStatMapComponentType);
assert entityStatMapComponent != null; assert entityStatMapComponent != null;
@@ -55,7 +64,7 @@ public class CameraEffectSystem extends DamageEventSystem {
if (healthStat != null) { if (healthStat != null) {
float health = healthStat.getMax() - healthStat.getMin(); float health = healthStat.getMax() - healthStat.getMin();
if (!(health <= 0.0F)) { if (!(health <= 0.0F)) {
PlayerRef playerRefComponent = archetypeChunk.getComponent(index, PLAYER_REF_COMPONENT_TYPE); PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType);
assert playerRefComponent != null; assert playerRefComponent != null;

View File

@@ -23,6 +23,7 @@ import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlock;
import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlockState; import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlockState;
import com.hypixel.hytale.builtin.adventure.farming.states.TilledSoilBlock; import com.hypixel.hytale.builtin.adventure.farming.states.TilledSoilBlock;
import com.hypixel.hytale.builtin.tagset.config.NPCGroup; 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.ComponentType;
import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.event.EventPriority; import com.hypixel.hytale.event.EventPriority;
@@ -31,10 +32,15 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Farmin
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset; import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList; import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
import com.hypixel.hytale.server.core.asset.type.weather.config.Weather; import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.modules.block.BlockModule;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.plugin.registry.AssetRegistry;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk; import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
import com.hypixel.hytale.server.core.universe.world.events.ChunkPreLoadProcessEvent; import com.hypixel.hytale.server.core.universe.world.events.ChunkPreLoadProcessEvent;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
@@ -60,28 +66,29 @@ public class FarmingPlugin extends JavaPlugin {
@Override @Override
protected void setup() { protected void setup() {
instance = this; instance = this;
this.getAssetRegistry() AssetRegistry assetRegistry = this.getAssetRegistry();
.register( ComponentRegistryProxy<ChunkStore> chunkStoreRegistry = this.getChunkStoreRegistry();
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder( ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
GrowthModifierAsset.class, new DefaultAssetMap() assetRegistry.register(
) ((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
.setPath("Farming/Modifiers")) GrowthModifierAsset.class, new DefaultAssetMap()
.setCodec(GrowthModifierAsset.CODEC)) )
.loadsAfter(Weather.class)) .setPath("Farming/Modifiers"))
.setKeyFunction(GrowthModifierAsset::getId)) .setCodec(GrowthModifierAsset.CODEC))
.build() .loadsAfter(Weather.class))
); .setKeyFunction(GrowthModifierAsset::getId))
this.getAssetRegistry() .build()
.register( );
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder( assetRegistry.register(
FarmingCoopAsset.class, new DefaultAssetMap() ((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
) FarmingCoopAsset.class, new DefaultAssetMap()
.setPath("Farming/Coops")) )
.setCodec(FarmingCoopAsset.CODEC)) .setPath("Farming/Coops"))
.loadsAfter(ItemDropList.class, NPCGroup.class)) .setCodec(FarmingCoopAsset.CODEC))
.setKeyFunction(FarmingCoopAsset::getId)) .loadsAfter(ItemDropList.class, NPCGroup.class))
.build() .setKeyFunction(FarmingCoopAsset::getId))
); .build()
);
this.getCodecRegistry(Interaction.CODEC) this.getCodecRegistry(Interaction.CODEC)
.register("HarvestCrop", HarvestCropInteraction.class, HarvestCropInteraction.CODEC) .register("HarvestCrop", HarvestCropInteraction.class, HarvestCropInteraction.CODEC)
.register("FertilizeSoil", FertilizeSoilInteraction.class, FertilizeSoilInteraction.CODEC) .register("FertilizeSoil", FertilizeSoilInteraction.class, FertilizeSoilInteraction.CODEC)
@@ -97,23 +104,34 @@ public class FarmingPlugin extends JavaPlugin {
this.getCodecRegistry(FarmingStageData.CODEC).register("Prefab", PrefabFarmingStageData.class, PrefabFarmingStageData.CODEC); this.getCodecRegistry(FarmingStageData.CODEC).register("Prefab", PrefabFarmingStageData.class, PrefabFarmingStageData.CODEC);
this.getCodecRegistry(FarmingStageData.CODEC).register("Spread", SpreadFarmingStageData.class, SpreadFarmingStageData.CODEC); this.getCodecRegistry(FarmingStageData.CODEC).register("Spread", SpreadFarmingStageData.class, SpreadFarmingStageData.CODEC);
this.getCodecRegistry(SpreadGrowthBehaviour.CODEC).register("Directional", DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour.CODEC); this.getCodecRegistry(SpreadGrowthBehaviour.CODEC).register("Directional", DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour.CODEC);
this.tiledSoilBlockComponentType = this.getChunkStoreRegistry().registerComponent(TilledSoilBlock.class, "TilledSoil", TilledSoilBlock.CODEC); this.tiledSoilBlockComponentType = chunkStoreRegistry.registerComponent(TilledSoilBlock.class, "TilledSoil", TilledSoilBlock.CODEC);
this.farmingBlockComponentType = this.getChunkStoreRegistry().registerComponent(FarmingBlock.class, "FarmingBlock", FarmingBlock.CODEC); this.farmingBlockComponentType = chunkStoreRegistry.registerComponent(FarmingBlock.class, "FarmingBlock", FarmingBlock.CODEC);
this.farmingBlockStateComponentType = this.getChunkStoreRegistry().registerComponent(FarmingBlockState.class, "Farming", FarmingBlockState.CODEC); this.farmingBlockStateComponentType = chunkStoreRegistry.registerComponent(FarmingBlockState.class, "Farming", FarmingBlockState.CODEC);
this.coopBlockStateComponentType = this.getChunkStoreRegistry().registerComponent(CoopBlock.class, "Coop", CoopBlock.CODEC); this.coopBlockStateComponentType = chunkStoreRegistry.registerComponent(CoopBlock.class, "Coop", CoopBlock.CODEC);
this.coopResidentComponentType = this.getEntityStoreRegistry() this.coopResidentComponentType = entityStoreRegistry.registerComponent(CoopResidentComponent.class, "CoopResident", CoopResidentComponent.CODEC);
.registerComponent(CoopResidentComponent.class, "CoopResident", CoopResidentComponent.CODEC); ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType = BlockModule.BlockStateInfo.getComponentType();
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.OnSoilAdded()); ComponentType<ChunkStore, BlockSection> blockSectionComponentType = BlockSection.getComponentType();
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.OnFarmBlockAdded()); ComponentType<ChunkStore, ChunkSection> chunkSectionComponentType = ChunkSection.getComponentType();
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.Ticking()); ComponentType<EntityStore, UUIDComponent> uuidComponentType = UUIDComponent.getComponentType();
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.MigrateFarming()); chunkStoreRegistry.registerSystem(new FarmingSystems.OnSoilAdded(blockStateInfoComponentType, this.tiledSoilBlockComponentType));
this.getChunkStoreRegistry().registerSystem(new FarmingSystems.OnCoopAdded()); chunkStoreRegistry.registerSystem(new FarmingSystems.OnFarmBlockAdded(blockStateInfoComponentType, this.farmingBlockComponentType));
this.getEntityStoreRegistry().registerSystem(new FarmingSystems.CoopResidentEntitySystem()); chunkStoreRegistry.registerSystem(
this.getEntityStoreRegistry().registerSystem(new FarmingSystems.CoopResidentTicking()); new FarmingSystems.Ticking(
blockSectionComponentType,
chunkSectionComponentType,
this.farmingBlockComponentType,
this.tiledSoilBlockComponentType,
this.coopBlockStateComponentType
)
);
chunkStoreRegistry.registerSystem(new FarmingSystems.MigrateFarming());
chunkStoreRegistry.registerSystem(new FarmingSystems.OnCoopAdded(blockStateInfoComponentType, this.coopBlockStateComponentType));
entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentEntitySystem(this.coopResidentComponentType, uuidComponentType));
entityStoreRegistry.registerSystem(new FarmingSystems.CoopResidentTicking(this.coopResidentComponentType));
this.getEventRegistry().registerGlobal(EventPriority.LAST, ChunkPreLoadProcessEvent.class, FarmingPlugin::preventSpreadOnNew); 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()) { if (event.isNewlyGenerated()) {
BlockComponentChunk components = event.getHolder().getComponent(BlockComponentChunk.getComponentType()); BlockComponentChunk components = event.getHolder().getComponent(BlockComponentChunk.getComponentType());
if (components != null) { if (components != null) {

View File

@@ -42,13 +42,14 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.util.TargetUtil; import com.hypixel.hytale.server.core.util.TargetUtil;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class FarmingSystems { 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) { if (y + 1 >= 320) {
return false; return false;
} else { } else {
@@ -67,35 +68,54 @@ public class FarmingSystems {
} }
} }
private static boolean updateSoilDecayTime(CommandBuffer<ChunkStore> commandBuffer, TilledSoilBlock soilBlock, BlockType blockType) { private static boolean updateSoilDecayTime(
if (blockType != null && blockType.getFarming() != null && blockType.getFarming().getSoilConfig() != null) { @Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull TilledSoilBlock soilBlock, @Nullable BlockType blockType
FarmingData.SoilConfig soilConfig = blockType.getFarming().getSoilConfig(); ) {
Rangef range = soilConfig.getLifetime(); if (blockType == null) {
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; 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> { public static class CoopResidentEntitySystem extends RefSystem<EntityStore> {
private static final ComponentType<EntityStore, CoopResidentComponent> componentType = CoopResidentComponent.getComponentType(); @Nonnull
private final ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType;
@Nonnull
private final ComponentType<EntityStore, UUIDComponent> uuidComponentType;
public CoopResidentEntitySystem(
@Nonnull ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType,
@Nonnull ComponentType<EntityStore, UUIDComponent> uuidComponentType
) {
this.coopResidentComponentType = coopResidentComponentType;
this.uuidComponentType = uuidComponentType;
}
@Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return componentType; return this.coopResidentComponentType;
} }
@Override @Override
@@ -109,26 +129,26 @@ public class FarmingSystems {
@Nonnull Ref<EntityStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer @Nonnull Ref<EntityStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer
) { ) {
if (reason != RemoveReason.UNLOAD) { if (reason != RemoveReason.UNLOAD) {
UUIDComponent uuidComponent = commandBuffer.getComponent(ref, UUIDComponent.getComponentType()); UUIDComponent uuidComponent = commandBuffer.getComponent(ref, this.uuidComponentType);
if (uuidComponent != null) { if (uuidComponent != null) {
UUID uuid = uuidComponent.getUuid(); UUID uuid = uuidComponent.getUuid();
CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, componentType); CoopResidentComponent coopResidentComponent = commandBuffer.getComponent(ref, this.coopResidentComponentType);
if (coopResidentComponent != null) { if (coopResidentComponent != null) {
Vector3i coopPosition = coopResidentComponent.getCoopLocation(); Vector3i coopPosition = coopResidentComponent.getCoopLocation();
World world = commandBuffer.getExternalData().getWorld(); World world = commandBuffer.getExternalData().getWorld();
long chunkIndex = ChunkUtil.indexChunkFromBlock(coopPosition.x, coopPosition.z); long chunkIndex = ChunkUtil.indexChunkFromBlock(coopPosition.x, coopPosition.z);
WorldChunk chunk = world.getChunkIfLoaded(chunkIndex); WorldChunk worldChunkComponent = world.getChunkIfLoaded(chunkIndex);
if (chunk != null) { if (worldChunkComponent != null) {
Ref<ChunkStore> chunkReference = world.getChunkStore().getChunkReference(chunkIndex); Ref<ChunkStore> chunkRef = world.getChunkStore().getChunkReference(chunkIndex);
if (chunkReference != null && chunkReference.isValid()) { if (chunkRef != null && chunkRef.isValid()) {
Store<ChunkStore> chunkStore = world.getChunkStore().getStore(); Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkReference, ChunkColumn.getComponentType()); ChunkColumn chunkColumnComponent = chunkStore.getComponent(chunkRef, ChunkColumn.getComponentType());
if (chunkColumnComponent != null) { if (chunkColumnComponent != null) {
BlockChunk blockChunkComponent = chunkStore.getComponent(chunkReference, BlockChunk.getComponentType()); BlockChunk blockChunkComponent = chunkStore.getComponent(chunkRef, BlockChunk.getComponentType());
if (blockChunkComponent != null) { if (blockChunkComponent != null) {
Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(coopPosition.y)); Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(ChunkUtil.chunkCoordinate(coopPosition.y));
if (sectionRef != null && sectionRef.isValid()) { if (sectionRef != null && sectionRef.isValid()) {
BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkReference, BlockComponentChunk.getComponentType()); BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkRef, BlockComponentChunk.getComponentType());
if (blockComponentChunk != null) { if (blockComponentChunk != null) {
int blockIndexColumn = ChunkUtil.indexBlockInColumn(coopPosition.x, coopPosition.y, coopPosition.z); int blockIndexColumn = ChunkUtil.indexBlockInColumn(coopPosition.x, coopPosition.y, coopPosition.z);
Ref<ChunkStore> coopEntityReference = blockComponentChunk.getEntityReference(blockIndexColumn); Ref<ChunkStore> coopEntityReference = blockComponentChunk.getEntityReference(blockIndexColumn);
@@ -151,11 +171,17 @@ public class FarmingSystems {
} }
public static class CoopResidentTicking extends EntityTickingSystem<EntityStore> { public static class CoopResidentTicking extends EntityTickingSystem<EntityStore> {
private static final ComponentType<EntityStore, CoopResidentComponent> componentType = CoopResidentComponent.getComponentType(); @Nonnull
private final ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType;
public CoopResidentTicking(@Nonnull ComponentType<EntityStore, CoopResidentComponent> coopResidentComponentType) {
this.coopResidentComponentType = coopResidentComponentType;
}
@Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return componentType; return this.coopResidentComponentType;
} }
@Override @Override
@@ -166,11 +192,12 @@ public class FarmingSystems {
@Nonnull Store<EntityStore> store, @Nonnull Store<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> commandBuffer @Nonnull CommandBuffer<EntityStore> commandBuffer
) { ) {
CoopResidentComponent coopResidentComponent = archetypeChunk.getComponent(index, CoopResidentComponent.getComponentType()); CoopResidentComponent coopResidentComponent = archetypeChunk.getComponent(index, this.coopResidentComponentType);
if (coopResidentComponent != null) {
if (coopResidentComponent.getMarkedForDespawn()) { assert coopResidentComponent != null;
commandBuffer.removeEntity(archetypeChunk.getReferenceTo(index), RemoveReason.REMOVE);
} if (coopResidentComponent.getMarkedForDespawn()) {
commandBuffer.removeEntity(archetypeChunk.getReferenceTo(index), RemoveReason.REMOVE);
} }
} }
} }
@@ -200,32 +227,47 @@ public class FarmingSystems {
} }
public static class OnCoopAdded extends RefSystem<ChunkStore> { public static class OnCoopAdded extends RefSystem<ChunkStore> {
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), CoopBlock.getComponentType()); @Nonnull
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<ChunkStore, CoopBlock> coopBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public OnCoopAdded(
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<ChunkStore, CoopBlock> coopBlockComponentType
) {
this.blockStateInfoComponentType = blockStateInfoComponentType;
this.coopBlockComponentType = coopBlockComponentType;
this.query = Query.and(blockStateInfoComponentType, coopBlockComponentType);
}
@Override @Override
public void onEntityAdded( public void onEntityAdded(
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer @Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
) { ) {
CoopBlock coopBlock = commandBuffer.getComponent(ref, CoopBlock.getComponentType()); CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, this.coopBlockComponentType);
if (coopBlock != null) {
WorldTimeResource worldTimeResource = commandBuffer.getExternalData()
.getWorld()
.getEntityStore()
.getStore()
.getResource(WorldTimeResource.getResourceType());
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
assert info != null; assert coopBlockComponent != null;
int x = ChunkUtil.xFromBlockInColumn(info.getIndex()); BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType());
assert blockChunk != null; assert blockStateInfoComponent != null;
BlockSection blockSection = blockChunk.getSectionAtBlockY(y); World world = commandBuffer.getExternalData().getWorld();
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), coopBlock.getNextScheduledTick(worldTimeResource)); Store<EntityStore> entityStore = world.getEntityStore().getStore();
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
int x = ChunkUtil.xFromBlockInColumn(blockStateInfoComponent.getIndex());
int y = ChunkUtil.yFromBlockInColumn(blockStateInfoComponent.getIndex());
int z = ChunkUtil.zFromBlockInColumn(blockStateInfoComponent.getIndex());
Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
if (chunkRef.isValid()) {
BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
if (blockChunkComponent != null) {
BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), coopBlockComponent.getNextScheduledTick(worldTimeResource));
}
} }
} }
@@ -234,147 +276,188 @@ public class FarmingSystems {
@Nonnull Ref<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer @Nonnull Ref<ChunkStore> ref, @Nonnull RemoveReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
) { ) {
if (reason != RemoveReason.UNLOAD) { if (reason != RemoveReason.UNLOAD) {
CoopBlock coop = commandBuffer.getComponent(ref, CoopBlock.getComponentType()); CoopBlock coopBlockComponent = commandBuffer.getComponent(ref, this.coopBlockComponentType);
if (coop != null) {
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
assert info != null; assert coopBlockComponent != null;
Store<EntityStore> entityStore = commandBuffer.getExternalData().getWorld().getEntityStore().getStore(); BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
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());
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); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getY(), y);
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getZ(), z); assert chunkSectionComponent != null;
World world = commandBuffer.getExternalData().getWorld();
WorldTimeResource worldTimeResource = world.getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()); int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
coop.handleBlockBroken(world, worldTimeResource, entityStore, worldX, worldY, worldZ); int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
} int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
World world = commandBuffer.getExternalData().getWorld();
Store<EntityStore> entityStore = world.getEntityStore().getStore();
WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
coopBlockComponent.handleBlockBroken(world, worldTimeResource, entityStore, worldX, worldY, worldZ);
} }
} }
@Nullable @Nonnull
@Override @Override
public Query<ChunkStore> getQuery() { public Query<ChunkStore> getQuery() {
return QUERY; return this.query;
} }
} }
public static class OnFarmBlockAdded extends RefSystem<ChunkStore> { public static class OnFarmBlockAdded extends RefSystem<ChunkStore> {
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), FarmingBlock.getComponentType()); @Nonnull
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public OnFarmBlockAdded(
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType
) {
this.blockStateInfoComponentType = blockStateInfoComponentType;
this.farmingBlockComponentType = farmingBlockComponentType;
this.query = Query.and(blockStateInfoComponentType, farmingBlockComponentType);
}
@Override @Override
public void onEntityAdded( public void onEntityAdded(
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer @Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
) { ) {
FarmingBlock farmingBlock = commandBuffer.getComponent(ref, FarmingBlock.getComponentType()); FarmingBlock farmingBlockComponent = commandBuffer.getComponent(ref, this.farmingBlockComponentType);
assert farmingBlock != null; assert farmingBlockComponent != null;
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
assert info != null; assert blockStateInfoComponent != null;
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType()); Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
if (farmingBlock.getLastTickGameTime() == null) { if (chunkRef.isValid()) {
int blockId = blockChunk.getBlock( BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
ChunkUtil.xFromBlockInColumn(info.getIndex()), ChunkUtil.yFromBlockInColumn(info.getIndex()), ChunkUtil.zFromBlockInColumn(info.getIndex())
);
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
if (blockType.getFarming() == null) {
return;
}
farmingBlock.setCurrentStageSet(blockType.getFarming().getStartingStageSet()); assert blockChunkComponent != null;
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;
for (int i = 0; i < stages.length; i++) { World world = store.getExternalData().getWorld();
FarmingStageData stage = stages[i]; Store<EntityStore> entityStore = world.getEntityStore().getStore();
switch (stage) { WorldTimeResource worldTimeResource = entityStore.getResource(WorldTimeResource.getResourceType());
case BlockTypeFarmingStageData data: if (farmingBlockComponent.getLastTickGameTime() == null) {
if (data.getBlock().equals(blockType.getId())) { int index = blockStateInfoComponent.getIndex();
farmingBlock.setGrowthProgress(i); int blockId = blockChunkComponent.getBlock(
found = true; ChunkUtil.xFromBlockInColumn(index), ChunkUtil.yFromBlockInColumn(index), ChunkUtil.zFromBlockInColumn(index)
} );
break; BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
case BlockStateFarmingStageData datax: if (blockType == null) {
BlockType stateBlockType = blockType.getBlockForState(datax.getState()); return;
if (stateBlockType != null && stateBlockType.getId().equals(blockType.getId())) { }
farmingBlock.setGrowthProgress(i);
found = true; FarmingData blockTypeFarming = blockType.getFarming();
} if (blockTypeFarming == null) {
break; return;
default: }
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) { if (!found) {
Ref<ChunkStore> sectionRef = commandBuffer.getComponent(info.getChunkRef(), ChunkColumn.getComponentType()) ChunkColumn chunkColumnComponent = commandBuffer.getComponent(chunkRef, ChunkColumn.getComponentType());
.getSection(ChunkUtil.chunkCoordinate(ChunkUtil.yFromBlockInColumn(info.getIndex())));
stages[0] assert chunkColumnComponent != null;
.apply(
commandBuffer, int chunkCoordinate = ChunkUtil.chunkCoordinate(ChunkUtil.yFromBlockInColumn(index));
sectionRef, Ref<ChunkStore> sectionRef = chunkColumnComponent.getSection(chunkCoordinate);
ref, if (sectionRef != null && sectionRef.isValid()) {
ChunkUtil.xFromBlockInColumn(info.getIndex()), stages[0]
ChunkUtil.yFromBlockInColumn(info.getIndex()), .apply(
ChunkUtil.zFromBlockInColumn(info.getIndex()), commandBuffer,
null 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 @Override
@@ -383,51 +466,67 @@ public class FarmingSystems {
) { ) {
} }
@Nullable @Nonnull
@Override @Override
public Query<ChunkStore> getQuery() { public Query<ChunkStore> getQuery() {
return QUERY; return this.query;
} }
} }
public static class OnSoilAdded extends RefSystem<ChunkStore> { public static class OnSoilAdded extends RefSystem<ChunkStore> {
private static final Query<ChunkStore> QUERY = Query.and(BlockModule.BlockStateInfo.getComponentType(), TilledSoilBlock.getComponentType()); @Nonnull
private final ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType;
@Nonnull
private final ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public OnSoilAdded(
@Nonnull ComponentType<ChunkStore, BlockModule.BlockStateInfo> blockStateInfoComponentType,
@Nonnull ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType
) {
this.blockStateInfoComponentType = blockStateInfoComponentType;
this.tilledSoilBlockComponentType = tilledSoilBlockComponentType;
this.query = Query.and(blockStateInfoComponentType, tilledSoilBlockComponentType);
}
@Override @Override
public void onEntityAdded( public void onEntityAdded(
@Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer @Nonnull Ref<ChunkStore> ref, @Nonnull AddReason reason, @Nonnull Store<ChunkStore> store, @Nonnull CommandBuffer<ChunkStore> commandBuffer
) { ) {
TilledSoilBlock soil = commandBuffer.getComponent(ref, TilledSoilBlock.getComponentType()); TilledSoilBlock soilComponent = commandBuffer.getComponent(ref, this.tilledSoilBlockComponentType);
assert soil != null; assert soilComponent != null;
BlockModule.BlockStateInfo info = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(ref, this.blockStateInfoComponentType);
assert info != null; assert blockStateInfoComponent != null;
if (!soil.isPlanted()) { Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
int x = ChunkUtil.xFromBlockInColumn(info.getIndex()); if (chunkRef.isValid()) {
int y = ChunkUtil.yFromBlockInColumn(info.getIndex()); if (!soilComponent.isPlanted()) {
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);
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); blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
Instant decayTime = soil.getDecayTime();
if (decayTime == null) {
BlockType blockType = BlockType.getAssetMap().getAsset(blockSection.get(x, y, z));
FarmingSystems.updateSoilDecayTime(commandBuffer, soil, blockType);
} }
if (decayTime == null) {
return;
}
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), decayTime);
} }
} }
@@ -437,15 +536,41 @@ public class FarmingSystems {
) { ) {
} }
@Nullable @Nonnull
@Override @Override
public Query<ChunkStore> getQuery() { public Query<ChunkStore> getQuery() {
return QUERY; return this.query;
} }
} }
public static class Ticking extends EntityTickingSystem<ChunkStore> { public static class Ticking extends EntityTickingSystem<ChunkStore> {
private static final Query<ChunkStore> QUERY = Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType()); @Nonnull
private final ComponentType<ChunkStore, BlockSection> blockSectionComponentType;
@Nonnull
private final ComponentType<ChunkStore, ChunkSection> chunkSectionComponentType;
@Nonnull
private final ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType;
@Nonnull
private final ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType;
@Nonnull
private final ComponentType<ChunkStore, CoopBlock> coopBlockComponentType;
@Nonnull
private final Query<ChunkStore> query;
public Ticking(
@Nonnull ComponentType<ChunkStore, BlockSection> blockSectionComponentType,
@Nonnull ComponentType<ChunkStore, ChunkSection> chunkSectionComponentType,
@Nonnull ComponentType<ChunkStore, FarmingBlock> farmingBlockComponentType,
@Nonnull ComponentType<ChunkStore, TilledSoilBlock> tilledSoilBlockComponentType,
@Nonnull ComponentType<ChunkStore, CoopBlock> coopBlockComponentType
) {
this.blockSectionComponentType = blockSectionComponentType;
this.chunkSectionComponentType = chunkSectionComponentType;
this.farmingBlockComponentType = farmingBlockComponentType;
this.tilledSoilBlockComponentType = tilledSoilBlockComponentType;
this.coopBlockComponentType = coopBlockComponentType;
this.query = Query.and(blockSectionComponentType, chunkSectionComponentType);
}
@Override @Override
public void tick( public void tick(
@@ -455,44 +580,50 @@ public class FarmingSystems {
@Nonnull Store<ChunkStore> store, @Nonnull Store<ChunkStore> store,
@Nonnull CommandBuffer<ChunkStore> commandBuffer @Nonnull CommandBuffer<ChunkStore> commandBuffer
) { ) {
BlockSection blocks = archetypeChunk.getComponent(index, BlockSection.getComponentType()); BlockSection blockSectionComponent = archetypeChunk.getComponent(index, this.blockSectionComponentType);
assert blocks != null; assert blockSectionComponent != null;
if (blocks.getTickingBlocksCountCopy() != 0) { if (blockSectionComponent.getTickingBlocksCountCopy() != 0) {
ChunkSection section = archetypeChunk.getComponent(index, ChunkSection.getComponentType()); ChunkSection chunkSectionComponent = archetypeChunk.getComponent(index, this.chunkSectionComponentType);
assert section != null; assert chunkSectionComponent != null;
if (section.getChunkColumnReference() != null && section.getChunkColumnReference().isValid()) { Ref<ChunkStore> chunkColumnRef = chunkSectionComponent.getChunkColumnReference();
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(section.getChunkColumnReference(), BlockComponentChunk.getComponentType()); if (chunkColumnRef != null && chunkColumnRef.isValid()) {
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunkColumnRef, BlockComponentChunk.getComponentType());
assert blockComponentChunk != null; assert blockComponentChunk != null;
Ref<ChunkStore> ref = archetypeChunk.getReferenceTo(index); Ref<ChunkStore> ref = archetypeChunk.getReferenceTo(index);
BlockChunk blockChunk = commandBuffer.getComponent(section.getChunkColumnReference(), BlockChunk.getComponentType()); BlockChunk blockChunk = commandBuffer.getComponent(chunkColumnRef, BlockChunk.getComponentType());
assert blockChunk != null; assert blockChunk != null;
blocks.forEachTicking( blockSectionComponent.forEachTicking(
blockComponentChunk, commandBuffer, section.getY(), (blockComponentChunk1, commandBuffer1, localX, localY, localZ, blockId) -> { blockComponentChunk,
commandBuffer,
chunkSectionComponent.getY(),
(blockComponentChunk1, commandBuffer1, localX, localY, localZ, blockId) -> {
Ref<ChunkStore> blockRef = blockComponentChunk1.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ)); Ref<ChunkStore> blockRef = blockComponentChunk1.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ));
if (blockRef == null) { if (blockRef == null) {
return BlockTickStrategy.IGNORED; return BlockTickStrategy.IGNORED;
} else { } else {
FarmingBlock farming = commandBuffer1.getComponent(blockRef, FarmingBlock.getComponentType()); FarmingBlock farmingBlockComp = commandBuffer1.getComponent(blockRef, this.farmingBlockComponentType);
if (farming != null) { if (farmingBlockComp != null) {
FarmingUtil.tickFarming(commandBuffer1, blockChunk, blocks, ref, blockRef, farming, localX, localY, localZ, false); FarmingUtil.tickFarming(
commandBuffer1, blockChunk, blockSectionComponent, ref, blockRef, farmingBlockComp, localX, localY, localZ, false
);
return BlockTickStrategy.SLEEP; return BlockTickStrategy.SLEEP;
} else { } else {
TilledSoilBlock soil = commandBuffer1.getComponent(blockRef, TilledSoilBlock.getComponentType()); TilledSoilBlock tilledSoilBlockComp = commandBuffer1.getComponent(blockRef, this.tilledSoilBlockComponentType);
if (soil != null) { if (tilledSoilBlockComp != null) {
tickSoil(commandBuffer1, blockComponentChunk1, blockRef, soil); tickSoil(commandBuffer1, blockRef, tilledSoilBlockComp);
return BlockTickStrategy.SLEEP; return BlockTickStrategy.SLEEP;
} else { } else {
CoopBlock coop = commandBuffer1.getComponent(blockRef, CoopBlock.getComponentType()); CoopBlock coopBlockComp = commandBuffer1.getComponent(blockRef, this.coopBlockComponentType);
if (coop != null) { if (coopBlockComp != null) {
tickCoop(commandBuffer1, blockComponentChunk1, blockRef, coop); tickCoop(commandBuffer1, blockRef, coopBlockComp);
return BlockTickStrategy.SLEEP; return BlockTickStrategy.SLEEP;
} else { } else {
return BlockTickStrategy.IGNORED; return BlockTickStrategy.IGNORED;
@@ -506,122 +637,128 @@ public class FarmingSystems {
} }
} }
private static void tickSoil( private static void tickSoil(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> blockRef, @Nonnull TilledSoilBlock soilBlock) {
CommandBuffer<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, Ref<ChunkStore> blockRef, TilledSoilBlock soilBlock BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
) {
BlockModule.BlockStateInfo info = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
assert info != null; assert blockStateInfoComponent != null;
int x = ChunkUtil.xFromBlockInColumn(info.getIndex()); int index = blockStateInfoComponent.getIndex();
int y = ChunkUtil.yFromBlockInColumn(info.getIndex()); int x = ChunkUtil.xFromBlockInColumn(index);
int z = ChunkUtil.zFromBlockInColumn(info.getIndex()); int y = ChunkUtil.yFromBlockInColumn(index);
int z = ChunkUtil.zFromBlockInColumn(index);
if (y < 320) { if (y < 320) {
assert info.getChunkRef() != null; Ref<ChunkStore> chunkRef = blockStateInfoComponent.getChunkRef();
if (chunkRef.isValid()) {
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType()); BlockChunk blockChunkComponent = commandBuffer.getComponent(chunkRef, BlockChunk.getComponentType());
if (blockChunkComponent != null) {
assert blockChunk != null; BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(y);
boolean hasCrop = FarmingSystems.hasCropAbove(blockChunkComponent, x, y, z);
BlockSection blockSection = blockChunk.getSectionAtBlockY(y); int blockId = blockSection.get(x, y, z);
boolean hasCrop = FarmingSystems.hasCropAbove(blockChunk, x, y, z); BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockId);
BlockType blockType = BlockType.getAssetMap().getAsset(blockSection.get(x, y, z)); if (blockTypeAsset != null) {
Instant currentTime = commandBuffer.getExternalData() Instant currentTime = commandBuffer.getExternalData()
.getWorld() .getWorld()
.getEntityStore() .getEntityStore()
.getStore() .getStore()
.getResource(WorldTimeResource.getResourceType()) .getResource(WorldTimeResource.getResourceType())
.getGameTime(); .getGameTime();
Instant decayTime = soilBlock.getDecayTime(); Instant decayTime = soilBlock.getDecayTime();
if (soilBlock.isPlanted() && !hasCrop) { if (soilBlock.isPlanted() && !hasCrop) {
if (!FarmingSystems.updateSoilDecayTime(commandBuffer, soilBlock, blockType)) { 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)) {
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));
return; 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( private static void tickCoop(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> blockRef, @Nonnull CoopBlock coopBlock) {
CommandBuffer<ChunkStore> commandBuffer, BlockComponentChunk blockComponentChunk, Ref<ChunkStore> blockRef, CoopBlock coopBlock BlockModule.BlockStateInfo blockStateInfoComponent = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
) {
BlockModule.BlockStateInfo info = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
assert info != null; assert blockStateInfoComponent != null;
Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore(); Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType()); WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType());
FarmingCoopAsset coopAsset = coopBlock.getCoopAsset(); FarmingCoopAsset coopAsset = coopBlock.getCoopAsset();
if (coopAsset != null) { if (coopAsset != null) {
int x = ChunkUtil.xFromBlockInColumn(info.getIndex()); int index = blockStateInfoComponent.getIndex();
int y = ChunkUtil.yFromBlockInColumn(info.getIndex()); int x = ChunkUtil.xFromBlockInColumn(index);
int z = ChunkUtil.zFromBlockInColumn(info.getIndex()); int y = ChunkUtil.yFromBlockInColumn(index);
BlockChunk blockChunk = commandBuffer.getComponent(info.getChunkRef(), BlockChunk.getComponentType()); 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; 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 worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getY(), y); int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSection.getZ(), z); int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
World world = commandBuffer.getExternalData().getWorld(); 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(); double blockRotation = chunk.getRotation(worldX, worldY, worldZ).yaw().getRadians();
Vector3d spawnOffset = new Vector3d().assign(coopAsset.getResidentSpawnOffset()).rotateY((float)blockRotation); Vector3d spawnOffset = new Vector3d().assign(coopAsset.getResidentSpawnOffset()).rotateY((float)blockRotation);
Vector3i coopLocation = new Vector3i(worldX, worldY, worldZ); Vector3i coopLocation = new Vector3i(worldX, worldY, worldZ);
@@ -652,15 +789,15 @@ public class FarmingSystems {
Instant nextTickInstant = coopBlock.getNextScheduledTick(worldTimeResource); Instant nextTickInstant = coopBlock.getNextScheduledTick(worldTimeResource);
if (nextTickInstant != null) { if (nextTickInstant != null) {
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), nextTickInstant); blockSectionComponent.scheduleTick(ChunkUtil.indexBlock(x, y, z), nextTickInstant);
} }
} }
} }
@Nullable @Nonnull
@Override @Override
public Query<ChunkStore> getQuery() { public Query<ChunkStore> getQuery() {
return QUERY; return this.query;
} }
} }
} }

View File

@@ -20,6 +20,7 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Farmin
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset; import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset; 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.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.block.BlockModule;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel; import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.interaction.BlockHarvestUtils; import com.hypixel.hytale.server.core.modules.interaction.BlockHarvestUtils;
@@ -43,19 +44,20 @@ public class FarmingUtil {
private static final int BETWEEN_RANDOM = 10; private static final int BETWEEN_RANDOM = 10;
public static void tickFarming( public static void tickFarming(
CommandBuffer<ChunkStore> commandBuffer, @Nonnull CommandBuffer<ChunkStore> commandBuffer,
BlockChunk blockChunk, @Nonnull BlockChunk blockChunk,
BlockSection blockSection, @Nonnull BlockSection blockSection,
Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> sectionRef,
Ref<ChunkStore> blockRef, @Nonnull Ref<ChunkStore> blockRef,
FarmingBlock farmingBlock, @Nonnull FarmingBlock farmingBlock,
int x, int x,
int y, int y,
int z, int z,
boolean initialTick boolean initialTick
) { ) {
World world = commandBuffer.getExternalData().getWorld(); 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(); Instant currentTime = worldTimeResource.getGameTime();
BlockType blockType = farmingBlock.getPreviousBlockType() != null BlockType blockType = farmingBlock.getPreviousBlockType() != null
? BlockType.getAssetMap().getAsset(farmingBlock.getPreviousBlockType()) ? BlockType.getAssetMap().getAsset(farmingBlock.getPreviousBlockType())
@@ -90,77 +92,79 @@ public class FarmingUtil {
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE); commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
} else { } else {
long remainingTimeSeconds = currentTime.getEpochSecond() - farmingBlock.getLastTickGameTime().getEpochSecond(); long remainingTimeSeconds = currentTime.getEpochSecond() - farmingBlock.getLastTickGameTime().getEpochSecond();
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x); if (chunkSectionComponent != null) {
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y); int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z); int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
while (currentStage < stages.length) { while (currentStage < stages.length) {
FarmingStageData stage = stages[currentStage]; FarmingStageData stage = stages[currentStage];
if (stage.shouldStop(commandBuffer, sectionRef, blockRef, x, y, z)) { if (stage.shouldStop(commandBuffer, sectionRef, blockRef, x, y, z)) {
blockChunk.markNeedsSaving(); 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 {
farmingBlock.setGrowthProgress(stages.length); farmingBlock.setGrowthProgress(stages.length);
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE); commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
break;
} }
} else {
farmingBlock.setExecutions(0);
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage - 1]);
}
}
farmingBlock.setLastTickGameTime(currentTime); Rangef range = stage.getDuration();
if (range == null) {
blockChunk.markNeedsSaving();
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
break;
}
double rand = HashUtil.random(farmingBlock.getGeneration(), worldX, worldY, worldZ);
double baseDuration = range.min + (range.max - range.min) * rand;
long remainingDurationSeconds = Math.round(baseDuration * (1.0 - currentProgress % 1.0));
double growthMultiplier = 1.0;
if (farmingConfig.getGrowthModifiers() != null) {
for (String modifierName : farmingConfig.getGrowthModifiers()) {
GrowthModifierAsset modifierAsset = GrowthModifierAsset.getAssetMap().getAsset(modifierName);
if (modifierAsset != null) {
growthMultiplier *= modifierAsset.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick);
}
}
}
remainingDurationSeconds = Math.round(remainingDurationSeconds / growthMultiplier);
if (remainingTimeSeconds < remainingDurationSeconds) {
currentProgress += (float)(remainingTimeSeconds / (baseDuration / growthMultiplier));
farmingBlock.setGrowthProgress(currentProgress);
long nextGrowthInNanos = (remainingDurationSeconds - remainingTimeSeconds) * 1000000000L;
long randCap = (long)(
(15.0 + 10.0 * HashUtil.random(farmingBlock.getGeneration() ^ 3405692655L, worldX, worldY, worldZ))
* world.getTps()
* WorldTimeResource.getSecondsPerTick(world)
* 1.0E9
);
long cappedNextGrowthInNanos = Math.min(nextGrowthInNanos, randCap);
blockSection.scheduleTick(ChunkUtil.indexBlock(x, y, z), currentTime.plusNanos(cappedNextGrowthInNanos));
break;
}
remainingTimeSeconds -= remainingDurationSeconds;
currentProgress = ++currentStage;
farmingBlock.setGrowthProgress(currentProgress);
blockChunk.markNeedsSaving();
farmingBlock.setGeneration(farmingBlock.getGeneration() + 1);
if (currentStage >= stages.length) {
if (stages[currentStage - 1].implementsShouldStop()) {
currentStage = stages.length - 1;
farmingBlock.setGrowthProgress(currentStage);
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage]);
} else {
farmingBlock.setGrowthProgress(stages.length);
commandBuffer.removeEntity(blockRef, RemoveReason.REMOVE);
}
} else {
farmingBlock.setExecutions(0);
stages[currentStage].apply(commandBuffer, sectionRef, blockRef, x, y, z, stages[currentStage - 1]);
}
}
farmingBlock.setLastTickGameTime(currentTime);
}
} }
} }
} }
@@ -168,22 +172,22 @@ public class FarmingUtil {
} }
} }
public static void harvest( public static boolean harvest(
@Nonnull World world, @Nonnull World world,
@Nonnull ComponentAccessor<EntityStore> store, @Nonnull ComponentAccessor<EntityStore> componentAccessor,
@Nonnull Ref<EntityStore> ref, @Nonnull Ref<EntityStore> ref,
@Nonnull BlockType blockType, @Nonnull BlockType blockType,
int rotationIndex, int rotationIndex,
@Nonnull Vector3i blockPosition @Nonnull Vector3i blockPosition
) { ) {
if (world.getGameplayConfig().getWorldConfig().isBlockGatheringAllowed()) { return world.getGameplayConfig().getWorldConfig().isBlockGatheringAllowed()
harvest0(store, ref, blockType, rotationIndex, blockPosition); ? harvest0(componentAccessor, ref, blockType, rotationIndex, blockPosition)
} : false;
} }
@Nullable @Nullable
public static CapturedNPCMetadata generateCapturedNPCMetadata( 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()); PersistentModel persistentModel = componentAccessor.getComponent(entityRef, PersistentModel.getComponentType());
if (persistentModel == null) { if (persistentModel == null) {
@@ -195,7 +199,7 @@ public class FarmingUtil {
meta.setIconPath(modelAsset.getIcon()); meta.setIconPath(modelAsset.getIcon());
} }
meta.setRoleIndex(roleIndex); meta.setNpcNameKey(npcNameKey);
return meta; return meta;
} }
} }
@@ -208,24 +212,19 @@ public class FarmingUtil {
@Nonnull Vector3i blockPosition @Nonnull Vector3i blockPosition
) { ) {
FarmingData farmingConfig = blockType.getFarming(); FarmingData farmingConfig = blockType.getFarming();
boolean isFarmable = true;
if (farmingConfig == null || farmingConfig.getStages() == null) { if (farmingConfig == null || farmingConfig.getStages() == null) {
return false; isFarmable = false;
} else if (blockType.getGathering().getHarvest() == null) { }
if (blockType.getGathering().getHarvest() == null) {
return false; return false;
} else { } else {
World world = store.getExternalData().getWorld(); World world = store.getExternalData().getWorld();
Vector3d centerPosition = new Vector3d(); Vector3d centerPosition = new Vector3d();
blockType.getBlockCenter(rotationIndex, centerPosition); blockType.getBlockCenter(rotationIndex, centerPosition);
centerPosition.add(blockPosition); centerPosition.add(blockPosition);
if (farmingConfig.getStageSetAfterHarvest() == null) { if (isFarmable && farmingConfig.getStageSetAfterHarvest() != null) {
giveDrops(store, ref, centerPosition, blockType);
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z));
if (chunk != null) {
chunk.breakBlock(blockPosition.x, blockPosition.y, blockPosition.z);
}
return true;
} else {
giveDrops(store, ref, centerPosition, blockType); giveDrops(store, ref, centerPosition, blockType);
Map<String, FarmingStageData[]> stageSets = farmingConfig.getStages(); Map<String, FarmingStageData[]> stageSets = farmingConfig.getStages();
FarmingStageData[] stages = stageSets.get(farmingConfig.getStartingStageSet()); FarmingStageData[] stages = stageSets.get(farmingConfig.getStartingStageSet());
@@ -285,7 +284,8 @@ public class FarmingUtil {
} else { } else {
BlockSection section = chunkStore.getComponent(sectionRef, BlockSection.getComponentType()); BlockSection section = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
if (section != null) { 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); newStages[0].apply(chunkStore, sectionRef, blockRef, blockPosition.x, blockPosition.y, blockPosition.z, previousStage);
@@ -302,6 +302,14 @@ public class FarmingUtil {
return false; return false;
} }
} }
} else {
giveDrops(store, ref, centerPosition, blockType);
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z));
if (chunk != null) {
chunk.breakBlock(blockPosition.x, blockPosition.y, blockPosition.z);
}
return true;
} }
} }
} }
@@ -312,6 +320,9 @@ public class FarmingUtil {
HarvestingDropType harvest = blockType.getGathering().getHarvest(); HarvestingDropType harvest = blockType.getGathering().getHarvest();
String itemId = harvest.getItemId(); String itemId = harvest.getItemId();
String dropListId = harvest.getDropListId(); String dropListId = harvest.getDropListId();
BlockHarvestUtils.getDrops(blockType, 1, itemId, dropListId).forEach(itemStack -> ItemUtils.interactivelyPickupItem(ref, itemStack, origin, store));
for (ItemStack itemStack : BlockHarvestUtils.getDrops(blockType, 1, itemId, dropListId)) {
ItemUtils.interactivelyPickupItem(ref, itemStack, origin, store);
}
} }
} }

View File

@@ -7,9 +7,11 @@ import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class CoopResidentComponent implements Component<EntityStore> { public class CoopResidentComponent implements Component<EntityStore> {
@Nonnull
public static final BuilderCodec<CoopResidentComponent> CODEC = BuilderCodec.builder(CoopResidentComponent.class, CoopResidentComponent::new) 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) .append(new KeyedCodec<>("CoopLocation", Vector3i.CODEC), (comp, ref) -> comp.coopLocation = ref, comp -> comp.coopLocation)
.add() .add()
@@ -20,6 +22,7 @@ public class CoopResidentComponent implements Component<EntityStore> {
) )
.add() .add()
.build(); .build();
@Nonnull
private Vector3i coopLocation = new Vector3i(); private Vector3i coopLocation = new Vector3i();
private boolean markedForDespawn; private boolean markedForDespawn;
@@ -27,10 +30,11 @@ public class CoopResidentComponent implements Component<EntityStore> {
return FarmingPlugin.get().getCoopResidentComponentType(); return FarmingPlugin.get().getCoopResidentComponentType();
} }
public void setCoopLocation(Vector3i coopLocation) { public void setCoopLocation(@Nonnull Vector3i coopLocation) {
this.coopLocation = coopLocation; this.coopLocation = coopLocation;
} }
@Nonnull
public Vector3i getCoopLocation() { public Vector3i getCoopLocation() {
return this.coopLocation; return this.coopLocation;
} }

View File

@@ -20,6 +20,7 @@ import java.util.Map;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, FarmingCoopAsset>> { public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, FarmingCoopAsset>> {
@Nonnull
public static final AssetBuilderCodec<String, FarmingCoopAsset> CODEC = AssetBuilderCodec.builder( 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 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 int maxResidents;
protected Map<String, String> produceDrops = Collections.emptyMap(); protected Map<String, String> produceDrops = Collections.emptyMap();
protected IntRange residentRoamTime; protected IntRange residentRoamTime;
@Nonnull
protected Vector3d residentSpawnOffset = new Vector3d(); protected Vector3d residentSpawnOffset = new Vector3d();
protected String[] acceptedNpcGroupIds; protected String[] acceptedNpcGroupIds;
protected int[] acceptedNpcGroupIndexes; protected int[] acceptedNpcGroupIndexes;
@@ -128,6 +130,7 @@ public class FarmingCoopAsset implements JsonAssetWithMap<String, DefaultAssetMa
return this.residentRoamTime; return this.residentRoamTime;
} }
@Nonnull
public Vector3d getResidentSpawnOffset() { public Vector3d getResidentSpawnOffset() {
return this.residentSpawnOffset; return this.residentSpawnOffset;
} }

View File

@@ -9,8 +9,10 @@ import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.Growth
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk; import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import javax.annotation.Nonnull;
public class FertilizerGrowthModifierAsset extends GrowthModifierAsset { public class FertilizerGrowthModifierAsset extends GrowthModifierAsset {
@Nonnull
public static final BuilderCodec<FertilizerGrowthModifierAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<FertilizerGrowthModifierAsset> CODEC = BuilderCodec.builder(
FertilizerGrowthModifierAsset.class, FertilizerGrowthModifierAsset::new, ABSTRACT_CODEC FertilizerGrowthModifierAsset.class, FertilizerGrowthModifierAsset::new, ABSTRACT_CODEC
) )
@@ -18,17 +20,37 @@ public class FertilizerGrowthModifierAsset extends GrowthModifierAsset {
@Override @Override
public double getCurrentGrowthMultiplier( 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()); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference();
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType()); assert chunkSectionComponent != null;
Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z));
if (blockRefBelow == null) { Ref<ChunkStore> chunkRef = chunkSectionComponent.getChunkColumnReference();
return 1.0; 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 { } else {
TilledSoilBlock soil = commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType()); return 1.0;
return soil != null && soil.isFertilized() ? super.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick) : 1.0;
} }
} }
} }

View File

@@ -10,12 +10,15 @@ import com.hypixel.hytale.protocol.Rangef;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset; import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;
import com.hypixel.hytale.server.core.codec.ProtocolCodecs; import com.hypixel.hytale.server.core.codec.ProtocolCodecs;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource; 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.BlockSection;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkLightData; 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.ChunkStore;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class LightLevelGrowthModifierAsset extends GrowthModifierAsset { public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
@Nonnull
public static final BuilderCodec<LightLevelGrowthModifierAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<LightLevelGrowthModifierAsset> CODEC = BuilderCodec.builder(
LightLevelGrowthModifierAsset.class, LightLevelGrowthModifierAsset::new, ABSTRACT_CODEC 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); 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; Rangef range = this.sunlight;
double sunlightFactor = worldTimeResource.getSunlightFactor(); double sunlightFactor = worldTimeResource.getSunlightFactor();
double daylight = sunlightFactor * sky; double daylight = sunlightFactor * sky;
@@ -70,19 +73,26 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
@Override @Override
public double getCurrentGrowthMultiplier( 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()); BlockSection blockSectionComponent = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
short lightRaw = blockSection.getGlobalLight().getLightRaw(x, y, z);
assert blockSectionComponent != null;
short lightRaw = blockSectionComponent.getGlobalLight().getLightRaw(x, y, z);
byte redLight = ChunkLightData.getLightValue(lightRaw, 0); byte redLight = ChunkLightData.getLightValue(lightRaw, 0);
byte greenLight = ChunkLightData.getLightValue(lightRaw, 1); byte greenLight = ChunkLightData.getLightValue(lightRaw, 1);
byte blueLight = ChunkLightData.getLightValue(lightRaw, 2); byte blueLight = ChunkLightData.getLightValue(lightRaw, 2);
byte skyLight = ChunkLightData.getLightValue(lightRaw, 3); byte skyLight = ChunkLightData.getLightValue(lightRaw, 3);
WorldTimeResource worldTimeResource = commandBuffer.getExternalData() World world = commandBuffer.getExternalData().getWorld();
.getWorld() EntityStore entityStore = world.getEntityStore();
.getEntityStore() WorldTimeResource worldTimeResource = entityStore.getStore().getResource(WorldTimeResource.getResourceType());
.getStore()
.getResource(WorldTimeResource.getResourceType());
boolean active = false; boolean active = false;
boolean onlySunlight = false; boolean onlySunlight = false;
if (this.requireBoth) { if (this.requireBoth) {
@@ -117,6 +127,7 @@ public class LightLevelGrowthModifierAsset extends GrowthModifierAsset {
} }
public static class ArtificialLight { public static class ArtificialLight {
@Nonnull
public static final BuilderCodec<LightLevelGrowthModifierAsset.ArtificialLight> CODEC = BuilderCodec.builder( public static final BuilderCodec<LightLevelGrowthModifierAsset.ArtificialLight> CODEC = BuilderCodec.builder(
LightLevelGrowthModifierAsset.ArtificialLight.class, LightLevelGrowthModifierAsset.ArtificialLight::new LightLevelGrowthModifierAsset.ArtificialLight.class, LightLevelGrowthModifierAsset.ArtificialLight::new
) )

View File

@@ -28,6 +28,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class WaterGrowthModifierAsset extends GrowthModifierAsset { public class WaterGrowthModifierAsset extends GrowthModifierAsset {
@Nonnull
public static final BuilderCodec<WaterGrowthModifierAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<WaterGrowthModifierAsset> CODEC = BuilderCodec.builder(
WaterGrowthModifierAsset.class, WaterGrowthModifierAsset::new, ABSTRACT_CODEC WaterGrowthModifierAsset.class, WaterGrowthModifierAsset::new, ABSTRACT_CODEC
) )
@@ -84,19 +85,28 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
@Override @Override
public double getCurrentGrowthMultiplier( 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 isRaining = this.checkIfRaining(commandBuffer, sectionRef, x, y, z);
boolean active = hasWaterBlock || isRaining; boolean active = hasWaterBlock || isRaining;
TilledSoilBlock soil = getSoil(commandBuffer, sectionRef, x, y, z); TilledSoilBlock soil = getSoil(commandBuffer, sectionRef, x, y, z);
if (soil != null) { if (soil != null) {
if (soil.hasExternalWater() != active) { if (soil.hasExternalWater() != active) {
soil.setExternalWater(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 commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()), soil
); );
} }
@@ -105,15 +115,28 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
} }
@Nullable @Nullable
private static TilledSoilBlock getSoil(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) { private static TilledSoilBlock getSoil(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference(); if (chunkSectionComponent == null) {
BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType()); return null;
Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z)); } else {
return blockRefBelow == null ? null : commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType()); 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; IntOpenHashSet waterBlocks = this.fluidIds;
if (waterBlocks == null) { if (waterBlocks == null) {
return false; return false;
@@ -122,31 +145,42 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
if (soil == null) { if (soil == null) {
return false; return false;
} else { } else {
int[] fluids = this.getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z); int[] fluids = getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z);
if (fluids == null) {
for (int block : fluids) { return false;
if (waterBlocks.contains(block)) { } else {
return true; 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) { @Nullable
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); private static int[] getNeighbourFluids(@Nonnull CommandBuffer<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, int x, int y, int z) {
return new int[]{ ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
this.getFluidAtPos(x - 1, y, z, sectionRef, section, commandBuffer), return chunkSectionComponent == null
this.getFluidAtPos(x + 1, y, z, sectionRef, section, commandBuffer), ? null
this.getFluidAtPos(x, y, z - 1, sectionRef, section, commandBuffer), : new int[]{
this.getFluidAtPos(x, y, z + 1, sectionRef, section, commandBuffer) 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( private static int getFluidAtPos(
int posX, int posY, int posZ, Ref<ChunkStore> sectionRef, ChunkSection currentChunkSection, CommandBuffer<ChunkStore> commandBuffer int posX,
int posY,
int posZ,
@Nonnull Ref<ChunkStore> sectionRef,
@Nonnull ChunkSection currentChunkSection,
@Nonnull CommandBuffer<ChunkStore> commandBuffer
) { ) {
Ref<ChunkStore> chunkToUse = sectionRef; Ref<ChunkStore> chunkToUse = sectionRef;
int chunkX = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getX(), posX); int chunkX = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getX(), posX);
@@ -156,49 +190,59 @@ public class WaterGrowthModifierAsset extends GrowthModifierAsset {
chunkToUse = commandBuffer.getExternalData().getChunkSectionReference(chunkX, chunkY, chunkZ); chunkToUse = commandBuffer.getExternalData().getChunkSectionReference(chunkX, chunkY, chunkZ);
} }
return chunkToUse == null ? Integer.MIN_VALUE : commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType()).getFluidId(posX, posY, posZ); if (chunkToUse == null) {
} return Integer.MIN_VALUE;
protected boolean checkIfRaining(CommandBuffer<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, int x, int y, int z) {
if (this.weatherIds == null) {
return false;
} else { } else {
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); FluidSection fluidSectionComponent = commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType());
Ref<ChunkStore> chunk = section.getChunkColumnReference(); return fluidSectionComponent == null ? Integer.MIN_VALUE : fluidSectionComponent.getFluidId(posX, posY, posZ);
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;
} }
} }
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(); Instant until = soilBlock.getWateredUntil();
if (until == null) { if (until == null) {
return false; return false;

View File

@@ -5,17 +5,22 @@ import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref; 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.BlockType;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.FarmingStageData; 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.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class BlockStateFarmingStageData extends FarmingStageData { public class BlockStateFarmingStageData extends FarmingStageData {
@Nonnull @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 BlockStateFarmingStageData.class, BlockStateFarmingStageData::new, FarmingStageData.BASE_CODEC
) )
.append(new KeyedCodec<>("State", Codec.STRING), (stage, block) -> stage.state = block, stage -> stage.state) .append(new KeyedCodec<>("State", Codec.STRING), (stage, block) -> stage.state = block, stage -> stage.state)
@@ -29,25 +34,49 @@ public class BlockStateFarmingStageData extends FarmingStageData {
@Override @Override
public void apply( public void apply(
ComponentAccessor<ChunkStore> commandBuffer, @Nonnull ComponentAccessor<ChunkStore> commandBuffer,
Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> sectionRef,
Ref<ChunkStore> blockRef, @Nonnull Ref<ChunkStore> blockRef,
int x, int x,
int y, int y,
int z, int z,
@Nullable FarmingStageData previousStage @Nullable FarmingStageData previousStage
) { ) {
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage); super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType()); if (chunkSectionComponent == null) {
int origBlockId = worldChunk.getBlock(x, y, z); LOGGER.at(Level.WARNING)
BlockType origBlockType = BlockType.getAssetMap().getAsset(origBlockId); .atMostEvery(1, TimeUnit.MINUTES)
BlockType blockType = origBlockType.getBlockForState(this.state); .log("Missing chunk section component when applying state farming stage at (%d, %d, %d)", x, y, z);
if (blockType != null) { } else {
int newType = BlockType.getAssetMap().getIndex(blockType.getId()); WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
if (origBlockId != newType) { if (worldChunkComponent == null) {
int rotation = worldChunk.getRotationIndex(x, y, z); LOGGER.at(Level.WARNING)
commandBuffer.getExternalData().getWorld().execute(() -> worldChunk.setBlock(x, y, z, newType, blockType, rotation, 0, 2)); .atMostEvery(1, TimeUnit.MINUTES)
.log("Missing world chunk component when applying state farming stage at (%d, %d, %d)", x, y, z);
} else {
int originBlockId = worldChunkComponent.getBlock(x, y, z);
BlockType originBlockType = BlockType.getAssetMap().getAsset(originBlockId);
if (originBlockType == null) {
LOGGER.at(Level.WARNING)
.atMostEvery(1, TimeUnit.MINUTES)
.log("Missing origin block type for block ID '%s' when applying state farming stage at (%d, %d, %d)", String.valueOf(originBlockId), x, y, z);
} else {
BlockType blockType = originBlockType.getBlockForState(this.state);
if (blockType == null) {
LOGGER.at(Level.WARNING)
.atMostEvery(1, TimeUnit.MINUTES)
.log("Missing new block type '%s' when applying state farming stage at (%d, %d, %d)", this.state, x, y, z);
} else {
int newBlockId = BlockType.getAssetMap().getIndex(blockType.getId());
if (originBlockId != newBlockId) {
int rotationIndex = worldChunkComponent.getRotationIndex(x, y, z);
commandBuffer.getExternalData()
.getWorld()
.execute(() -> worldChunkComponent.setBlock(x, y, z, newBlockId, blockType, rotationIndex, 0, 2));
}
}
}
} }
} }
} }

View File

@@ -5,17 +5,22 @@ import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref; 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.BlockType;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.FarmingStageData; 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.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class BlockTypeFarmingStageData extends FarmingStageData { public class BlockTypeFarmingStageData extends FarmingStageData {
@Nonnull @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 BlockTypeFarmingStageData.class, BlockTypeFarmingStageData::new, FarmingStageData.BASE_CODEC
) )
.append(new KeyedCodec<>("Block", Codec.STRING), (stage, block) -> stage.block = block, stage -> stage.block) .append(new KeyedCodec<>("Block", Codec.STRING), (stage, block) -> stage.block = block, stage -> stage.block)
@@ -30,21 +35,42 @@ public class BlockTypeFarmingStageData extends FarmingStageData {
@Override @Override
public void apply( public void apply(
ComponentAccessor<ChunkStore> commandBuffer, @Nonnull ComponentAccessor<ChunkStore> commandBuffer,
Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> sectionRef,
Ref<ChunkStore> blockRef, @Nonnull Ref<ChunkStore> blockRef,
int x, int x,
int y, int y,
int z, int z,
@Nullable FarmingStageData previousStage @Nullable FarmingStageData previousStage
) { ) {
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage); super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
WorldChunk worldChunk = commandBuffer.getComponent(section.getChunkColumnReference(), WorldChunk.getComponentType()); if (chunkSectionComponent == null) {
int blockId = BlockType.getAssetMap().getIndex(this.block); LOGGER.at(Level.WARNING)
if (blockId != worldChunk.getBlock(x, y, z)) { .atMostEvery(1, TimeUnit.MINUTES)
BlockType blockType = BlockType.getAssetMap().getAsset(blockId); .log("Missing chunk section component when applying state farming stage at (%d, %d, %d)", x, y, z);
commandBuffer.getExternalData().getWorld().execute(() -> worldChunk.setBlock(x, y, z, blockId, blockType, worldChunk.getRotationIndex(x, y, z), 0, 2)); } else {
WorldChunk worldChunkComponent = commandBuffer.getComponent(chunkSectionComponent.getChunkColumnReference(), WorldChunk.getComponentType());
if (worldChunkComponent == null) {
LOGGER.at(Level.WARNING)
.atMostEvery(1, TimeUnit.MINUTES)
.log("Missing world chunk component when applying state farming stage at (%d, %d, %d)", x, y, z);
} else {
int blockId = BlockType.getAssetMap().getIndex(this.block);
if (blockId != worldChunkComponent.getBlock(x, y, z)) {
BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
if (blockType == null) {
LOGGER.at(Level.WARNING)
.atMostEvery(1, TimeUnit.MINUTES)
.log("Invalid block type '%s' when applying block type farming stage at (%d, %d, %d)", this.block, x, y, z);
} else {
commandBuffer.getExternalData().getWorld().execute(() -> {
int rotationIndex = worldChunkComponent.getRotationIndex(x, y, z);
worldChunkComponent.setBlock(x, y, z, blockId, blockType, rotationIndex, 0, 2);
});
}
}
}
} }
} }

View File

@@ -1,6 +1,5 @@
package com.hypixel.hytale.builtin.adventure.farming.config.stages; package com.hypixel.hytale.builtin.adventure.farming.config.stages;
import com.hypixel.hytale.assetstore.AssetPack;
import com.hypixel.hytale.assetstore.AssetRegistry; import com.hypixel.hytale.assetstore.AssetRegistry;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap; import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlock; import com.hypixel.hytale.builtin.adventure.farming.states.FarmingBlock;
@@ -13,13 +12,13 @@ import com.hypixel.hytale.common.map.IWeightedElement;
import com.hypixel.hytale.common.map.IWeightedMap; import com.hypixel.hytale.common.map.IWeightedMap;
import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref; 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.ChunkUtil;
import com.hypixel.hytale.math.util.FastRandom; import com.hypixel.hytale.math.util.FastRandom;
import com.hypixel.hytale.math.util.HashUtil; import com.hypixel.hytale.math.util.HashUtil;
import com.hypixel.hytale.math.util.MathUtil; import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.protocol.BlockMaterial; import com.hypixel.hytale.protocol.BlockMaterial;
import com.hypixel.hytale.server.core.asset.AssetModule;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation; import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple; import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
@@ -37,20 +36,24 @@ import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.server.core.util.PrefabUtil; import com.hypixel.hytale.server.core.util.PrefabUtil;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class PrefabFarmingStageData extends FarmingStageData { 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 MIN_VOLUME_PREFAB = 125.0F;
public static final float MAX_VOLUME_PREFAB = 1000.0F; public static final float MAX_VOLUME_PREFAB = 1000.0F;
public static final float MIN_BROKEN_PARTICLE_RATE = 0.25F; public static final float MIN_BROKEN_PARTICLE_RATE = 0.25F;
public static final float MAX_BROKEN_PARTICLE_RATE = 0.75F; public static final float MAX_BROKEN_PARTICLE_RATE = 0.75F;
@Nonnull
private static final String[] EMPTY_REPLACE_MASK = new String[0]; private static final String[] EMPTY_REPLACE_MASK = new String[0];
@Nonnull @Nonnull
public static BuilderCodec<PrefabFarmingStageData> CODEC = BuilderCodec.builder( public static final BuilderCodec<PrefabFarmingStageData> CODEC = BuilderCodec.builder(
PrefabFarmingStageData.class, PrefabFarmingStageData::new, FarmingStageData.BASE_CODEC PrefabFarmingStageData.class, PrefabFarmingStageData::new, FarmingStageData.BASE_CODEC
) )
.append( .append(
@@ -77,12 +80,12 @@ public class PrefabFarmingStageData extends FarmingStageData {
double zLength = prefab.getMaxZ() - prefab.getMinZ(); double zLength = prefab.getMaxZ() - prefab.getMinZ();
double volume = xLength * yLength * zLength; double volume = xLength * yLength * zLength;
double ratio = -5.7142857E-4F; 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); return MathUtil.clamp(rate + 0.75, 0.25, 0.75);
} }
private static boolean isPrefabBlockIntact( private static boolean isPrefabBlockIntact(
LocalCachedChunkAccessor chunkAccessor, @Nonnull LocalCachedChunkAccessor chunkAccessor,
int worldX, int worldX,
int worldY, int worldY,
int worldZ, int worldZ,
@@ -91,33 +94,40 @@ public class PrefabFarmingStageData extends FarmingStageData {
int blockZ, int blockZ,
int blockId, int blockId,
int rotation, int rotation,
PrefabRotation prefabRotation @Nonnull PrefabRotation prefabRotation
) { ) {
int globalX = prefabRotation.getX(blockX, blockZ) + worldX; int globalX = prefabRotation.getX(blockX, blockZ) + worldX;
int globalY = blockY + worldY; int globalY = blockY + worldY;
int globalZ = prefabRotation.getZ(blockX, blockZ) + worldZ; int globalZ = prefabRotation.getZ(blockX, blockZ) + worldZ;
BlockType block = BlockType.getAssetMap().getAsset(blockId); BlockType blockType = BlockType.getAssetMap().getAsset(blockId);
if (block.getMaterial() == BlockMaterial.Empty) { if (blockType != null && blockType.getMaterial() != BlockMaterial.Empty) {
return true; long chunkIndex = ChunkUtil.indexChunkFromBlock(globalX, globalZ);
} else { WorldChunk worldChunkComponent = chunkAccessor.getNonTickingChunk(chunkIndex);
WorldChunk chunk = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(globalX, globalZ)); if (worldChunkComponent == null) {
if (chunk == null) {
return false; return false;
} else { } else {
int worldBlockId = chunk.getBlock(globalX, globalY, globalZ); int worldBlockId = worldChunkComponent.getBlock(globalX, globalY, globalZ);
if (worldBlockId != blockId) { if (worldBlockId != blockId) {
return false; return false;
} else { } else {
int expectedRotation = prefabRotation.getRotation(rotation); int expectedRotation = prefabRotation.getRotation(rotation);
int worldRotation = chunk.getRotationIndex(globalX, globalY, globalZ); int worldRotation = worldChunkComponent.getRotationIndex(globalX, globalY, globalZ);
return worldRotation == expectedRotation; return worldRotation == expectedRotation;
} }
} }
} else {
return true;
} }
} }
private static boolean isPrefabIntact( 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( return prefabBuffer.forEachRaw(
IPrefabBuffer.iterateAllColumns(), IPrefabBuffer.iterateAllColumns(),
@@ -136,144 +146,210 @@ public class PrefabFarmingStageData extends FarmingStageData {
@Override @Override
public void apply( public void apply(
ComponentAccessor<ChunkStore> commandBuffer, @Nonnull ComponentAccessor<ChunkStore> commandBuffer,
Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> sectionRef,
Ref<ChunkStore> blockRef, @Nonnull Ref<ChunkStore> blockRef,
int x, int x,
int y, int y,
int z, int z,
@Nullable FarmingStageData previousStage @Nullable FarmingStageData previousStage
) { ) {
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType()); FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
IPrefabBuffer prefabBuffer = this.getCachedPrefab(x, y, z, farming.getGeneration()); if (farmingBlockComponent == null) {
BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType()); LOGGER.at(Level.WARNING)
int randomRotation = HashUtil.randomInt(x, y, z, Rotation.VALUES.length); .atMostEvery(1, TimeUnit.MINUTES)
RotationTuple yaw = RotationTuple.of(Rotation.VALUES[randomRotation], Rotation.None); .log("Missing farming block component when applying prefab farming stage at (%d, %d, %d)", x, y, z);
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
);
}
}
}
);
} else { } else {
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage); IPrefabBuffer prefabBuffer = this.getCachedPrefab(x, y, z, farmingBlockComponent.getGeneration());
world.execute( BlockSection blockSection = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType());
() -> { int randomRotation = HashUtil.randomInt(x, y, z, Rotation.VALUES.length);
boolean isUnObstructed = prefabBuffer.forEachRaw( RotationTuple yaw = RotationTuple.of(Rotation.VALUES[randomRotation], Rotation.None);
IPrefabBuffer.iterateAllColumns(), (blockX, blockY, blockZ, blockId, chance, holder, supportValue, rotation, filler, t) -> { ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
int bx = worldX + prefabRotation.getX(blockX, blockZ); if (chunkSectionComponent == null) {
int by = worldY + blockY; LOGGER.at(Level.WARNING)
int bz = worldZ + prefabRotation.getX(blockZ, blockX); .atMostEvery(1, TimeUnit.MINUTES)
if (blockId != 0 && blockId != Integer.MIN_VALUE) { .log("Missing chunk section component when applying prefab farming stage at (%d, %d, %d)", x, y, z);
int worldBlock = chunkAccessor.getNonTickingChunk(ChunkUtil.indexChunkFromBlock(bx, bz)).getBlock(bx, by, bz); } else {
return !this.doesBlockObstruct(blockId, worldBlock); int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
} else { int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
return true; int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
} if (farmingBlockComponent.getPreviousBlockType() == null) {
}, (fluidX, fluidY, fluidZ, fluidId, level, o) -> true, null, new PrefabBufferCall(random, prefabRotation) farmingBlockComponent.setPreviousBlockType(BlockType.getAssetMap().getAsset(blockSection.get(x, y, z)).getId());
);
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)
);
}
} }
);
double xLength = prefabBuffer.getMaxX() - prefabBuffer.getMinX();
double zLength = prefabBuffer.getMaxZ() - prefabBuffer.getMinZ();
int prefabRadius = (int)MathUtil.fastFloor(0.5 * Math.sqrt(xLength * xLength + zLength * zLength));
World world = commandBuffer.getExternalData().getWorld();
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, x, z, prefabRadius);
FastRandom random = new FastRandom();
PrefabRotation prefabRotation = PrefabRotation.fromRotation(yaw.yaw());
BlockTypeAssetMap<String, BlockType> blockTypeMap = BlockType.getAssetMap();
if (previousStage instanceof PrefabFarmingStageData oldPrefab) {
IPrefabBuffer oldPrefabBuffer = oldPrefab.getCachedPrefab(worldX, worldY, worldZ, farmingBlockComponent.getGeneration() - 1);
double brokenParticlesRate = computeParticlesRate(prefabBuffer);
world.execute(
() -> {
boolean isIntact = isPrefabIntact(oldPrefabBuffer, chunkAccessor, worldX, worldY, worldZ, prefabRotation, random);
if (isIntact) {
boolean isUnobstructed = prefabBuffer.compare(
(px, py, pz, blockId, stateWrapper, chance, rotation, filler, secondBlockId, secondStateWrapper, secondChance, secondRotation, secondFiller, prefabBufferCall) -> {
int bx = worldX + px;
int by = worldY + py;
int bz = worldZ + pz;
if ((secondBlockId == 0 || secondBlockId == Integer.MIN_VALUE) && blockId != 0 && blockId != Integer.MIN_VALUE) {
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(chunkIndex);
if (nonTickingChunk == null) {
return false;
} else {
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
return !this.doesBlockObstruct(blockId, worldBlock);
}
} else {
return true;
}
},
new PrefabBufferCall(random, prefabRotation),
oldPrefabBuffer
);
if (isUnobstructed) {
prefabBuffer.compare(
(px, py, pz, blockId, stateWrapper, chance, rotation, filler, secondBlockId, secondStateWrapper, secondChance, secondRotation, secondFiller, prefabBufferCall) -> {
int bx = worldX + px;
int by = worldY + py;
int bz = worldZ + pz;
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
WorldChunk nonTickingChunk = chunkAccessor.getNonTickingChunk(chunkIndex);
if (nonTickingChunk == null) {
return true;
} else {
int updatedSetBlockSettings = 2;
if (random.nextDouble() > brokenParticlesRate) {
updatedSetBlockSettings |= 4;
}
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
BlockType block = blockTypeMap.getAsset(blockId);
if (block == null) {
LOGGER.at(Level.WARNING)
.atMostEvery(1, TimeUnit.MINUTES)
.log(
"Invalid block ID %d in prefab at (%d, %d, %d) for farming stage at (%d, %d, %d)",
blockId,
px,
py,
pz,
worldX,
worldY,
worldZ
);
return true;
}
if (filler != 0) {
return true;
}
int worldBlock = nonTickingChunk.getBlock(bx, by, bz);
if ((secondBlockId == 0 || secondBlockId == Integer.MIN_VALUE) && !this.canReplace(worldBlock, blockTypeMap)) {
return true;
}
nonTickingChunk.setBlock(bx, by, bz, blockId, block, rotation, filler, updatedSetBlockSettings);
if (stateWrapper != null) {
nonTickingChunk.setState(bx, by, bz, stateWrapper.clone());
}
} else if (secondBlockId != 0 && secondBlockId != Integer.MIN_VALUE) {
nonTickingChunk.breakBlock(bx, by, bz, updatedSetBlockSettings);
}
return true;
}
},
new PrefabBufferCall(random, prefabRotation),
oldPrefabBuffer
);
}
}
}
);
} else {
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
world.execute(
() -> {
boolean isUnObstructed = prefabBuffer.forEachRaw(
IPrefabBuffer.iterateAllColumns(), (blockX, blockY, blockZ, blockId, chance, holder, supportValue, rotation, filler, t) -> {
int bx = worldX + prefabRotation.getX(blockX, blockZ);
int by = worldY + blockY;
int bz = worldZ + prefabRotation.getX(blockZ, blockX);
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
WorldChunk nonTickingWorldChunkComponent = chunkAccessor.getNonTickingChunk(chunkIndex);
if (nonTickingWorldChunkComponent == null) {
return false;
} else {
int worldBlock = nonTickingWorldChunkComponent.getBlock(bx, by, bz);
return !this.doesBlockObstruct(blockId, worldBlock);
}
} else {
return true;
}
}, (fluidX, fluidY, fluidZ, fluidId, level, o) -> true, null, new PrefabBufferCall(random, prefabRotation)
);
if (isUnObstructed) {
prefabBuffer.forEach(
IPrefabBuffer.iterateAllColumns(),
(blockX, blockY, blockZ, blockId, holder, supportValue, rotation, filler, t, fluidId, fluidLevel) -> {
int bx = worldX + blockX;
int by = worldY + blockY;
int bz = worldZ + blockZ;
long chunkIndex = ChunkUtil.indexChunkFromBlock(bx, bz);
WorldChunk nonTickingWorldChunkComponent = chunkAccessor.getNonTickingChunk(chunkIndex);
if (nonTickingWorldChunkComponent != null) {
if (blockId != 0 && blockId != Integer.MIN_VALUE) {
BlockType blockTypeAsset = blockTypeMap.getAsset(blockId);
if (blockTypeAsset == null) {
LOGGER.at(Level.WARNING)
.atMostEvery(1, TimeUnit.MINUTES)
.log(
"Invalid block ID %d in prefab at (%d, %d, %d) for farming stage at (%d, %d, %d)",
blockId,
blockX,
blockY,
blockZ,
worldX,
worldY,
worldZ
);
return;
}
if (filler != 0) {
return;
}
int worldBlock = nonTickingWorldChunkComponent.getBlock(bx, by, bz);
if (!this.canReplace(worldBlock, blockTypeMap)) {
return;
}
nonTickingWorldChunkComponent.setBlock(bx, by, bz, blockId, blockTypeAsset, rotation, filler, 2);
if (holder != null) {
nonTickingWorldChunkComponent.setState(bx, by, bz, holder.clone());
}
}
}
},
null,
null,
new PrefabBufferCall(random, prefabRotation)
);
}
}
);
}
}
} }
} }
@@ -283,7 +359,7 @@ public class PrefabFarmingStageData extends FarmingStageData {
return blockType != null && blockType.getMaterial() != BlockMaterial.Empty ? !this.canReplace(worldBlockId, assetMap) : false; 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); BlockType worldBlockType = assetMap.getAsset(worldBlockId);
if (worldBlockType != null && worldBlockType.getMaterial() != BlockMaterial.Empty) { if (worldBlockType != null && worldBlockType.getMaterial() != BlockMaterial.Empty) {
for (int tagIndex : this.replaceMaskTagIndices) { for (int tagIndex : this.replaceMaskTagIndices) {
@@ -299,18 +375,39 @@ public class PrefabFarmingStageData extends FarmingStageData {
} }
@Override @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); super.remove(commandBuffer, sectionRef, blockRef, x, y, z);
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x); if (chunkSectionComponent == null) {
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y); LOGGER.at(Level.WARNING)
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z); .atMostEvery(1, TimeUnit.MINUTES)
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType()); .log("Missing chunk section component when removing prefab farming stage at (%d, %d, %d)", x, y, z);
IPrefabBuffer prefab = this.getCachedPrefab(worldX, worldY, worldZ, farming.getGeneration() - 1); } else {
RotationTuple rotation = commandBuffer.getComponent(sectionRef, BlockSection.getComponentType()).getRotation(x, y, z); int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
double rate = computeParticlesRate(prefab); int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
World world = commandBuffer.getExternalData().getWorld(); int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
world.execute(() -> PrefabUtil.remove(prefab, world, new Vector3i(worldX, worldY, worldZ), rotation.yaw(), true, new FastRandom(), 2, rate)); 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 @Nonnull
@@ -326,15 +423,17 @@ public class PrefabFarmingStageData extends FarmingStageData {
} }
} }
@Nonnull
@Override @Override
public String toString() { public String toString() {
return "PrefabFarmingStageData{replaceMaskTags=" + Arrays.toString((Object[])this.replaceMaskTags) + ", prefabStages=" + this.prefabStages + "}"; return "PrefabFarmingStageData{replaceMaskTags=" + Arrays.toString((Object[])this.replaceMaskTags) + ", prefabStages=" + this.prefabStages + "}";
} }
public static class PrefabStage implements IWeightedElement { public static class PrefabStage implements IWeightedElement {
@Nonnull
public static final PrefabFarmingStageData.PrefabStage[] EMPTY_ARRAY = new PrefabFarmingStageData.PrefabStage[0]; public static final PrefabFarmingStageData.PrefabStage[] EMPTY_ARRAY = new PrefabFarmingStageData.PrefabStage[0];
@Nonnull @Nonnull
public static Codec<PrefabFarmingStageData.PrefabStage> CODEC = BuilderCodec.builder( public static final Codec<PrefabFarmingStageData.PrefabStage> CODEC = BuilderCodec.builder(
PrefabFarmingStageData.PrefabStage.class, PrefabFarmingStageData.PrefabStage::new PrefabFarmingStageData.PrefabStage.class, PrefabFarmingStageData.PrefabStage::new
) )
.append(new KeyedCodec<>("Weight", Codec.INTEGER), (prefabStage, integer) -> prefabStage.weight = integer, prefabStage -> prefabStage.weight) .append(new KeyedCodec<>("Weight", Codec.INTEGER), (prefabStage, integer) -> prefabStage.weight = integer, prefabStage -> prefabStage.weight)
@@ -354,14 +453,12 @@ public class PrefabFarmingStageData extends FarmingStageData {
@Nonnull @Nonnull
public Path getResolvedPath() { public Path getResolvedPath() {
for (AssetPack pack : AssetModule.get().getAssetPacks()) { Path assetPath = PrefabStore.get().findAssetPrefabPath(this.path);
Path assetPath = pack.getRoot().resolve("Server").resolve("Prefabs").resolve(this.path); if (assetPath == null) {
if (Files.exists(assetPath)) { throw new IllegalStateException("Invalid prefab path: " + this.path);
return assetPath; } else {
} return assetPath;
} }
return PrefabStore.get().getAssetPrefabsPath().resolve(this.path);
} }
@Nonnull @Nonnull

View File

@@ -32,6 +32,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour { public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
@Nonnull
public static final BuilderCodec<DirectionalGrowthBehaviour> CODEC = BuilderCodec.builder( public static final BuilderCodec<DirectionalGrowthBehaviour> CODEC = BuilderCodec.builder(
DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour::new, BASE_CODEC DirectionalGrowthBehaviour.class, DirectionalGrowthBehaviour::new, BASE_CODEC
) )
@@ -92,9 +93,9 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
@Override @Override
public void execute( public void execute(
ComponentAccessor<ChunkStore> commandBuffer, @Nonnull ComponentAccessor<ChunkStore> componentAccessor,
Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> sectionRef,
Ref<ChunkStore> blockRef, @Nonnull Ref<ChunkStore> blockRef,
int worldX, int worldX,
int worldY, int worldY,
int worldZ, int worldZ,
@@ -103,54 +104,68 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
int x = 0; int x = 0;
int z = 0; int z = 0;
FastRandom random = new FastRandom(); FastRandom random = new FastRandom();
String blockTypeKey = this.blockTypes.get(random).getBlockTypeKey(); DirectionalGrowthBehaviour.BlockTypeWeight blockTypeWeight = this.blockTypes.get(random);
World world = commandBuffer.getExternalData().getWorld(); if (blockTypeWeight != null) {
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, worldX, worldZ, 1); String blockTypeKey = blockTypeWeight.getBlockTypeKey();
World world = componentAccessor.getExternalData().getWorld();
LocalCachedChunkAccessor chunkAccessor = LocalCachedChunkAccessor.atWorldCoords(world, worldX, worldZ, 1);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
if (this.horizontalRange != null) { if (this.horizontalRange != null) {
double angle = (float) (Math.PI * 2) * random.nextFloat(); double angle = (float) (Math.PI * 2) * random.nextFloat();
int radius = this.horizontalRange.getInt(random.nextFloat()); int radius = this.horizontalRange.getInt(random.nextFloat());
x = MathUtil.fastRound(radius * TrigMathUtil.cos(angle)); x = MathUtil.fastRound(radius * TrigMathUtil.cos(angle));
z = MathUtil.fastRound(radius * TrigMathUtil.sin(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;
} }
if (this.tryPlaceBlock(world, chunk, targetX, targetY, targetZ, blockTypeKey, 0)) { int targetX = worldX + x;
int finalTargetY = targetY; int targetZ = worldZ + z;
world.execute(() -> { int chunkX = ChunkUtil.chunkCoordinate(targetX);
WorldChunk loadedChunk = chunkAccessor.getChunk(ChunkUtil.indexChunk(chunkX, chunkZ)); int chunkZ = ChunkUtil.chunkCoordinate(targetZ);
if (loadedChunk != null) { long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
loadedChunk.placeBlock(targetX, finalTargetY, targetZ, blockTypeKey, Rotation.None, Rotation.None, Rotation.None); WorldChunk worldChunkComponent = chunkAccessor.getChunkIfInMemory(chunkIndex);
decaySpread(commandBuffer, loadedChunk.getBlockComponentChunk(), targetX, finalTargetY, targetZ, newSpreadRate); if (worldChunkComponent != null) {
} int targetY;
}); if (this.verticalRange != null) {
return; 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( 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) { if (blockRefPlaced != null) {
FarmingBlock farmingPlaced = commandBuffer.getComponent(blockRefPlaced, FarmingBlock.getComponentType()); FarmingBlock farmingPlaced = commandBuffer.getComponent(blockRefPlaced, FarmingBlock.getComponentType());
if (farmingPlaced != null) { 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) { if (chunk.getBlock(worldX, worldY, worldZ) != 0) {
return false; return false;
} else if (!this.validatePosition(world, worldX, worldY, worldZ)) { } else if (!this.validatePosition(world, worldX, worldY, worldZ)) {
return false; return false;
} else { } else {
BlockType blockType = BlockType.getAssetMap().getAsset(blockTypeKey); BlockType blockTypeAsset = BlockType.getAssetMap().getAsset(blockTypeKey);
if (blockType == null) { if (blockTypeAsset == null) {
return false; return false;
} else if (!chunk.testPlaceBlock(worldX, worldY, worldZ, blockType, rotation)) { } else if (!chunk.testPlaceBlock(worldX, worldY, worldZ, blockTypeAsset, rotation)) {
return false; return false;
} else { } else {
int cx = chunk.getX(); int chunkX = chunk.getX();
int cz = chunk.getZ(); int chunkY = ChunkUtil.indexSection(worldY);
int cy = ChunkUtil.indexSection(worldY); int chunkZ = chunk.getZ();
Ref<ChunkStore> sectionRef = world.getChunkStore().getChunkSectionReference(cx, cy, cz); ChunkStore chunkStore = world.getChunkStore();
if (sectionRef == null) { Ref<ChunkStore> sectionRef = chunkStore.getChunkSectionReference(chunkX, chunkY, chunkZ);
return false; if (sectionRef != null && sectionRef.isValid()) {
} else { Store<ChunkStore> store = chunkStore.getStore();
Store<ChunkStore> store = world.getChunkStore().getStore(); BlockPhysics blockPhysicsComponent = store.getComponent(sectionRef, BlockPhysics.getComponentType());
BlockPhysics blockPhysics = store.getComponent(sectionRef, BlockPhysics.getComponentType());
FluidSection fluidSection = store.getComponent(sectionRef, FluidSection.getComponentType()); assert blockPhysicsComponent != null;
BlockSection blockSection = store.getComponent(sectionRef, BlockSection.getComponentType());
int filler = blockSection.getFiller(worldX, worldY, worldZ); 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( 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( return BlockPhysicsUtil.testBlockPhysics(
cachedAccessor, blockSection, blockPhysics, fluidSection, worldX, worldY, worldZ, blockType, rotation, filler cachedAccessor,
blockSectionComponent,
blockPhysicsComponent,
fluidSectionComponent,
worldX,
worldY,
worldZ,
blockTypeAsset,
rotation,
filler
) )
!= 0; != 0;
} else {
return false;
} }
} }
} }
@@ -212,7 +248,7 @@ public class DirectionalGrowthBehaviour extends SpreadGrowthBehaviour {
public static class BlockTypeWeight implements IWeightedElement { public static class BlockTypeWeight implements IWeightedElement {
@Nonnull @Nonnull
public static BuilderCodec<DirectionalGrowthBehaviour.BlockTypeWeight> CODEC = BuilderCodec.builder( public static final BuilderCodec<DirectionalGrowthBehaviour.BlockTypeWeight> CODEC = BuilderCodec.builder(
DirectionalGrowthBehaviour.BlockTypeWeight.class, DirectionalGrowthBehaviour.BlockTypeWeight::new DirectionalGrowthBehaviour.BlockTypeWeight.class, DirectionalGrowthBehaviour.BlockTypeWeight::new
) )
.append( .append(

View File

@@ -19,7 +19,7 @@ import javax.annotation.Nullable;
public class SpreadFarmingStageData extends FarmingStageData { public class SpreadFarmingStageData extends FarmingStageData {
@Nonnull @Nonnull
public static BuilderCodec<SpreadFarmingStageData> CODEC = BuilderCodec.builder( public static final BuilderCodec<SpreadFarmingStageData> CODEC = BuilderCodec.builder(
SpreadFarmingStageData.class, SpreadFarmingStageData::new, FarmingStageData.BASE_CODEC SpreadFarmingStageData.class, SpreadFarmingStageData::new, FarmingStageData.BASE_CODEC
) )
.append( .append(
@@ -84,50 +84,67 @@ public class SpreadFarmingStageData extends FarmingStageData {
} }
@Override @Override
public boolean shouldStop(ComponentAccessor<ChunkStore> commandBuffer, Ref<ChunkStore> sectionRef, Ref<ChunkStore> blockRef, int x, int y, int z) { public boolean shouldStop(
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType()); @Nonnull ComponentAccessor<ChunkStore> commandBuffer, @Nonnull Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> blockRef, int x, int y, int z
float spreadRate = farming.getSpreadRate(); ) {
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x); if (farmingBlockComponent == null) {
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y); return true;
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z); } else {
float executions = this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farming.getGeneration())) * spreadRate; ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
int executed = farming.getExecutions(); if (chunkSectionComponent == null) {
return spreadRate <= 0.0F || executed >= executions; 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 @Override
public void apply( public void apply(
ComponentAccessor<ChunkStore> commandBuffer, @Nonnull ComponentAccessor<ChunkStore> commandBuffer,
Ref<ChunkStore> sectionRef, @Nonnull Ref<ChunkStore> sectionRef,
Ref<ChunkStore> blockRef, @Nonnull Ref<ChunkStore> blockRef,
int x, int x,
int y, int y,
int z, int z,
@Nullable FarmingStageData previousStage @Nullable FarmingStageData previousStage
) { ) {
super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage); super.apply(commandBuffer, sectionRef, blockRef, x, y, z, previousStage);
FarmingBlock farming = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType()); FarmingBlock farmingBlockComponent = commandBuffer.getComponent(blockRef, FarmingBlock.getComponentType());
ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType()); if (farmingBlockComponent != null) {
int worldX = ChunkUtil.worldCoordFromLocalCoord(section.getX(), x); ChunkSection chunkSectionComponent = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
int worldY = ChunkUtil.worldCoordFromLocalCoord(section.getY(), y); if (chunkSectionComponent != null) {
int worldZ = ChunkUtil.worldCoordFromLocalCoord(section.getZ(), z); int worldX = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getX(), x);
float spreadRate = farming.getSpreadRate(); int worldY = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getY(), y);
double executions = Math.floor(this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, farming.getGeneration())) * spreadRate); int worldZ = ChunkUtil.worldCoordFromLocalCoord(chunkSectionComponent.getZ(), z);
int executed = farming.getExecutions(); float spreadRate = farmingBlockComponent.getSpreadRate();
if (!(spreadRate <= 0.0F) && !(executed >= executions)) { int generation = farmingBlockComponent.getGeneration();
for (int i = 0; i < this.spreadGrowthBehaviours.length; i++) { double executions = Math.floor(this.executions.getInt(HashUtil.random(worldX, worldY, worldZ, generation)) * spreadRate);
SpreadGrowthBehaviour spreadGrowthBehaviour = this.spreadGrowthBehaviours[i]; int executed = farmingBlockComponent.getExecutions();
float decayRate = this.spreadDecayPercent.getInt(HashUtil.random(i | (long)farming.getGeneration() << 32, worldX, worldY, worldZ)) / 100.0F; if (!(spreadRate <= 0.0F) && !(executed >= executions)) {
spreadGrowthBehaviour.execute(commandBuffer, sectionRef, blockRef, worldX, worldY, worldZ, spreadRate - decayRate); 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 @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); super.remove(commandBuffer, sectionRef, blockRef, x, y, z);
} }

View File

@@ -9,9 +9,12 @@ import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.server.core.universe.world.worldlocationcondition.WorldLocationCondition; import com.hypixel.hytale.server.core.universe.world.worldlocationcondition.WorldLocationCondition;
import javax.annotation.Nonnull;
public abstract class SpreadGrowthBehaviour { public abstract class SpreadGrowthBehaviour {
@Nonnull
public static final CodecMapCodec<SpreadGrowthBehaviour> CODEC = new CodecMapCodec<>("Type"); public static final CodecMapCodec<SpreadGrowthBehaviour> CODEC = new CodecMapCodec<>("Type");
@Nonnull
public static final BuilderCodec<SpreadGrowthBehaviour> BASE_CODEC = BuilderCodec.abstractBuilder(SpreadGrowthBehaviour.class) public static final BuilderCodec<SpreadGrowthBehaviour> BASE_CODEC = BuilderCodec.abstractBuilder(SpreadGrowthBehaviour.class)
.append( .append(
new KeyedCodec<>("LocationConditions", new ArrayCodec<>(WorldLocationCondition.CODEC, WorldLocationCondition[]::new)), new KeyedCodec<>("LocationConditions", new ArrayCodec<>(WorldLocationCondition.CODEC, WorldLocationCondition[]::new)),
@@ -23,9 +26,11 @@ public abstract class SpreadGrowthBehaviour {
.build(); .build();
protected WorldLocationCondition[] worldLocationConditions; 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) { if (this.worldLocationConditions == null) {
return true; return true;
} else { } else {

View File

@@ -35,7 +35,9 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class ChangeFarmingStageInteraction extends SimpleBlockInteraction { public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
@Nonnull
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
@Nonnull
public static final BuilderCodec<ChangeFarmingStageInteraction> CODEC = BuilderCodec.builder( public static final BuilderCodec<ChangeFarmingStageInteraction> CODEC = BuilderCodec.builder(
ChangeFarmingStageInteraction.class, ChangeFarmingStageInteraction::new, SimpleBlockInteraction.CODEC ChangeFarmingStageInteraction.class, ChangeFarmingStageInteraction::new, SimpleBlockInteraction.CODEC
) )
@@ -75,11 +77,11 @@ public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
.build(); .build();
protected int targetStage = -1; protected int targetStage = -1;
@Nullable @Nullable
protected Integer increaseBy = null; protected Integer increaseBy;
@Nullable @Nullable
protected Integer decreaseBy = null; protected Integer decreaseBy;
@Nullable @Nullable
protected String targetStageSet = null; protected String targetStageSet;
@Nonnull @Nonnull
@Override @Override
@@ -270,16 +272,16 @@ public class ChangeFarmingStageInteraction extends SimpleBlockInteraction {
); );
Ref<ChunkStore> sectionRef = world.getChunkStore() Ref<ChunkStore> sectionRef = world.getChunkStore()
.getChunkSectionReference(ChunkUtil.chunkCoordinate(x), ChunkUtil.chunkCoordinate(y), ChunkUtil.chunkCoordinate(z)); .getChunkSectionReference(ChunkUtil.chunkCoordinate(x), ChunkUtil.chunkCoordinate(y), ChunkUtil.chunkCoordinate(z));
if (sectionRef != null) { if (sectionRef != null && sectionRef.isValid()) {
BlockSection section = chunkStore.getComponent(sectionRef, BlockSection.getComponentType()); BlockSection blockSectionComponent = chunkStore.getComponent(sectionRef, BlockSection.getComponentType());
if (section != null) { if (blockSectionComponent != null) {
section.scheduleTick(ChunkUtil.indexBlock(x, y, z), now); blockSectionComponent.scheduleTick(ChunkUtil.indexBlock(x, y, z), now);
} }
stages[stageIndex].apply(chunkStore, sectionRef, blockRef, x, y, z, previousStage); stages[stageIndex].apply(chunkStore, sectionRef, blockRef, x, y, z, previousStage);
LOGGER.atInfo().log("[ChangeFarmingStage] Applied stage %d via stages[%d].apply()", stageIndex, stageIndex); LOGGER.atInfo().log("[ChangeFarmingStage] Applied stage %d via stages[%d].apply()", stageIndex, stageIndex);
} else { } 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); worldChunk.setTicking(x, y, z, true);

View File

@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class FertilizeSoilInteraction extends SimpleBlockInteraction { public class FertilizeSoilInteraction extends SimpleBlockInteraction {
@Nonnull
public static final BuilderCodec<FertilizeSoilInteraction> CODEC = BuilderCodec.builder( public static final BuilderCodec<FertilizeSoilInteraction> CODEC = BuilderCodec.builder(
FertilizeSoilInteraction.class, FertilizeSoilInteraction::new, SimpleBlockInteraction.CODEC FertilizeSoilInteraction.class, FertilizeSoilInteraction::new, SimpleBlockInteraction.CODEC
) )
@@ -56,40 +57,45 @@ public class FertilizeSoilInteraction extends SimpleBlockInteraction {
) { ) {
int x = targetBlock.getX(); int x = targetBlock.getX();
int z = targetBlock.getZ(); int z = targetBlock.getZ();
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z)); long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z); WorldChunk worldChunkComponent = world.getChunk(chunkIndex);
if (blockRef == null) { if (worldChunkComponent == null) {
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
}
if (blockRef == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
Store<ChunkStore> chunkStore = world.getChunkStore().getStore(); Ref<ChunkStore> blockRef = worldChunkComponent.getBlockComponentEntity(x, targetBlock.getY(), z);
TilledSoilBlock soil = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType()); if (blockRef == null || !blockRef.isValid()) {
if (soil != null && !soil.isFertilized()) { blockRef = BlockModule.ensureBlockEntity(worldChunkComponent, targetBlock.x, targetBlock.y, targetBlock.z);
soil.setFertilized(true); }
worldChunk.setTicking(x, targetBlock.getY(), z, true);
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true); if (blockRef != null && blockRef.isValid()) {
} else { Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
FarmingBlock farmingState = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType()); TilledSoilBlock tilledSoilComponent = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
if (farmingState == null) { if (tilledSoilComponent != null && !tilledSoilComponent.isFertilized()) {
context.getState().state = InteractionState.Failed; tilledSoilComponent.setFertilized(true);
worldChunkComponent.setTicking(x, targetBlock.getY(), z, true);
worldChunkComponent.setTicking(x, targetBlock.getY() + 1, z, true);
} else { } else {
Ref<ChunkStore> soilRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z); FarmingBlock farmingBlockComponent = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
if (soilRef == null) { if (farmingBlockComponent == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
soil = chunkStore.getComponent(soilRef, TilledSoilBlock.getComponentType()); Ref<ChunkStore> soilBlockRef = worldChunkComponent.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
if (soil != null && !soil.isFertilized()) { if (soilBlockRef != null && soilBlockRef.isValid()) {
soil.setFertilized(true); tilledSoilComponent = chunkStore.getComponent(soilBlockRef, TilledSoilBlock.getComponentType());
worldChunk.setTicking(x, targetBlock.getY() - 1, z, true); if (tilledSoilComponent != null && !tilledSoilComponent.isFertilized()) {
worldChunk.setTicking(x, targetBlock.getY(), z, true); 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 { } else {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} }
} }
} }
} else {
context.getState().state = InteractionState.Failed;
} }
} }
} }

View File

@@ -1,11 +1,14 @@
package com.hypixel.hytale.builtin.adventure.farming.interactions; package com.hypixel.hytale.builtin.adventure.farming.interactions;
import com.hypixel.hytale.builtin.adventure.farming.FarmingUtil; import com.hypixel.hytale.builtin.adventure.farming.FarmingUtil;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.protocol.InteractionState;
import com.hypixel.hytale.protocol.InteractionType; import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.entity.InteractionContext; import com.hypixel.hytale.server.core.entity.InteractionContext;
@@ -22,11 +25,21 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class HarvestCropInteraction extends SimpleBlockInteraction { public class HarvestCropInteraction extends SimpleBlockInteraction {
@Nonnull
public static final BuilderCodec<HarvestCropInteraction> CODEC = BuilderCodec.builder( public static final BuilderCodec<HarvestCropInteraction> CODEC = BuilderCodec.builder(
HarvestCropInteraction.class, HarvestCropInteraction::new, SimpleBlockInteraction.CODEC HarvestCropInteraction.class, HarvestCropInteraction::new, SimpleBlockInteraction.CODEC
) )
.documentation("Harvests the resources from the target farmable block.") .documentation("Harvests the resources from the target farmable block.")
.<Boolean>appendInherited(
new KeyedCodec<>("RequireNotBroken", Codec.BOOLEAN),
(interaction, s) -> interaction.requireNotBroken = s,
interaction -> interaction.requireNotBroken,
(interaction, parent) -> interaction.requireNotBroken = parent.requireNotBroken
)
.documentation("If true, the interaction will fail if the held item is broken (durability = 0).")
.add()
.build(); .build();
protected boolean requireNotBroken = false;
@Override @Override
protected void interactWithBlock( protected void interactWithBlock(
@@ -38,25 +51,31 @@ public class HarvestCropInteraction extends SimpleBlockInteraction {
@Nonnull Vector3i targetBlock, @Nonnull Vector3i targetBlock,
@Nonnull CooldownHandler cooldownHandler @Nonnull CooldownHandler cooldownHandler
) { ) {
Ref<EntityStore> ref = context.getEntity(); if (this.requireNotBroken && itemInHand != null && itemInHand.isBroken()) {
ChunkStore chunkStore = world.getChunkStore(); context.getState().state = InteractionState.Failed;
long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z); } else {
Ref<ChunkStore> chunkRef = chunkStore.getChunkReference(chunkIndex); Ref<EntityStore> ref = context.getEntity();
if (chunkRef != null && chunkRef.isValid()) { ChunkStore chunkStore = world.getChunkStore();
BlockChunk blockChunkComponent = chunkStore.getStore().getComponent(chunkRef, BlockChunk.getComponentType()); long chunkIndex = ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z);
Ref<ChunkStore> chunkRef = chunkStore.getChunkReference(chunkIndex);
if (chunkRef != null && chunkRef.isValid()) {
BlockChunk blockChunkComponent = chunkStore.getStore().getComponent(chunkRef, BlockChunk.getComponentType());
assert blockChunkComponent != null; assert blockChunkComponent != null;
BlockSection section = blockChunkComponent.getSectionAtBlockY(targetBlock.y); BlockSection blockSection = blockChunkComponent.getSectionAtBlockY(targetBlock.y);
if (section != null) { if (blockSection != null) {
WorldChunk worldChunkComponent = chunkStore.getStore().getComponent(chunkRef, WorldChunk.getComponentType()); WorldChunk worldChunkComponent = chunkStore.getStore().getComponent(chunkRef, WorldChunk.getComponentType());
assert worldChunkComponent != null; assert worldChunkComponent != null;
BlockType blockType = worldChunkComponent.getBlockType(targetBlock); BlockType blockType = worldChunkComponent.getBlockType(targetBlock);
if (blockType != null) { 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); if (!FarmingUtil.harvest(world, commandBuffer, ref, blockType, rotationIndex, targetBlock)) {
context.getState().state = InteractionState.Failed;
}
}
} }
} }
} }

View File

@@ -26,6 +26,7 @@ import com.hypixel.hytale.server.core.inventory.Inventory;
import com.hypixel.hytale.server.core.inventory.ItemStack; import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.modules.block.BlockModule; 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.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.CooldownHandler;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInteraction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInteraction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction;
@@ -41,6 +42,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class UseCaptureCrateInteraction extends SimpleBlockInteraction { public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
@Nonnull
public static final BuilderCodec<UseCaptureCrateInteraction> CODEC = BuilderCodec.builder( public static final BuilderCodec<UseCaptureCrateInteraction> CODEC = BuilderCodec.builder(
UseCaptureCrateInteraction.class, UseCaptureCrateInteraction::new, SimpleInteraction.CODEC 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 boolean firstRun, float time, @Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler
) { ) {
CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer(); CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer();
if (commandBuffer == null) {
assert commandBuffer != null;
ItemStack item = context.getHeldItem();
if (item == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
ItemStack item = context.getHeldItem(); Ref<EntityStore> ref = context.getEntity();
if (item == null) { if (!(EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity)) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
Ref<EntityStore> ref = context.getEntity(); Inventory inventory = livingEntity.getInventory();
if (!(EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity)) { byte activeHotbarSlot = inventory.getActiveHotbarSlot();
ItemStack inHandItemStack = inventory.getActiveHotbarItem();
if (inHandItemStack == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
Inventory inventory = livingEntity.getInventory();
byte activeHotbarSlot = inventory.getActiveHotbarSlot();
ItemStack inHandItemStack = inventory.getActiveHotbarItem();
CapturedNPCMetadata existingMeta = item.getFromMetadataOrNull("CapturedEntity", CapturedNPCMetadata.CODEC); CapturedNPCMetadata existingMeta = item.getFromMetadataOrNull("CapturedEntity", CapturedNPCMetadata.CODEC);
if (existingMeta != null) { if (existingMeta != null) {
super.tick0(firstRun, time, type, context, cooldownHandler); super.tick0(firstRun, time, type, context, cooldownHandler);
@@ -95,47 +103,56 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
Ref<EntityStore> targetEntity = context.getTargetEntity(); Ref<EntityStore> targetEntity = context.getTargetEntity();
if (targetEntity == null) { if (targetEntity == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
NPCEntity npcComponent = commandBuffer.getComponent(targetEntity, NPCEntity.getComponentType()); NPCEntity npcComponent = commandBuffer.getComponent(targetEntity, NPCEntity.getComponentType());
if (npcComponent == null) { if (npcComponent == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class); DeathComponent deathComponent = commandBuffer.getComponent(targetEntity, DeathComponent.getComponentType());
boolean tagFound = false; if (deathComponent != null) {
for (int group : this.acceptedNpcGroupIndexes) {
if (tagSetPlugin.tagInSet(group, npcComponent.getRoleIndex())) {
tagFound = true;
break;
}
}
if (!tagFound) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
PersistentModel persistentModel = commandBuffer.getComponent(targetEntity, PersistentModel.getComponentType()); TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
if (persistentModel == null) { boolean tagFound = false;
for (int group : this.acceptedNpcGroupIndexes) {
if (tagSetPlugin.tagInSet(group, npcComponent.getRoleIndex())) {
tagFound = true;
break;
}
}
if (!tagFound) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
super.tick0(firstRun, time, type, context, cooldownHandler);
} else { } else {
ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(persistentModel.getModelReference().getModelAssetId()); PersistentModel persistentModelComponent = commandBuffer.getComponent(targetEntity, PersistentModel.getComponentType());
CapturedNPCMetadata meta = inHandItemStack.getFromMetadataOrDefault("CapturedEntity", CapturedNPCMetadata.CODEC); if (persistentModelComponent == null) {
if (modelAsset != null) { context.getState().state = InteractionState.Failed;
meta.setIconPath(modelAsset.getIcon()); 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());
String npcName = NPCPlugin.get().getName(npcComponent.getRoleIndex()); if (npcName != null) {
if (npcName != null) { itemMetaData.setNpcNameKey(npcName);
meta.setNpcNameKey(npcName); }
}
if (this.fullIcon != null) { if (this.fullIcon != null) {
meta.setFullItemIcon(this.fullIcon); itemMetaData.setFullItemIcon(this.fullIcon);
} }
ItemStack itemWithNPC = inHandItemStack.withMetadata(CapturedNPCMetadata.KEYED_CODEC, meta); ItemStack itemWithNPC = inHandItemStack.withMetadata(CapturedNPCMetadata.KEYED_CODEC, itemMetaData);
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, itemWithNPC); inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, itemWithNPC);
commandBuffer.removeEntity(targetEntity, RemoveReason.REMOVE); commandBuffer.removeEntity(targetEntity, RemoveReason.REMOVE);
}
} }
} }
} }
@@ -172,46 +189,51 @@ public class UseCaptureCrateInteraction extends SimpleBlockInteraction {
if (pos == null) { if (pos == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(pos.x, pos.z)); long chunkIndex = ChunkUtil.indexChunkFromBlock(pos.x, pos.z);
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(pos.x, pos.y, pos.z); WorldChunk worldChunk = world.getChunk(chunkIndex);
if (blockRef == null) { if (worldChunk == null) {
blockRef = BlockModule.ensureBlockEntity(worldChunk, pos.x, pos.y, pos.z); 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); ItemStack noMetaItemStack = item.withMetadata(null);
if (blockRef != null) { if (blockRef != null && blockRef.isValid()) {
Store<ChunkStore> chunkStore = world.getChunkStore().getStore(); Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
CoopBlock coopBlockState = chunkStore.getComponent(blockRef, CoopBlock.getComponentType()); CoopBlock coopBlockComponent = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
if (coopBlockState != null) { if (coopBlockComponent != null) {
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType()); WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
if (coopBlockState.tryPutResident(existingMeta, worldTimeResource)) { if (coopBlockComponent.tryPutResident(existingMeta, worldTimeResource)) {
world.execute( world.execute(
() -> coopBlockState.ensureSpawnResidentsInWorld( () -> coopBlockComponent.ensureSpawnResidentsInWorld(
world, world.getEntityStore().getStore(), new Vector3d(pos.x, pos.y, pos.z), new Vector3d().assign(Vector3d.FORWARD) world, world.getEntityStore().getStore(), new Vector3d(pos.x, pos.y, pos.z), new Vector3d().assign(Vector3d.FORWARD)
) )
); );
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack); inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
} else { context.getState().state = InteractionState.Finished;
context.getState().state = InteractionState.Failed; } else {
context.getState().state = InteractionState.Failed;
}
return;
} }
return;
} }
}
Vector3d spawnPos = new Vector3d(pos.x + 0.5F, pos.y, pos.z + 0.5F); Vector3d spawnPos = new Vector3d(pos.x + 0.5F, pos.y, pos.z + 0.5F);
if (context.getClientState() != null) { if (context.getClientState() != null) {
BlockFace blockFace = BlockFace.fromProtocolFace(context.getClientState().blockFace); BlockFace blockFace = BlockFace.fromProtocolFace(context.getClientState().blockFace);
if (blockFace != null) { if (blockFace != null) {
spawnPos.add(blockFace.getDirection()); spawnPos.add(blockFace.getDirection());
}
} }
}
NPCPlugin npcModule = NPCPlugin.get(); String roleId = existingMeta.getNpcNameKey();
Store<EntityStore> store = context.getCommandBuffer().getStore(); int roleIndex = NPCPlugin.get().getIndex(roleId);
int roleIndex = existingMeta.getRoleIndex(); commandBuffer.run(_store -> NPCPlugin.get().spawnEntity(_store, roleIndex, spawnPos, Vector3f.ZERO, null, null));
commandBuffer.run(_store -> npcModule.spawnEntity(store, roleIndex, spawnPos, Vector3f.ZERO, null, null)); inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack);
inventory.getHotbar().replaceItemStackInSlot(activeHotbarSlot, item, noMetaItemStack); }
} }
} }
} else { } else {

View File

@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class UseCoopInteraction extends SimpleBlockInteraction { public class UseCoopInteraction extends SimpleBlockInteraction {
@Nonnull
public static final BuilderCodec<UseCoopInteraction> CODEC = BuilderCodec.builder( public static final BuilderCodec<UseCoopInteraction> CODEC = BuilderCodec.builder(
UseCoopInteraction.class, UseCoopInteraction::new, SimpleBlockInteraction.CODEC UseCoopInteraction.class, UseCoopInteraction::new, SimpleBlockInteraction.CODEC
) )
@@ -43,39 +44,39 @@ public class UseCoopInteraction extends SimpleBlockInteraction {
) { ) {
int x = targetBlock.getX(); int x = targetBlock.getX();
int z = targetBlock.getZ(); 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) { if (worldChunk == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z); 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); blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
} }
if (blockRef == null) { if (blockRef != null && blockRef.isValid()) {
context.getState().state = InteractionState.Failed;
} else {
Store<ChunkStore> chunkStore = world.getChunkStore().getStore(); Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
CoopBlock coopBlockState = chunkStore.getComponent(blockRef, CoopBlock.getComponentType()); CoopBlock coopBlockComponent = chunkStore.getComponent(blockRef, CoopBlock.getComponentType());
if (coopBlockState == null) { if (coopBlockComponent == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
Ref<EntityStore> playerRef = context.getEntity(); Ref<EntityStore> ref = context.getEntity();
LivingEntity playerEntity = (LivingEntity)EntityUtils.getEntity(playerRef, commandBuffer); if (EntityUtils.getEntity(ref, commandBuffer) instanceof LivingEntity livingEntity) {
if (playerEntity == null) { CombinedItemContainer inventoryContainer = livingEntity.getInventory().getCombinedHotbarFirst();
context.getState().state = InteractionState.Failed; if (inventoryContainer != null) {
} else { coopBlockComponent.gatherProduceFromContainer(inventoryContainer);
CombinedItemContainer playerInventoryContainer = playerEntity.getInventory().getCombinedHotbarFirst();
if (playerInventoryContainer != null) {
coopBlockState.gatherProduceFromInventory(playerInventoryContainer);
BlockType currentBlockType = worldChunk.getBlockType(targetBlock); BlockType currentBlockType = worldChunk.getBlockType(targetBlock);
assert currentBlockType != null; assert currentBlockType != null;
worldChunk.setBlockInteractionState(targetBlock, currentBlockType, coopBlockState.hasProduce() ? "Produce_Ready" : "default"); worldChunk.setBlockInteractionState(targetBlock, currentBlockType, coopBlockComponent.hasProduce() ? "Produce_Ready" : "default");
} }
} else {
context.getState().state = InteractionState.Failed;
} }
} }
} else {
context.getState().state = InteractionState.Failed;
} }
} }
} }

View File

@@ -29,6 +29,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class UseWateringCanInteraction extends SimpleBlockInteraction { public class UseWateringCanInteraction extends SimpleBlockInteraction {
@Nonnull
public static final BuilderCodec<UseWateringCanInteraction> CODEC = BuilderCodec.builder( public static final BuilderCodec<UseWateringCanInteraction> CODEC = BuilderCodec.builder(
UseWateringCanInteraction.class, UseWateringCanInteraction::new, SimpleBlockInteraction.CODEC UseWateringCanInteraction.class, UseWateringCanInteraction::new, SimpleBlockInteraction.CODEC
) )
@@ -61,45 +62,52 @@ public class UseWateringCanInteraction extends SimpleBlockInteraction {
) { ) {
int x = targetBlock.getX(); int x = targetBlock.getX();
int z = targetBlock.getZ(); int z = targetBlock.getZ();
WorldChunk worldChunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z)); long chunkIndex = ChunkUtil.indexChunkFromBlock(x, z);
Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z); WorldChunk worldChunk = world.getChunk(chunkIndex);
if (blockRef == null) { if (worldChunk == null) {
blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
}
if (blockRef == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
Store<ChunkStore> chunkStore = world.getChunkStore().getStore(); Ref<ChunkStore> blockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY(), z);
WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType()); if (blockRef == null) {
TilledSoilBlock soil = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType()); blockRef = BlockModule.ensureBlockEntity(worldChunk, targetBlock.x, targetBlock.y, targetBlock.z);
if (soil != null) { }
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
soil.setWateredUntil(wateredUntil); if (blockRef != null && blockRef.isValid()) {
worldChunk.setTicking(x, targetBlock.getY(), z, true); Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
worldChunk.getBlockChunk().getSectionAtBlockY(targetBlock.y).scheduleTick(ChunkUtil.indexBlock(x, targetBlock.y, z), wateredUntil); WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
worldChunk.setTicking(x, targetBlock.getY() + 1, z, true); TilledSoilBlock tilledSoilBlockComponent = chunkStore.getComponent(blockRef, TilledSoilBlock.getComponentType());
} else { if (tilledSoilBlockComponent != null) {
FarmingBlock farmingState = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType()); Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS);
if (farmingState == null) { tilledSoilBlockComponent.setWateredUntil(wateredUntil);
context.getState().state = InteractionState.Failed; 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 { } else {
Ref<ChunkStore> soilRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z); FarmingBlock farmingBlockComponent = chunkStore.getComponent(blockRef, FarmingBlock.getComponentType());
if (soilRef == null) { if (farmingBlockComponent == null) {
context.getState().state = InteractionState.Failed; context.getState().state = InteractionState.Failed;
} else { } else {
soil = chunkStore.getComponent(soilRef, TilledSoilBlock.getComponentType()); Ref<ChunkStore> soilBlockRef = worldChunk.getBlockComponentEntity(x, targetBlock.getY() - 1, z);
if (soil == null) { if (soilBlockRef != null && soilBlockRef.isValid()) {
context.getState().state = InteractionState.Failed; 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 { } else {
Instant wateredUntil = worldTimeResource.getGameTime().plus(this.duration, ChronoUnit.SECONDS); context.getState().state = InteractionState.Failed;
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);
} }
} }
} }
} else {
context.getState().state = InteractionState.Failed;
} }
} }
} }

View File

@@ -56,10 +56,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class CoopBlock implements Component<ChunkStore> { public class CoopBlock implements Component<ChunkStore> {
@Nonnull
public static final String STATE_PRODUCE = "Produce_Ready"; public static final String STATE_PRODUCE = "Produce_Ready";
@Nonnull
public static final BuilderCodec<CoopBlock> CODEC = BuilderCodec.builder(CoopBlock.class, CoopBlock::new) 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) .append(new KeyedCodec<>("FarmingCoopId", Codec.STRING, true), (coop, s) -> coop.coopAssetId = s, coop -> coop.coopAssetId)
.add() .add()
@@ -73,7 +76,9 @@ public class CoopBlock implements Component<ChunkStore> {
.add() .add()
.build(); .build();
protected String coopAssetId; protected String coopAssetId;
protected List<CoopBlock.CoopResident> residents = new ArrayList<>(); @Nonnull
protected List<CoopBlock.CoopResident> residents = new ObjectArrayList<>();
@Nonnull
protected ItemContainer itemContainer = EmptyItemContainer.INSTANCE; protected ItemContainer itemContainer = EmptyItemContainer.INSTANCE;
public static ComponentType<ChunkStore, CoopBlock> getComponentType() { public static ComponentType<ChunkStore, CoopBlock> getComponentType() {
@@ -81,7 +86,7 @@ public class CoopBlock implements Component<ChunkStore> {
} }
public CoopBlock() { public CoopBlock() {
ArrayList<ItemStack> remainder = new ArrayList<>(); List<ItemStack> remainder = new ObjectArrayList<>();
this.itemContainer = ItemContainer.ensureContainerCapacity(this.itemContainer, (short)5, SimpleItemContainer::new, remainder); 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); 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.coopAssetId = farmingCoopId;
this.residents.addAll(residents); this.residents.addAll(residents);
this.itemContainer = itemContainer.clone(); 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); 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(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset == null) { if (coopAsset == null) {
return false; return false;
} else if (this.residents.size() >= coopAsset.getMaxResidents()) { } else if (this.residents.size() >= coopAsset.getMaxResidents()) {
return false; return false;
} else if (!this.getCoopAcceptsNPCGroup(metadata.getRoleIndex())) { } else if (!this.getCoopAcceptsNPC(metadata.getNpcNameKey())) {
return false; return false;
} else { } else {
this.residents.add(new CoopBlock.CoopResident(metadata, null, worldTimeResource.getGameTime())); 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(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset == null) { if (coopAsset == null) {
return false; return false;
@@ -124,7 +131,7 @@ public class CoopBlock implements Component<ChunkStore> {
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType()); CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
if (coopResidentComponent != null) { if (coopResidentComponent != null) {
return false; return false;
} else if (!this.getCoopAcceptsNPCGroup(npcComponent.getRoleIndex())) { } else if (!this.getCoopAcceptsNPC(npcComponent.getRoleName())) {
return false; return false;
} else if (this.residents.size() >= coopAsset.getMaxResidents()) { } else if (this.residents.size() >= coopAsset.getMaxResidents()) {
return false; return false;
@@ -137,7 +144,7 @@ public class CoopBlock implements Component<ChunkStore> {
} else { } else {
PersistentRef persistentRef = new PersistentRef(); PersistentRef persistentRef = new PersistentRef();
persistentRef.setEntity(entityRef, uuidComponent.getUuid()); 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()); CoopBlock.CoopResident residentRecord = new CoopBlock.CoopResident(metadata, persistentRef, worldTimeResource.getGameTime());
residentRecord.deployedToWorld = true; residentRecord.deployedToWorld = true;
this.residents.add(residentRecord); 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); TagSetPlugin.TagSetLookup tagSetPlugin = TagSetPlugin.get(NPCGroup.class);
int roleIndex = NPCPlugin.get().getIndex(npcNameKey);
FarmingCoopAsset coopAsset = this.getCoopAsset(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset == null) { if (coopAsset == null) {
return false; return false;
@@ -159,7 +167,7 @@ public class CoopBlock implements Component<ChunkStore> {
return true; return true;
} else { } else {
for (int group : acceptedNpcGroupIndexes) { for (int group : acceptedNpcGroupIndexes) {
if (tagSetPlugin.tagInSet(group, npcRoleIndex)) { if (tagSetPlugin.tagInSet(group, roleIndex)) {
return true; 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(); Instant currentTime = worldTimeResource.getGameTime();
FarmingCoopAsset coopAsset = this.getCoopAsset(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset != null) { if (coopAsset != null) {
@@ -184,8 +192,7 @@ public class CoopBlock implements Component<ChunkStore> {
resident.setLastProduced(currentTime); resident.setLastProduced(currentTime);
} else { } else {
CapturedNPCMetadata residentMeta = resident.getMetadata(); CapturedNPCMetadata residentMeta = resident.getMetadata();
int npcRoleIndex = residentMeta.getRoleIndex(); String npcName = residentMeta.getNpcNameKey();
String npcName = NPCPlugin.get().getName(npcRoleIndex);
String npcDropListName = produceDropsMap.get(npcName); String npcDropListName = produceDropsMap.get(npcName);
if (npcDropListName != null) { if (npcDropListName != null) {
ItemDropList dropListAsset = ItemDropList.getAssetMap().getAsset(npcDropListName); 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()) { for (ItemStack item : this.itemContainer.removeAllItemStacks()) {
playerInventory.addItemStack(item); playerInventory.addItemStack(item);
} }
} }
public void ensureSpawnResidentsInWorld(World world, Store<EntityStore> store, Vector3d coopLocation, Vector3d spawnOffset) { public void ensureSpawnResidentsInWorld(
NPCPlugin npcModule = NPCPlugin.get(); @Nonnull World world, @Nonnull Store<EntityStore> store, @Nonnull Vector3d coopLocation, @Nonnull Vector3d spawnOffset
) {
FarmingCoopAsset coopAsset = this.getCoopAsset(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset != null) { if (coopAsset != null) {
float radiansPerSpawn = (float) (Math.PI * 2) / coopAsset.getMaxResidents(); float radiansPerSpawn = (float) (Math.PI * 2) / coopAsset.getMaxResidents();
@@ -241,7 +249,8 @@ public class CoopBlock implements Component<ChunkStore> {
for (CoopBlock.CoopResident resident : this.residents) { for (CoopBlock.CoopResident resident : this.residents) {
CapturedNPCMetadata residentMeta = resident.getMetadata(); CapturedNPCMetadata residentMeta = resident.getMetadata();
int npcRoleIndex = residentMeta.getRoleIndex(); String npcNameKey = residentMeta.getNpcNameKey();
int npcRoleIndex = NPCPlugin.get().getIndex(npcNameKey);
boolean residentDeployed = resident.getDeployedToWorld(); boolean residentDeployed = resident.getDeployedToWorld();
PersistentRef residentEntityId = resident.getPersistentRef(); PersistentRef residentEntityId = resident.getPersistentRef();
if (!residentDeployed && residentEntityId == null) { if (!residentDeployed && residentEntityId == null) {
@@ -251,9 +260,8 @@ public class CoopBlock implements Component<ChunkStore> {
spawningContext.setSpawnable((ISpawnableWithModel)roleBuilder); spawningContext.setSpawnable((ISpawnableWithModel)roleBuilder);
if (spawningContext.set(world, residentSpawnLocation.x, residentSpawnLocation.y, residentSpawnLocation.z) if (spawningContext.set(world, residentSpawnLocation.x, residentSpawnLocation.y, residentSpawnLocation.z)
&& spawningContext.canSpawn() == SpawnTestResult.TEST_OK) { && spawningContext.canSpawn() == SpawnTestResult.TEST_OK) {
Pair<Ref<EntityStore>, NPCEntity> npcPair = npcModule.spawnEntity( Pair<Ref<EntityStore>, NPCEntity> npcPair = NPCPlugin.get()
store, npcRoleIndex, spawningContext.newPosition(), Vector3f.ZERO, null, null .spawnEntity(store, npcRoleIndex, spawningContext.newPosition(), Vector3f.ZERO, null, null);
);
if (npcPair == null) { if (npcPair == null) {
resident.setPersistentRef(null); resident.setPersistentRef(null);
resident.setDeployedToWorld(false); resident.setDeployedToWorld(false);
@@ -288,40 +296,45 @@ public class CoopBlock implements Component<ChunkStore> {
} }
} }
public void ensureNoResidentsInWorld(Store<EntityStore> store) { public void ensureNoResidentsInWorld(@Nonnull Store<EntityStore> store) {
ArrayList<CoopBlock.CoopResident> residentsToRemove = new ArrayList<>(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset != null) {
ObjectArrayList<CoopBlock.CoopResident> residentsToRemove = new ObjectArrayList<>();
for (CoopBlock.CoopResident resident : this.residents) { for (CoopBlock.CoopResident resident : this.residents) {
boolean deployed = resident.getDeployedToWorld(); boolean deployed = resident.getDeployedToWorld();
PersistentRef entityUuid = resident.getPersistentRef(); PersistentRef entityUuid = resident.getPersistentRef();
if (deployed || entityUuid != null) { if (deployed || entityUuid != null) {
Ref<EntityStore> entityRef = entityUuid.getEntity(store); Ref<EntityStore> entityRef = entityUuid.getEntity(store);
if (entityRef == null) { if (entityRef == null) {
residentsToRemove.add(resident);
} else {
CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
if (coopResidentComponent == null) {
residentsToRemove.add(resident); residentsToRemove.add(resident);
} else { } else {
DeathComponent deathComponent = store.getComponent(entityRef, DeathComponent.getComponentType()); CoopResidentComponent coopResidentComponent = store.getComponent(entityRef, CoopResidentComponent.getComponentType());
if (deathComponent != null) { if (coopResidentComponent == null) {
residentsToRemove.add(resident); residentsToRemove.add(resident);
} else { } else {
coopResidentComponent.setMarkedForDespawn(true); DeathComponent deathComponent = store.getComponent(entityRef, DeathComponent.getComponentType());
resident.setPersistentRef(null); if (deathComponent != null) {
resident.setDeployedToWorld(false); 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) { for (CoopBlock.CoopResident residentx : residentsToRemove) {
this.residents.remove(residentx); this.residents.remove(residentx);
}
} }
} }
public boolean shouldResidentsBeInCoop(WorldTimeResource worldTimeResource) { public boolean shouldResidentsBeInCoop(@Nonnull WorldTimeResource worldTimeResource) {
FarmingCoopAsset coopAsset = this.getCoopAsset(); FarmingCoopAsset coopAsset = this.getCoopAsset();
if (coopAsset == null) { if (coopAsset == null) {
return true; return true;
@@ -337,7 +350,7 @@ public class CoopBlock implements Component<ChunkStore> {
} }
@Nullable @Nullable
public Instant getNextScheduledTick(WorldTimeResource worldTimeResource) { public Instant getNextScheduledTick(@Nonnull WorldTimeResource worldTimeResource) {
Instant gameTime = worldTimeResource.getGameTime(); Instant gameTime = worldTimeResource.getGameTime();
LocalDateTime gameDateTime = worldTimeResource.getGameDateTime(); LocalDateTime gameDateTime = worldTimeResource.getGameDateTime();
int gameHour = worldTimeResource.getCurrentHour(); 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; CoopBlock.CoopResident removedResident = null;
for (CoopBlock.CoopResident resident : this.residents) { 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); Vector3i location = new Vector3i(blockX, blockY, blockZ);
world.execute(() -> this.ensureSpawnResidentsInWorld(world, store, location.toVector3d(), new Vector3d().assign(Vector3d.FORWARD))); world.execute(() -> this.ensureSpawnResidentsInWorld(world, store, location.toVector3d(), new Vector3d().assign(Vector3d.FORWARD)));
this.generateProduceToInventory(worldTimeResource); this.generateProduceToInventory(worldTimeResource);
@@ -416,6 +431,7 @@ public class CoopBlock implements Component<ChunkStore> {
} }
public static class CoopResident { public static class CoopResident {
@Nonnull
public static final BuilderCodec<CoopBlock.CoopResident> CODEC = BuilderCodec.builder(CoopBlock.CoopResident.class, CoopBlock.CoopResident::new) 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) .append(new KeyedCodec<>("Metadata", CapturedNPCMetadata.CODEC), (coop, meta) -> coop.metadata = meta, coop -> coop.metadata)
.add() .add()
@@ -439,7 +455,7 @@ public class CoopBlock implements Component<ChunkStore> {
public CoopResident() { public CoopResident() {
} }
public CoopResident(CapturedNPCMetadata metadata, PersistentRef persistentRef, Instant lastProduced) { public CoopResident(CapturedNPCMetadata metadata, @Nullable PersistentRef persistentRef, @Nonnull Instant lastProduced) {
this.metadata = metadata; this.metadata = metadata;
this.persistentRef = persistentRef; this.persistentRef = persistentRef;
this.lastProduced = lastProduced; this.lastProduced = lastProduced;

View File

@@ -8,10 +8,13 @@ import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import java.time.Instant; import java.time.Instant;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class FarmingBlock implements Component<ChunkStore> { public class FarmingBlock implements Component<ChunkStore> {
@Nonnull
public static final String DEFAULT_STAGE_SET = "Default"; public static final String DEFAULT_STAGE_SET = "Default";
@Nonnull
public static final BuilderCodec<FarmingBlock> CODEC = BuilderCodec.builder(FarmingBlock.class, FarmingBlock::new) public static final BuilderCodec<FarmingBlock> CODEC = BuilderCodec.builder(FarmingBlock.class, FarmingBlock::new)
.append( .append(
new KeyedCodec<>("CurrentStageSet", Codec.STRING), new KeyedCodec<>("CurrentStageSet", Codec.STRING),
@@ -56,13 +59,14 @@ public class FarmingBlock implements Component<ChunkStore> {
) )
.add() .add()
.build(); .build();
@Nonnull
private String currentStageSet = "Default"; private String currentStageSet = "Default";
private float growthProgress; private float growthProgress;
private Instant lastTickGameTime; private Instant lastTickGameTime;
private int generation; private int generation;
private String previousBlockType; private String previousBlockType;
private float spreadRate = 1.0F; private float spreadRate = 1.0F;
private int executions = 0; private int executions;
public static ComponentType<ChunkStore, FarmingBlock> getComponentType() { public static ComponentType<ChunkStore, FarmingBlock> getComponentType() {
return FarmingPlugin.get().getFarmingBlockComponentType(); return FarmingPlugin.get().getFarmingBlockComponentType();
@@ -72,7 +76,13 @@ public class FarmingBlock implements Component<ChunkStore> {
} }
public FarmingBlock( 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.currentStageSet = currentStageSet;
this.growthProgress = growthProgress; this.growthProgress = growthProgress;
@@ -83,11 +93,12 @@ public class FarmingBlock implements Component<ChunkStore> {
this.executions = executions; this.executions = executions;
} }
@Nonnull
public String getCurrentStageSet() { public String getCurrentStageSet() {
return this.currentStageSet; return this.currentStageSet;
} }
public void setCurrentStageSet(String currentStageSet) { public void setCurrentStageSet(@Nullable String currentStageSet) {
this.currentStageSet = currentStageSet != null ? currentStageSet : "Default"; this.currentStageSet = currentStageSet != null ? currentStageSet : "Default";
} }
@@ -147,6 +158,7 @@ public class FarmingBlock implements Component<ChunkStore> {
); );
} }
@Nonnull
@Override @Override
public String toString() { public String toString() {
return "FarmingBlock{currentStageSet='" return "FarmingBlock{currentStageSet='"

View File

@@ -13,7 +13,7 @@ import javax.annotation.Nullable;
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public class FarmingBlockState implements Component<ChunkStore> { public class FarmingBlockState implements Component<ChunkStore> {
@Nonnull @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) .append(new KeyedCodec<>("BaseCrop", Codec.STRING), (state, crop) -> state.baseCrop = crop, state -> state.baseCrop)
.add() .add()
.append(new KeyedCodec<>("StageStart", Codec.INSTANT), (state, start) -> state.stageStart = start, state -> state.stageStart) .append(new KeyedCodec<>("StageStart", Codec.INSTANT), (state, start) -> state.stageStart = start, state -> state.stageStart)

View File

@@ -13,10 +13,12 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.time.Instant; import java.time.Instant;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class TilledSoilBlock implements Component<ChunkStore> { public class TilledSoilBlock implements Component<ChunkStore> {
public static int VERSION = 1; public static int VERSION = 1;
@Nonnull
public static final BuilderCodec<TilledSoilBlock> CODEC = BuilderCodec.builder(TilledSoilBlock.class, TilledSoilBlock::new) public static final BuilderCodec<TilledSoilBlock> CODEC = BuilderCodec.builder(TilledSoilBlock.class, TilledSoilBlock::new)
.versioned() .versioned()
.codecVersion(VERSION) .codecVersion(VERSION)
@@ -116,7 +118,8 @@ public class TilledSoilBlock implements Component<ChunkStore> {
this.decayTime = decayTime; 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); boolean watered = this.hasExternalWater() || this.wateredUntil != null && this.wateredUntil.isAfter(gameTime);
if (this.fertilized && watered) { if (this.fertilized && watered) {
return type.getBlockKeyForState("Fertilized_Watered"); return type.getBlockKeyForState("Fertilized_Watered");
@@ -127,6 +130,7 @@ public class TilledSoilBlock implements Component<ChunkStore> {
} }
} }
@Nonnull
@Override @Override
public String toString() { public String toString() {
return "TilledSoilBlock{planted=" return "TilledSoilBlock{planted="

View File

@@ -11,7 +11,9 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class MemoriesGameplayConfig { public class MemoriesGameplayConfig {
@Nonnull
public static final String ID = "Memories"; public static final String ID = "Memories";
@Nonnull
public static final BuilderCodec<MemoriesGameplayConfig> CODEC = BuilderCodec.builder(MemoriesGameplayConfig.class, MemoriesGameplayConfig::new) public static final BuilderCodec<MemoriesGameplayConfig> CODEC = BuilderCodec.builder(MemoriesGameplayConfig.class, MemoriesGameplayConfig::new)
.appendInherited( .appendInherited(
new KeyedCodec<>("MemoriesAmountPerLevel", Codec.INT_ARRAY), new KeyedCodec<>("MemoriesAmountPerLevel", Codec.INT_ARRAY),

View File

@@ -40,6 +40,7 @@ import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.entity.entities.player.windows.Window; import com.hypixel.hytale.server.core.entity.entities.player.windows.Window;
import com.hypixel.hytale.server.core.io.PacketHandler; import com.hypixel.hytale.server.core.io.PacketHandler;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.player.PlayerSystems; import com.hypixel.hytale.server.core.modules.entity.player.PlayerSystems;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
@@ -69,9 +70,14 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class MemoriesPlugin extends JavaPlugin { public class MemoriesPlugin extends JavaPlugin {
@Nonnull
public static final String MEMORIES_JSON_PATH = "memories.json";
private static MemoriesPlugin instance; private static MemoriesPlugin instance;
@Nonnull
private final Config<MemoriesPlugin.MemoriesPluginConfig> config = this.withConfig(MemoriesPlugin.MemoriesPluginConfig.CODEC); private final Config<MemoriesPlugin.MemoriesPluginConfig> config = this.withConfig(MemoriesPlugin.MemoriesPluginConfig.CODEC);
@Nonnull
private final List<MemoryProvider<?>> providers = new ObjectArrayList<>(); private final List<MemoryProvider<?>> providers = new ObjectArrayList<>();
@Nonnull
private final Map<String, Set<Memory>> allMemories = new Object2ObjectRBTreeMap<>(); private final Map<String, Set<Memory>> allMemories = new Object2ObjectRBTreeMap<>();
private ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType; private ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType;
@Nullable @Nullable
@@ -95,9 +101,16 @@ public class MemoriesPlugin extends JavaPlugin {
OpenCustomUIInteraction.registerCustomPageSupplier(this, MemoriesUnlockedPage.class, "MemoriesUnlocked", new MemoriesUnlockedPageSuplier()); OpenCustomUIInteraction.registerCustomPageSupplier(this, MemoriesUnlockedPage.class, "MemoriesUnlocked", new MemoriesUnlockedPageSuplier());
Window.CLIENT_REQUESTABLE_WINDOW_TYPES.put(WindowType.Memories, MemoriesWindow::new); Window.CLIENT_REQUESTABLE_WINDOW_TYPES.put(WindowType.Memories, MemoriesWindow::new);
this.playerMemoriesComponentType = entityStoreRegistry.registerComponent(PlayerMemories.class, "PlayerMemories", PlayerMemories.CODEC); this.playerMemoriesComponentType = entityStoreRegistry.registerComponent(PlayerMemories.class, "PlayerMemories", PlayerMemories.CODEC);
ComponentType<EntityStore, Player> playerComponentType = Player.getComponentType();
ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ComponentType<EntityStore, TransformComponent> transformComponentType = TransformComponent.getComponentType();
NPCMemoryProvider npcMemoryProvider = new NPCMemoryProvider(); NPCMemoryProvider npcMemoryProvider = new NPCMemoryProvider();
this.registerMemoryProvider(npcMemoryProvider); this.registerMemoryProvider(npcMemoryProvider);
entityStoreRegistry.registerSystem(new NPCMemory.GatherMemoriesSystem(npcMemoryProvider.getCollectionRadius())); entityStoreRegistry.registerSystem(
new NPCMemory.GatherMemoriesSystem(
transformComponentType, playerComponentType, playerRefComponentType, this.playerMemoriesComponentType, npcMemoryProvider.getCollectionRadius()
)
);
for (MemoryProvider<?> provider : this.providers) { for (MemoryProvider<?> provider : this.providers) {
BuilderCodec<? extends Memory> codec = (BuilderCodec<? extends Memory>)provider.getCodec(); BuilderCodec<? extends Memory> codec = (BuilderCodec<? extends Memory>)provider.getCodec();
@@ -105,11 +118,11 @@ public class MemoriesPlugin extends JavaPlugin {
} }
this.getEventRegistry().register(AllNPCsLoadedEvent.class, event -> this.onAssetsLoad()); this.getEventRegistry().register(AllNPCsLoadedEvent.class, event -> this.onAssetsLoad());
entityStoreRegistry.registerSystem(new MemoriesPlugin.PlayerAddedSystem()); entityStoreRegistry.registerSystem(new MemoriesPlugin.PlayerAddedSystem(playerComponentType, playerRefComponentType, this.playerMemoriesComponentType));
this.getCodecRegistry(Interaction.CODEC).register("SetMemoriesCapacity", SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction.CODEC); this.getCodecRegistry(Interaction.CODEC).register("SetMemoriesCapacity", SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction.CODEC);
this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(MemoriesGameplayConfig.class, "Memories", MemoriesGameplayConfig.CODEC); this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(MemoriesGameplayConfig.class, "Memories", MemoriesGameplayConfig.CODEC);
this.getCodecRegistry(Interaction.CODEC).register("MemoriesCondition", MemoriesConditionInteraction.class, MemoriesConditionInteraction.CODEC); this.getCodecRegistry(Interaction.CODEC).register("MemoriesCondition", MemoriesConditionInteraction.class, MemoriesConditionInteraction.CODEC);
entityStoreRegistry.registerSystem(new TempleRespawnPlayersSystem()); entityStoreRegistry.registerSystem(new TempleRespawnPlayersSystem(playerRefComponentType, transformComponentType));
this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ForgottenTempleConfig.class, "ForgottenTemple", ForgottenTempleConfig.CODEC); this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ForgottenTempleConfig.class, "ForgottenTemple", ForgottenTempleConfig.CODEC);
} }
@@ -169,6 +182,7 @@ public class MemoriesPlugin extends JavaPlugin {
this.providers.add(memoryProvider); this.providers.add(memoryProvider);
} }
@Nonnull
public Map<String, Set<Memory>> getAllMemories() { public Map<String, Set<Memory>> getAllMemories() {
return this.allMemories; return this.allMemories;
} }
@@ -299,6 +313,7 @@ public class MemoriesPlugin extends JavaPlugin {
} }
public static class MemoriesPluginConfig { public static class MemoriesPluginConfig {
@Nonnull
public static final BuilderCodec<MemoriesPlugin.MemoriesPluginConfig> CODEC = BuilderCodec.builder( public static final BuilderCodec<MemoriesPlugin.MemoriesPluginConfig> CODEC = BuilderCodec.builder(
MemoriesPlugin.MemoriesPluginConfig.class, MemoriesPlugin.MemoriesPluginConfig::new MemoriesPlugin.MemoriesPluginConfig.class, MemoriesPlugin.MemoriesPluginConfig::new
) )
@@ -321,7 +336,24 @@ public class MemoriesPlugin extends JavaPlugin {
@Nonnull @Nonnull
private final Set<Dependency<EntityStore>> dependencies = Set.of(new SystemDependency<>(Order.AFTER, PlayerSystems.PlayerSpawnedSystem.class)); private final Set<Dependency<EntityStore>> dependencies = Set.of(new SystemDependency<>(Order.AFTER, PlayerSystems.PlayerSpawnedSystem.class));
@Nonnull @Nonnull
private final Query<EntityStore> query = Query.and(Player.getComponentType(), PlayerRef.getComponentType()); private final ComponentType<EntityStore, Player> playerComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType;
@Nonnull
private final Query<EntityStore> query;
public PlayerAddedSystem(
@Nonnull ComponentType<EntityStore, Player> playerComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType
) {
this.playerComponentType = playerComponentType;
this.playerRefComponentType = playerRefComponentType;
this.playerMemoriesComponentType = playerMemoriesComponentType;
this.query = Query.and(playerComponentType, playerRefComponentType);
}
@Nonnull @Nonnull
@Override @Override
@@ -339,15 +371,15 @@ public class MemoriesPlugin extends JavaPlugin {
public void onEntityAdded( public void onEntityAdded(
@Nonnull Ref<EntityStore> ref, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer @Nonnull Ref<EntityStore> ref, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer
) { ) {
Player playerComponent = store.getComponent(ref, Player.getComponentType()); Player playerComponent = store.getComponent(ref, this.playerComponentType);
assert playerComponent != null; assert playerComponent != null;
PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType()); PlayerRef playerRefComponent = store.getComponent(ref, this.playerRefComponentType);
assert playerRefComponent != null; assert playerRefComponent != null;
PlayerMemories playerMemoriesComponent = store.getComponent(ref, PlayerMemories.getComponentType()); PlayerMemories playerMemoriesComponent = store.getComponent(ref, this.playerMemoriesComponentType);
boolean isFeatureUnlockedByPlayer = playerMemoriesComponent != null; boolean isFeatureUnlockedByPlayer = playerMemoriesComponent != null;
PacketHandler playerConnection = playerRefComponent.getPacketHandler(); PacketHandler playerConnection = playerRefComponent.getPacketHandler();
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(isFeatureUnlockedByPlayer)); playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(isFeatureUnlockedByPlayer));
@@ -361,6 +393,7 @@ public class MemoriesPlugin extends JavaPlugin {
} }
private static class RecordedMemories { private static class RecordedMemories {
@Nonnull
public static final BuilderCodec<MemoriesPlugin.RecordedMemories> CODEC = BuilderCodec.builder( public static final BuilderCodec<MemoriesPlugin.RecordedMemories> CODEC = BuilderCodec.builder(
MemoriesPlugin.RecordedMemories.class, MemoriesPlugin.RecordedMemories::new MemoriesPlugin.RecordedMemories.class, MemoriesPlugin.RecordedMemories::new
) )
@@ -371,7 +404,9 @@ public class MemoriesPlugin extends JavaPlugin {
}, recordedMemories -> recordedMemories.memories.toArray(Memory[]::new)) }, recordedMemories -> recordedMemories.memories.toArray(Memory[]::new))
.add() .add()
.build(); .build();
@Nonnull
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
@Nonnull
private final Set<Memory> memories = new HashSet<>(); private final Set<Memory> memories = new HashSet<>();
} }
} }

View File

@@ -15,6 +15,7 @@ import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class PlayerMemories implements Component<EntityStore> { public class PlayerMemories implements Component<EntityStore> {
@Nonnull
public static final BuilderCodec<PlayerMemories> CODEC = BuilderCodec.builder(PlayerMemories.class, PlayerMemories::new) public static final BuilderCodec<PlayerMemories> CODEC = BuilderCodec.builder(PlayerMemories.class, PlayerMemories::new)
.append( .append(
new KeyedCodec<>("Capacity", Codec.INTEGER), new KeyedCodec<>("Capacity", Codec.INTEGER),
@@ -29,6 +30,7 @@ public class PlayerMemories implements Component<EntityStore> {
}, playerMemories -> playerMemories.memories.toArray(Memory[]::new)) }, playerMemories -> playerMemories.memories.toArray(Memory[]::new))
.add() .add()
.build(); .build();
@Nonnull
private final Set<Memory> memories = new LinkedHashSet<>(); private final Set<Memory> memories = new LinkedHashSet<>();
private int memoriesCapacity; private int memoriesCapacity;

View File

@@ -142,7 +142,7 @@ public class MemoriesConditionInteraction extends Interaction {
} }
@Override @Override
protected void configurePacket(com.hypixel.hytale.protocol.Interaction packet) { protected void configurePacket(@Nonnull com.hypixel.hytale.protocol.Interaction packet) {
super.configurePacket(packet); super.configurePacket(packet);
com.hypixel.hytale.protocol.MemoriesConditionInteraction p = (com.hypixel.hytale.protocol.MemoriesConditionInteraction)packet; com.hypixel.hytale.protocol.MemoriesConditionInteraction p = (com.hypixel.hytale.protocol.MemoriesConditionInteraction)packet;
p.memoriesNext = new Int2IntOpenHashMap(this.next.size()); p.memoriesNext = new Int2IntOpenHashMap(this.next.size());
@@ -156,11 +156,9 @@ public class MemoriesConditionInteraction extends Interaction {
@Override @Override
public boolean walk(@Nonnull Collector collector, @Nonnull InteractionContext context) { public boolean walk(@Nonnull Collector collector, @Nonnull InteractionContext context) {
if (this.next != null) { for (Entry<String> entry : this.next.int2ObjectEntrySet()) {
for (Entry<String> entry : this.next.int2ObjectEntrySet()) { if (InteractionManager.walkInteraction(collector, context, new MemoriesConditionInteraction.MemoriesTag(entry.getIntKey()), entry.getValue())) {
if (InteractionManager.walkInteraction(collector, context, new MemoriesConditionInteraction.MemoriesTag(entry.getIntKey()), entry.getValue())) { return true;
return true;
}
} }
} }
@@ -172,6 +170,7 @@ public class MemoriesConditionInteraction extends Interaction {
return false; return false;
} }
@Nonnull
@Override @Override
public WaitForDataFrom getWaitForDataFrom() { public WaitForDataFrom getWaitForDataFrom() {
return WaitForDataFrom.Server; return WaitForDataFrom.Server;

View File

@@ -21,6 +21,15 @@ import com.hypixel.hytale.server.core.util.NotificationUtil;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class SetMemoriesCapacityInteraction extends SimpleInstantInteraction { 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( public static final BuilderCodec<SetMemoriesCapacityInteraction> CODEC = BuilderCodec.builder(
SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction::new, SimpleInstantInteraction.CODEC SetMemoriesCapacityInteraction.class, SetMemoriesCapacityInteraction::new, SimpleInstantInteraction.CODEC
) )
@@ -48,15 +57,14 @@ public class SetMemoriesCapacityInteraction extends SimpleInstantInteraction {
memoriesComponent.setMemoriesCapacity(this.capacity); memoriesComponent.setMemoriesCapacity(this.capacity);
if (previousCapacity <= 0) { if (previousCapacity <= 0) {
PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType()); PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
if (playerRefComponent != null) {
assert playerRefComponent != null; PacketHandler playerConnection = playerRefComponent.getPacketHandler();
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(true));
PacketHandler playerConnection = playerRefComponent.getPacketHandler(); NotificationUtil.sendNotification(
playerConnection.writeNoCache(new UpdateMemoriesFeatureStatus(true)); playerConnection, MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_NOTIFICATION, null, "NotificationIcons/MemoriesIcon.png"
NotificationUtil.sendNotification( );
playerConnection, Message.translation("server.memories.general.featureUnlockedNotification"), null, "NotificationIcons/MemoriesIcon.png" playerRefComponent.sendMessage(MESSAGE_SERVER_MEMORIES_GENERAL_FEATURE_UNLOCKED_MESSAGE);
); }
playerRefComponent.sendMessage(Message.translation("server.memories.general.featureUnlockedMessage"));
} }
context.getState().state = InteractionState.Finished; context.getState().state = InteractionState.Finished;

View File

@@ -6,6 +6,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public abstract class Memory { public abstract class Memory {
@Nonnull
public static final CodecMapCodec<Memory> CODEC = new CodecMapCodec<>(); public static final CodecMapCodec<Memory> CODEC = new CodecMapCodec<>();
public abstract String getId(); public abstract String getId();

View File

@@ -13,6 +13,7 @@ import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.component.AddReason; import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.Store;
@@ -34,7 +35,6 @@ import com.hypixel.hytale.server.core.modules.entity.component.TransformComponen
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent; import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
import com.hypixel.hytale.server.core.modules.entity.item.PickupItemComponent; import com.hypixel.hytale.server.core.modules.entity.item.PickupItemComponent;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId; import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.server.core.modules.i18n.I18nModule;
import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
@@ -53,18 +53,14 @@ public class NPCMemory extends Memory {
@Nonnull @Nonnull
public static final String ID = "NPC"; public static final String ID = "NPC";
@Nonnull @Nonnull
public static final String ZONE_NAME_UNKNOWN = "???";
@Nonnull
public static final BuilderCodec<NPCMemory> CODEC = BuilderCodec.builder(NPCMemory.class, NPCMemory::new) 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) .append(new KeyedCodec<>("NPCRole", Codec.STRING), (npcMemory, s) -> npcMemory.npcRole = s, npcMemory -> npcMemory.npcRole)
.addValidator(Validators.nonNull()) .addValidator(Validators.nonNull())
.add() .add()
.append(new KeyedCodec<>("TranslationKey", Codec.STRING), (npcMemory, s) -> npcMemory.memoryTitleKey = s, npcMemory -> npcMemory.memoryTitleKey) .append(new KeyedCodec<>("TranslationKey", Codec.STRING), (npcMemory, s) -> npcMemory.memoryTitleKey = s, npcMemory -> npcMemory.memoryTitleKey)
.add() .add()
.append(
new KeyedCodec<>("IsMemoriesNameOverridden", Codec.BOOLEAN),
(npcMemory, aBoolean) -> npcMemory.isMemoriesNameOverridden = aBoolean,
npcMemory -> npcMemory.isMemoriesNameOverridden
)
.add()
.append( .append(
new KeyedCodec<>("CapturedTimestamp", Codec.LONG), new KeyedCodec<>("CapturedTimestamp", Codec.LONG),
(npcMemory, aDouble) -> npcMemory.capturedTimestamp = aDouble, (npcMemory, aDouble) -> npcMemory.capturedTimestamp = aDouble,
@@ -83,10 +79,8 @@ public class NPCMemory extends Memory {
npcMemory -> npcMemory.foundLocationGeneralNameKey npcMemory -> npcMemory.foundLocationGeneralNameKey
) )
.add() .add()
.afterDecode(NPCMemory::processConfig)
.build(); .build();
private String npcRole; private String npcRole;
private boolean isMemoriesNameOverridden;
private long capturedTimestamp; private long capturedTimestamp;
private String foundLocationZoneNameKey; private String foundLocationZoneNameKey;
private String foundLocationGeneralNameKey; private String foundLocationGeneralNameKey;
@@ -95,11 +89,9 @@ public class NPCMemory extends Memory {
private NPCMemory() { private NPCMemory() {
} }
public NPCMemory(@Nonnull String npcRole, @Nonnull String nameTranslationKey, boolean isMemoriesNameOverridden) { public NPCMemory(@Nonnull String npcRole, @Nonnull String nameTranslationKey) {
this.npcRole = npcRole; this.npcRole = npcRole;
this.memoryTitleKey = nameTranslationKey; this.memoryTitleKey = nameTranslationKey;
this.isMemoriesNameOverridden = isMemoriesNameOverridden;
this.processConfig();
} }
@Override @Override
@@ -119,25 +111,12 @@ public class NPCMemory extends Memory {
return Message.translation("server.memories.general.discovered.tooltipText"); return Message.translation("server.memories.general.discovered.tooltipText");
} }
@Nullable @Nonnull
@Override @Override
public String getIconPath() { public String getIconPath() {
return "UI/Custom/Pages/Memories/npcs/" + this.npcRole + ".png"; return "UI/Custom/Pages/Memories/npcs/" + this.npcRole + ".png";
} }
public void processConfig() {
if (this.isMemoriesNameOverridden) {
this.memoryTitleKey = "server.npcRoles." + this.npcRole + ".name";
if (I18nModule.get().getMessage("en-US", this.memoryTitleKey) == null) {
this.memoryTitleKey = "server.memories.names." + this.npcRole;
}
}
if (this.memoryTitleKey == null || this.memoryTitleKey.isEmpty()) {
this.memoryTitleKey = "server.npcRoles." + this.npcRole + ".name";
}
}
@Nonnull @Nonnull
@Override @Override
public Message getUndiscoveredTooltipText() { public Message getUndiscoveredTooltipText() {
@@ -157,6 +136,7 @@ public class NPCMemory extends Memory {
return this.foundLocationZoneNameKey; return this.foundLocationZoneNameKey;
} }
@Nonnull
public Message getLocationMessage() { public Message getLocationMessage() {
if (this.foundLocationGeneralNameKey != null) { if (this.foundLocationGeneralNameKey != null) {
return Message.translation(this.foundLocationGeneralNameKey); return Message.translation(this.foundLocationGeneralNameKey);
@@ -166,30 +146,28 @@ public class NPCMemory extends Memory {
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(@Nullable Object o) {
if (o == null || this.getClass() != o.getClass()) { if (o == null || this.getClass() != o.getClass()) {
return false; return false;
} else if (!super.equals(o)) { } else if (!super.equals(o)) {
return false; return false;
} else { } else {
NPCMemory npcMemory = (NPCMemory)o; NPCMemory npcMemory = (NPCMemory)o;
return this.isMemoriesNameOverridden == npcMemory.isMemoriesNameOverridden && Objects.equals(this.npcRole, npcMemory.npcRole); return Objects.equals(this.npcRole, npcMemory.npcRole);
} }
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = super.hashCode(); int result = super.hashCode();
result = 31 * result + Objects.hashCode(this.npcRole); return 31 * result + Objects.hashCode(this.npcRole);
return 31 * result + Boolean.hashCode(this.isMemoriesNameOverridden);
} }
@Nonnull
@Override @Override
public String toString() { public String toString() {
return "NPCMemory{npcRole='" return "NPCMemory{npcRole='"
+ this.npcRole + this.npcRole
+ "', isMemoriesNameOverride="
+ this.isMemoriesNameOverridden
+ "', capturedTimestamp=" + "', capturedTimestamp="
+ this.capturedTimestamp + this.capturedTimestamp
+ "', foundLocationZoneNameKey='" + "', foundLocationZoneNameKey='"
@@ -199,12 +177,29 @@ public class NPCMemory extends Memory {
public static class GatherMemoriesSystem extends EntityTickingSystem<EntityStore> { public static class GatherMemoriesSystem extends EntityTickingSystem<EntityStore> {
@Nonnull @Nonnull
public static final Query<EntityStore> QUERY = Query.and( private final ComponentType<EntityStore, TransformComponent> transformComponentType;
TransformComponent.getComponentType(), Player.getComponentType(), PlayerMemories.getComponentType() @Nonnull
); private final ComponentType<EntityStore, Player> playerComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType;
@Nonnull
private final Query<EntityStore> query;
private final double radius; private final double radius;
public GatherMemoriesSystem(double radius) { public GatherMemoriesSystem(
@Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType,
@Nonnull ComponentType<EntityStore, Player> playerComponentType,
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType,
@Nonnull ComponentType<EntityStore, PlayerMemories> playerMemoriesComponentType,
double radius
) {
this.transformComponentType = transformComponentType;
this.playerComponentType = playerComponentType;
this.playerRefComponentType = playerRefComponentType;
this.playerMemoriesComponentType = playerMemoriesComponentType;
this.query = Query.and(transformComponentType, playerComponentType, playerRefComponentType, playerMemoriesComponentType);
this.radius = radius; this.radius = radius;
} }
@@ -216,12 +211,12 @@ public class NPCMemory extends Memory {
@Nonnull Store<EntityStore> store, @Nonnull Store<EntityStore> store,
@Nonnull CommandBuffer<EntityStore> commandBuffer @Nonnull CommandBuffer<EntityStore> commandBuffer
) { ) {
Player playerComponent = archetypeChunk.getComponent(index, Player.getComponentType()); Player playerComponent = archetypeChunk.getComponent(index, this.playerComponentType);
assert playerComponent != null; assert playerComponent != null;
if (playerComponent.getGameMode() == GameMode.Adventure) { if (playerComponent.getGameMode() == GameMode.Adventure) {
TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType);
assert transformComponent != null; assert transformComponent != null;
@@ -230,13 +225,13 @@ public class NPCMemory extends Memory {
ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList(); ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
npcSpatialResource.getSpatialStructure().collect(position, this.radius, results); npcSpatialResource.getSpatialStructure().collect(position, this.radius, results);
if (!results.isEmpty()) { if (!results.isEmpty()) {
PlayerRef playerRefComponent = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType);
assert playerRefComponent != null; assert playerRefComponent != null;
Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index); Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
MemoriesPlugin memoriesPlugin = MemoriesPlugin.get(); MemoriesPlugin memoriesPlugin = MemoriesPlugin.get();
PlayerMemories playerMemoriesComponent = archetypeChunk.getComponent(index, PlayerMemories.getComponentType()); PlayerMemories playerMemoriesComponent = archetypeChunk.getComponent(index, this.playerMemoriesComponentType);
assert playerMemoriesComponent != null; assert playerMemoriesComponent != null;
@@ -248,29 +243,22 @@ public class NPCMemory extends Memory {
NPCEntity npcComponent = commandBuffer.getComponent(npcRef, NPCEntity.getComponentType()); NPCEntity npcComponent = commandBuffer.getComponent(npcRef, NPCEntity.getComponentType());
if (npcComponent != null) { if (npcComponent != null) {
Role role = npcComponent.getRole(); Role role = npcComponent.getRole();
if (role != null && role.isMemory()) {
assert role != null; String memoriesNameOverride = role.getMemoriesNameOverride();
temp.npcRole = memoriesNameOverride != null && !memoriesNameOverride.isEmpty() ? memoriesNameOverride : npcComponent.getRoleName();
if (role.isMemory()) {
temp.isMemoriesNameOverridden = role.isMemoriesNameOverriden();
temp.npcRole = temp.isMemoriesNameOverridden ? role.getMemoriesNameOverride() : npcComponent.getRoleName();
temp.memoryTitleKey = role.getNameTranslationKey(); temp.memoryTitleKey = role.getNameTranslationKey();
temp.capturedTimestamp = System.currentTimeMillis(); temp.capturedTimestamp = System.currentTimeMillis();
temp.foundLocationGeneralNameKey = foundLocationZoneNameKey; temp.foundLocationGeneralNameKey = foundLocationZoneNameKey;
if (!memoriesPlugin.hasRecordedMemory(temp)) { if (!memoriesPlugin.hasRecordedMemory(temp) && playerMemoriesComponent.recordMemory(temp)) {
temp.processConfig(); NotificationUtil.sendNotification(
if (playerMemoriesComponent.recordMemory(temp)) { playerRefComponent.getPacketHandler(),
NotificationUtil.sendNotification( Message.translation("server.memories.general.collected").param("memoryTitle", Message.translation(temp.getTitle())),
playerRefComponent.getPacketHandler(), null,
Message.translation("server.memories.general.collected").param("memoryTitle", Message.translation(temp.getTitle())), "NotificationIcons/MemoriesIcon.png"
null, );
"NotificationIcons/MemoriesIcon.png" temp = new NPCMemory();
); TransformComponent npcTransformComponent = commandBuffer.getComponent(npcRef, TransformComponent.getComponentType());
temp = new NPCMemory(); if (npcTransformComponent != null) {
TransformComponent npcTransformComponent = commandBuffer.getComponent(npcRef, TransformComponent.getComponentType());
assert npcTransformComponent != null;
MemoriesGameplayConfig memoriesGameplayConfig = MemoriesGameplayConfig.get(store.getExternalData().getWorld().getGameplayConfig()); MemoriesGameplayConfig memoriesGameplayConfig = MemoriesGameplayConfig.get(store.getExternalData().getWorld().getGameplayConfig());
if (memoriesGameplayConfig != null) { if (memoriesGameplayConfig != null) {
ItemStack memoryItemStack = new ItemStack(memoriesGameplayConfig.getMemoriesCatchItemId()); ItemStack memoryItemStack = new ItemStack(memoriesGameplayConfig.getMemoriesCatchItemId());
@@ -301,7 +289,7 @@ public class NPCMemory extends Memory {
} }
} }
private static String findLocationZoneName(World world, Vector3d position) { private static String findLocationZoneName(@Nonnull World world, @Nonnull Vector3d position) {
if (world.getChunkStore().getGenerator() instanceof ChunkGenerator generator) { if (world.getChunkStore().getGenerator() instanceof ChunkGenerator generator) {
int seed = (int)world.getWorldConfig().getSeed(); int seed = (int)world.getWorldConfig().getSeed();
ZoneBiomeResult result = generator.getZoneBiomeResultAt(seed, MathUtil.floor(position.x), MathUtil.floor(position.z)); ZoneBiomeResult result = generator.getZoneBiomeResultAt(seed, MathUtil.floor(position.x), MathUtil.floor(position.z));
@@ -320,7 +308,10 @@ public class NPCMemory extends Memory {
} }
private static void displayCatchEntityParticles( 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(); ModelParticle particle = memoriesGameplayConfig.getMemoriesCatchEntityParticle();
if (particle != null) { if (particle != null) {
@@ -335,10 +326,9 @@ public class NPCMemory extends Memory {
for (Ref<EntityStore> ref : results) { for (Ref<EntityStore> ref : results) {
PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType()); PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
if (playerRefComponent != null) {
assert playerRefComponent != null; playerRefComponent.getPacketHandler().write(packet);
}
playerRefComponent.getPacketHandler().write(packet);
} }
} }
} }
@@ -347,7 +337,7 @@ public class NPCMemory extends Memory {
@Nonnull @Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return QUERY; return this.query;
} }
} }
} }

View File

@@ -42,9 +42,9 @@ public class NPCMemoryProvider extends MemoryProvider<NPCMemory> {
String translationKey = getNPCNameTranslationKey(builder); String translationKey = getNPCNameTranslationKey(builder);
NPCMemory memory; NPCMemory memory;
if (memoriesNameOverride != null && !memoriesNameOverride.isEmpty()) { if (memoriesNameOverride != null && !memoriesNameOverride.isEmpty()) {
memory = new NPCMemory(memoriesNameOverride, translationKey, true); memory = new NPCMemory(memoriesNameOverride, translationKey);
} else { } else {
memory = new NPCMemory(builderInfo.getKeyName(), translationKey, false); memory = new NPCMemory(builderInfo.getKeyName(), translationKey);
} }
allMemories.computeIfAbsent(category, s -> new HashSet<>()).add(memory); allMemories.computeIfAbsent(category, s -> new HashSet<>()).add(memory);

View File

@@ -34,11 +34,8 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList; import it.unimi.dsi.fastutil.objects.ObjectList;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -50,9 +47,10 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
private String currentCategory; private String currentCategory;
@Nullable @Nullable
private Memory selectedMemory; 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); super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction, MemoriesPage.PageEventData.CODEC);
this.recordMemoriesParticlesPosition = new Vector3d(blockPosition.x, blockPosition.y, blockPosition.z); this.recordMemoriesParticlesPosition = new Vector3d(blockPosition.x, blockPosition.y, blockPosition.z);
} }
@@ -103,11 +101,11 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
commandBuilder.set(selector + "#TotalMemoryCountComplete.Text", String.valueOf(memoriesInCategory.size())); commandBuilder.set(selector + "#TotalMemoryCountComplete.Text", String.valueOf(memoriesInCategory.size()));
boolean isCategoryComplete = recordedMemoriesCount == memoriesInCategory.size(); boolean isCategoryComplete = recordedMemoriesCount == memoriesInCategory.size();
if (isCategoryComplete) { if (isCategoryComplete) {
commandBuilder.set(selector + "#CategoryIcon.Background", "Pages/Memories/categories/" + category + "Complete.png"); commandBuilder.set(selector + "#CategoryIcon.AssetPath", "UI/Custom/Pages/Memories/categories/" + category + "Complete.png");
commandBuilder.set(selector + "#CompleteCategoryBackground.Visible", true); commandBuilder.set(selector + "#CompleteCategoryBackground.Visible", true);
commandBuilder.set(selector + "#CompleteCategoryCounter.Visible", true); commandBuilder.set(selector + "#CompleteCategoryCounter.Visible", true);
} else { } else {
commandBuilder.set(selector + "#CategoryIcon.Background", "Pages/Memories/categories/" + category + ".png"); commandBuilder.set(selector + "#CategoryIcon.AssetPath", "UI/Custom/Pages/Memories/categories/" + category + ".png");
commandBuilder.set(selector + "#NotCompleteCategoryCounter.Visible", true); commandBuilder.set(selector + "#NotCompleteCategoryCounter.Visible", true);
} }
@@ -356,10 +354,9 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
if (memory instanceof NPCMemory npcMemory) { if (memory instanceof NPCMemory npcMemory) {
Message locationNameKey = npcMemory.getLocationMessage(); Message locationNameKey = npcMemory.getLocationMessage();
long capturedTimestamp = npcMemory.getCapturedTimestamp(); long capturedTimestamp = npcMemory.getCapturedTimestamp();
String timeString = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn")
.withLocale(Locale.getDefault()) .param("location", locationNameKey)
.format(Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC)); .param("dateValue", Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC).toString());
Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn").param("location", locationNameKey).param("time", timeString);
commandBuilder.set("#MemoryTimeLocation.TextSpans", memoryLocationTimeText); commandBuilder.set("#MemoryTimeLocation.TextSpans", memoryLocationTimeText);
} }
@@ -378,13 +375,18 @@ public class MemoriesPage extends InteractiveCustomUIPage<MemoriesPage.PageEvent
MemoriesInfo, MemoriesInfo,
SelectMemory; SelectMemory;
@Nonnull
public static final Codec<MemoriesPage.PageAction> CODEC = new EnumCodec<>(MemoriesPage.PageAction.class); public static final Codec<MemoriesPage.PageAction> CODEC = new EnumCodec<>(MemoriesPage.PageAction.class);
} }
public static class PageEventData { public static class PageEventData {
@Nonnull
public static final String KEY_ACTION = "Action"; public static final String KEY_ACTION = "Action";
@Nonnull
public static final String KEY_CATEGORY = "Category"; public static final String KEY_CATEGORY = "Category";
@Nonnull
public static final String KEY_MEMORY_ID = "MemoryId"; public static final String KEY_MEMORY_ID = "MemoryId";
@Nonnull
public static final BuilderCodec<MemoriesPage.PageEventData> CODEC = BuilderCodec.builder( public static final BuilderCodec<MemoriesPage.PageEventData> CODEC = BuilderCodec.builder(
MemoriesPage.PageEventData.class, MemoriesPage.PageEventData::new MemoriesPage.PageEventData.class, MemoriesPage.PageEventData::new
) )

View File

@@ -2,17 +2,25 @@ package com.hypixel.hytale.builtin.adventure.memories.page;
import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref; 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.InteractionContext;
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage; 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.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class MemoriesPageSupplier implements OpenCustomUIInteraction.CustomPageSupplier { public class MemoriesPageSupplier implements OpenCustomUIInteraction.CustomPageSupplier {
@Nullable @Nullable
@Override @Override
public CustomUIPage tryCreate(Ref<EntityStore> ref, ComponentAccessor<EntityStore> componentAccessor, PlayerRef playerRef, InteractionContext context) { public CustomUIPage tryCreate(
return new MemoriesPage(playerRef, context.getTargetBlock()); @Nonnull Ref<EntityStore> ref,
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
@Nonnull PlayerRef playerRef,
@Nonnull InteractionContext context
) {
BlockPosition targetBlock = context.getTargetBlock();
return targetBlock == null ? null : new MemoriesPage(playerRef, targetBlock);
} }
} }

View File

@@ -51,11 +51,14 @@ public class MemoriesUnlockedPage extends InteractiveCustomUIPage<MemoriesUnlock
public static enum PageAction { public static enum PageAction {
DiscoverMemories; DiscoverMemories;
@Nonnull
public static final Codec<MemoriesUnlockedPage.PageAction> CODEC = new EnumCodec<>(MemoriesUnlockedPage.PageAction.class); public static final Codec<MemoriesUnlockedPage.PageAction> CODEC = new EnumCodec<>(MemoriesUnlockedPage.PageAction.class);
} }
public static class PageEventData { public static class PageEventData {
@Nonnull
public static final String KEY_ACTION = "Action"; public static final String KEY_ACTION = "Action";
@Nonnull
public static final BuilderCodec<MemoriesUnlockedPage.PageEventData> CODEC = BuilderCodec.builder( public static final BuilderCodec<MemoriesUnlockedPage.PageEventData> CODEC = BuilderCodec.builder(
MemoriesUnlockedPage.PageEventData.class, MemoriesUnlockedPage.PageEventData::new MemoriesUnlockedPage.PageEventData.class, MemoriesUnlockedPage.PageEventData::new
) )

View File

@@ -2,17 +2,25 @@ package com.hypixel.hytale.builtin.adventure.memories.page;
import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref; 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.InteractionContext;
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage; 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.modules.interaction.interaction.config.server.OpenCustomUIInteraction;
import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class MemoriesUnlockedPageSuplier implements OpenCustomUIInteraction.CustomPageSupplier { public class MemoriesUnlockedPageSuplier implements OpenCustomUIInteraction.CustomPageSupplier {
@Nullable @Nullable
@Override @Override
public CustomUIPage tryCreate(Ref<EntityStore> ref, ComponentAccessor<EntityStore> componentAccessor, PlayerRef playerRef, InteractionContext context) { public CustomUIPage tryCreate(
return new MemoriesUnlockedPage(playerRef, context.getTargetBlock()); @Nonnull Ref<EntityStore> ref,
@Nonnull ComponentAccessor<EntityStore> componentAccessor,
@Nonnull PlayerRef playerRef,
@Nonnull InteractionContext context
) {
BlockPosition targetBlock = context.getTargetBlock();
return targetBlock == null ? null : new MemoriesUnlockedPage(playerRef, targetBlock);
} }
} }

View File

@@ -4,8 +4,10 @@ import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent; import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
import javax.annotation.Nonnull;
public class ForgottenTempleConfig { public class ForgottenTempleConfig {
@Nonnull
public static final BuilderCodec<ForgottenTempleConfig> CODEC = BuilderCodec.builder(ForgottenTempleConfig.class, ForgottenTempleConfig::new) 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) .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.") .documentation("The Y at which players are teleported back to spawn.")

View File

@@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.adventure.memories.temple;
import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.query.Query;
@@ -18,13 +19,22 @@ import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.spawn.ISpawnProvider; import com.hypixel.hytale.server.core.universe.world.spawn.ISpawnProvider;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class TempleRespawnPlayersSystem extends DelayedEntitySystem<EntityStore> { public class TempleRespawnPlayersSystem extends DelayedEntitySystem<EntityStore> {
public static final Query<EntityStore> QUERY = Query.and(PlayerRef.getComponentType(), TransformComponent.getComponentType()); @Nonnull
private final ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
private final ComponentType<EntityStore, TransformComponent> transformComponentType;
@Nonnull
private final Query<EntityStore> query;
public TempleRespawnPlayersSystem() { public TempleRespawnPlayersSystem(
@Nonnull ComponentType<EntityStore, PlayerRef> playerRefComponentType, @Nonnull ComponentType<EntityStore, TransformComponent> transformComponentType
) {
super(1.0F); super(1.0F);
this.playerRefComponentType = playerRefComponentType;
this.transformComponentType = transformComponentType;
this.query = Query.and(playerRefComponentType, transformComponentType);
} }
@Override @Override
@@ -39,7 +49,7 @@ public class TempleRespawnPlayersSystem extends DelayedEntitySystem<EntityStore>
GameplayConfig gameplayConfig = world.getGameplayConfig(); GameplayConfig gameplayConfig = world.getGameplayConfig();
ForgottenTempleConfig config = gameplayConfig.getPluginConfig().get(ForgottenTempleConfig.class); ForgottenTempleConfig config = gameplayConfig.getPluginConfig().get(ForgottenTempleConfig.class);
if (config != null) { if (config != null) {
TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType()); TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType);
assert transformComponent != null; assert transformComponent != null;
@@ -50,15 +60,18 @@ public class TempleRespawnPlayersSystem extends DelayedEntitySystem<EntityStore>
Transform spawnTransform = spawnProvider.getSpawnPoint(ref, commandBuffer); Transform spawnTransform = spawnProvider.getSpawnPoint(ref, commandBuffer);
Teleport teleportComponent = Teleport.createForPlayer(null, spawnTransform); Teleport teleportComponent = Teleport.createForPlayer(null, spawnTransform);
commandBuffer.addComponent(ref, Teleport.getComponentType(), teleportComponent); commandBuffer.addComponent(ref, Teleport.getComponentType(), teleportComponent);
PlayerRef playerRef = archetypeChunk.getComponent(index, PlayerRef.getComponentType()); PlayerRef playerRefComponent = archetypeChunk.getComponent(index, this.playerRefComponentType);
SoundUtil.playSoundEvent2dToPlayer(playerRef, config.getRespawnSoundIndex(), SoundCategory.SFX);
assert playerRefComponent != null;
SoundUtil.playSoundEvent2dToPlayer(playerRefComponent, config.getRespawnSoundIndex(), SoundCategory.SFX);
} }
} }
} }
@Nullable @Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return QUERY; return this.query;
} }
} }

View File

@@ -21,6 +21,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class MemoriesWindow extends Window { public class MemoriesWindow extends Window {
@Nonnull
private final JsonObject windowData = new JsonObject(); private final JsonObject windowData = new JsonObject();
public MemoriesWindow() { public MemoriesWindow() {

View File

@@ -23,6 +23,8 @@ import com.hypixel.hytale.builtin.adventure.objectives.config.task.UseEntityObje
import com.hypixel.hytale.builtin.adventure.objectives.task.ObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.ObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask;
import com.hypixel.hytale.builtin.tagset.config.NPCGroup; import com.hypixel.hytale.builtin.tagset.config.NPCGroup;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.Store;
@@ -33,8 +35,10 @@ import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.npc.NPCPlugin; import com.hypixel.hytale.server.npc.NPCPlugin;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.server.spawning.assets.spawnmarker.config.SpawnMarker; import com.hypixel.hytale.server.spawning.assets.spawnmarker.config.SpawnMarker;
import com.hypixel.hytale.server.spawning.assets.spawns.config.BeaconNPCSpawn; import com.hypixel.hytale.server.spawning.assets.spawns.config.BeaconNPCSpawn;
import com.hypixel.hytale.server.spawning.beacons.LegacySpawnBeaconEntity;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@@ -56,45 +60,45 @@ public class NPCObjectivesPlugin extends JavaPlugin {
@Override @Override
protected void setup() { protected void setup() {
instance = this; instance = this;
ObjectivePlugin.get() ObjectivePlugin objectivePlugin = ObjectivePlugin.get();
.registerTask( ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
"KillSpawnBeacon", objectivePlugin.registerTask(
KillSpawnBeaconObjectiveTaskAsset.class, "KillSpawnBeacon",
KillSpawnBeaconObjectiveTaskAsset.CODEC, KillSpawnBeaconObjectiveTaskAsset.class,
KillSpawnBeaconObjectiveTask.class, KillSpawnBeaconObjectiveTaskAsset.CODEC,
KillSpawnBeaconObjectiveTask.CODEC, KillSpawnBeaconObjectiveTask.class,
KillSpawnBeaconObjectiveTask::new KillSpawnBeaconObjectiveTask.CODEC,
); KillSpawnBeaconObjectiveTask::new
ObjectivePlugin.get() );
.registerTask( objectivePlugin.registerTask(
"KillSpawnMarker", "KillSpawnMarker",
KillSpawnMarkerObjectiveTaskAsset.class, KillSpawnMarkerObjectiveTaskAsset.class,
KillSpawnMarkerObjectiveTaskAsset.CODEC, KillSpawnMarkerObjectiveTaskAsset.CODEC,
KillSpawnMarkerObjectiveTask.class, KillSpawnMarkerObjectiveTask.class,
KillSpawnMarkerObjectiveTask.CODEC, KillSpawnMarkerObjectiveTask.CODEC,
KillSpawnMarkerObjectiveTask::new KillSpawnMarkerObjectiveTask::new
); );
ObjectivePlugin.get() objectivePlugin.registerTask(
.registerTask( "Bounty",
"Bounty", BountyObjectiveTaskAsset.class,
BountyObjectiveTaskAsset.class, BountyObjectiveTaskAsset.CODEC,
BountyObjectiveTaskAsset.CODEC, BountyObjectiveTask.class,
BountyObjectiveTask.class, BountyObjectiveTask.CODEC,
BountyObjectiveTask.CODEC, BountyObjectiveTask::new
BountyObjectiveTask::new );
); objectivePlugin.registerTask(
ObjectivePlugin.get() "KillNPC",
.registerTask( KillObjectiveTaskAsset.class,
"KillNPC", KillObjectiveTaskAsset.CODEC,
KillObjectiveTaskAsset.class, KillNPCObjectiveTask.class,
KillObjectiveTaskAsset.CODEC, KillNPCObjectiveTask.CODEC,
KillNPCObjectiveTask.class, KillNPCObjectiveTask::new
KillNPCObjectiveTask.CODEC, );
KillNPCObjectiveTask::new this.killTrackerResourceType = entityStoreRegistry.registerResource(KillTrackerResource.class, KillTrackerResource::new);
); ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType = LegacySpawnBeaconEntity.getComponentType();
this.getEntityStoreRegistry().registerSystem(new SpawnBeaconCheckRemovalSystem()); ComponentType<EntityStore, NPCEntity> npcEntityComponentType = NPCEntity.getComponentType();
this.killTrackerResourceType = this.getEntityStoreRegistry().registerResource(KillTrackerResource.class, KillTrackerResource::new); entityStoreRegistry.registerSystem(new SpawnBeaconCheckRemovalSystem(legacySpawnBeaconEntityComponentType));
this.getEntityStoreRegistry().registerSystem(new KillTrackerSystem()); entityStoreRegistry.registerSystem(new KillTrackerSystem(npcEntityComponentType, this.killTrackerResourceType));
NPCPlugin.get() NPCPlugin.get()
.registerCoreComponentType("CompleteTask", BuilderActionCompleteTask::new) .registerCoreComponentType("CompleteTask", BuilderActionCompleteTask::new)
.registerCoreComponentType("StartObjective", BuilderActionStartObjective::new) .registerCoreComponentType("StartObjective", BuilderActionStartObjective::new)
@@ -114,48 +118,51 @@ public class NPCObjectivesPlugin extends JavaPlugin {
@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull UUID npcId, @Nonnull String taskId @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull UUID npcId, @Nonnull String taskId
) { ) {
UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType()); UUIDComponent uuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
if (uuidComponent == null) {
assert uuidComponent != null;
ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore();
Map<String, Set<UUID>> entityObjectiveUUIDs = objectiveDataStore.getEntityTasksForPlayer(uuidComponent.getUuid());
if (entityObjectiveUUIDs == null) {
return null; return null;
} else { } else {
Set<UUID> objectiveUUIDsForTaskId = entityObjectiveUUIDs.get(taskId); ObjectiveDataStore objectiveDataStore = ObjectivePlugin.get().getObjectiveDataStore();
if (objectiveUUIDsForTaskId == null) { Map<String, Set<UUID>> entityObjectiveUUIDs = objectiveDataStore.getEntityTasksForPlayer(uuidComponent.getUuid());
if (entityObjectiveUUIDs == null) {
return null; return null;
} else { } else {
for (UUID objectiveUUID : objectiveUUIDsForTaskId) { Set<UUID> objectiveUUIDsForTaskId = entityObjectiveUUIDs.get(taskId);
Objective objective = objectiveDataStore.getObjective(objectiveUUID); if (objectiveUUIDsForTaskId == null) {
if (objective != null) { return null;
for (ObjectiveTask task : objective.getCurrentTasks()) { } else {
if (task instanceof UseEntityObjectiveTask useEntityTask) { for (UUID objectiveUUID : objectiveUUIDsForTaskId) {
UseEntityObjectiveTaskAsset taskAsset = useEntityTask.getAsset(); Objective objective = objectiveDataStore.getObjective(objectiveUUID);
if (taskAsset.getTaskId().equals(taskId)) { if (objective != null) {
if (!useEntityTask.increaseTaskCompletion(store, ref, 1, objective, playerRef, npcId)) { ObjectiveTask[] currentTasks = objective.getCurrentTasks();
return null; 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) { public static void startObjective(@Nonnull Ref<EntityStore> playerRef, @Nonnull String taskId, @Nonnull Store<EntityStore> store) {
UUIDComponent uuidComponent = store.getComponent(playerReference, UUIDComponent.getComponentType()); UUIDComponent uuidComponent = store.getComponent(playerRef, UUIDComponent.getComponentType());
if (uuidComponent != null) {
assert uuidComponent != null; World world = store.getExternalData().getWorld();
ObjectivePlugin.get().startObjective(taskId, Set.of(uuidComponent.getUuid()), world.getWorldConfig().getUuid(), null, store);
World world = store.getExternalData().getWorld(); }
ObjectivePlugin.get().startObjective(taskId, Set.of(uuidComponent.getUuid()), world.getWorldConfig().getUuid(), null, store);
} }
public ResourceType<EntityStore, KillTrackerResource> getKillTrackerResourceType() { public ResourceType<EntityStore, KillTrackerResource> getKillTrackerResourceType() {

View File

@@ -12,6 +12,7 @@ import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class BountyObjectiveTaskAsset extends ObjectiveTaskAsset { public class BountyObjectiveTaskAsset extends ObjectiveTaskAsset {
@Nonnull
public static final BuilderCodec<BountyObjectiveTaskAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<BountyObjectiveTaskAsset> CODEC = BuilderCodec.builder(
BountyObjectiveTaskAsset.class, BountyObjectiveTaskAsset::new, ObjectiveTaskAsset.BASE_CODEC BountyObjectiveTaskAsset.class, BountyObjectiveTaskAsset::new, ObjectiveTaskAsset.BASE_CODEC
) )

View File

@@ -12,6 +12,7 @@ import com.hypixel.hytale.math.vector.Vector3i;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset { public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset {
@Nonnull
public static final BuilderCodec<KillObjectiveTaskAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillObjectiveTaskAsset> CODEC = BuilderCodec.builder(
KillObjectiveTaskAsset.class, KillObjectiveTaskAsset::new, CountObjectiveTaskAsset.CODEC KillObjectiveTaskAsset.class, KillObjectiveTaskAsset::new, CountObjectiveTaskAsset.CODEC
) )
@@ -45,7 +46,7 @@ public class KillObjectiveTaskAsset extends CountObjectiveTaskAsset {
if (!super.matchesAsset0(task)) { if (!super.matchesAsset0(task)) {
return false; return false;
} else { } else {
return !(task instanceof KillObjectiveTaskAsset) ? false : ((KillObjectiveTaskAsset)task).npcGroupId.equals(this.npcGroupId); return task instanceof KillObjectiveTaskAsset killObjectiveTaskAsset ? killObjectiveTaskAsset.npcGroupId.equals(this.npcGroupId) : false;
} }
} }

View File

@@ -16,6 +16,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset { public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
@Nonnull
public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset> CODEC = BuilderCodec.builder(
KillSpawnBeaconObjectiveTaskAsset.class, KillSpawnBeaconObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC KillSpawnBeaconObjectiveTaskAsset.class, KillSpawnBeaconObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC
) )
@@ -56,9 +57,9 @@ public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
if (!super.matchesAsset0(task)) { if (!super.matchesAsset0(task)) {
return false; return false;
} else { } else {
return !(task instanceof KillSpawnBeaconObjectiveTaskAsset) return task instanceof KillSpawnBeaconObjectiveTaskAsset killSpawnBeaconObjectiveTaskAsset
? false ? Arrays.equals((Object[])killSpawnBeaconObjectiveTaskAsset.spawnBeacons, (Object[])this.spawnBeacons)
: Arrays.equals((Object[])((KillSpawnBeaconObjectiveTaskAsset)task).spawnBeacons, (Object[])this.spawnBeacons); : false;
} }
} }
@@ -69,6 +70,7 @@ public class KillSpawnBeaconObjectiveTaskAsset extends KillObjectiveTaskAsset {
} }
public static class ObjectiveSpawnBeacon { public static class ObjectiveSpawnBeacon {
@Nonnull
public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon> CODEC = BuilderCodec.builder(
KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon.class, KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon::new KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon.class, KillSpawnBeaconObjectiveTaskAsset.ObjectiveSpawnBeacon::new
) )

View File

@@ -14,6 +14,7 @@ import java.util.Arrays;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class KillSpawnMarkerObjectiveTaskAsset extends KillObjectiveTaskAsset { public class KillSpawnMarkerObjectiveTaskAsset extends KillObjectiveTaskAsset {
@Nonnull
public static final BuilderCodec<KillSpawnMarkerObjectiveTaskAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillSpawnMarkerObjectiveTaskAsset> CODEC = BuilderCodec.builder(
KillSpawnMarkerObjectiveTaskAsset.class, KillSpawnMarkerObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC KillSpawnMarkerObjectiveTaskAsset.class, KillSpawnMarkerObjectiveTaskAsset::new, KillObjectiveTaskAsset.CODEC
) )

View File

@@ -25,41 +25,42 @@ public class ActionCompleteTask extends ActionPlayAnimation {
@Override @Override
public boolean canExecute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) { public boolean canExecute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) {
Ref<EntityStore> target = role.getStateSupport().getInteractionIterationTarget(); Ref<EntityStore> targetRef = role.getStateSupport().getInteractionIterationTarget();
boolean targetExists = target != null && !store.getArchetype(target).contains(DeathComponent.getComponentType()); boolean targetExists = targetRef != null && targetRef.isValid() && !store.getArchetype(targetRef).contains(DeathComponent.getComponentType());
return super.canExecute(ref, role, sensorInfo, dt, store) && targetExists; return super.canExecute(ref, role, sensorInfo, dt, store) && targetExists;
} }
@Override @Override
public boolean execute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) { 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()); UUIDComponent parentUuidComponent = store.getComponent(ref, UUIDComponent.getComponentType());
if (parentUuidComponent == null) {
assert parentUuidComponent != null;
Ref<EntityStore> targetPlayerReference = role.getStateSupport().getInteractionIterationTarget();
if (targetPlayerReference == null) {
return false; return false;
} else { } else {
PlayerRef targetPlayerRefComponent = store.getComponent(targetPlayerReference, PlayerRef.getComponentType()); Ref<EntityStore> targetPlayerReference = role.getStateSupport().getInteractionIterationTarget();
if (targetPlayerRefComponent == null) { if (targetPlayerReference == null) {
return false; return false;
} else { } else {
List<String> activeTasks = role.getEntitySupport().getTargetPlayerActiveTasks(); PlayerRef targetPlayerRefComponent = store.getComponent(targetPlayerReference, PlayerRef.getComponentType());
String animation = null; if (targetPlayerRefComponent == null) {
if (activeTasks != null) { return false;
for (int i = 0; i < activeTasks.size(); i++) { } else {
animation = NPCObjectivesPlugin.updateTaskCompletion( List<String> activeTasks = role.getEntitySupport().getTargetPlayerActiveTasks();
store, targetPlayerReference, targetPlayerRefComponent, parentUuidComponent.getUuid(), activeTasks.get(i) 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) { if (this.playAnimation && animation != null) {
this.setAnimationId(animation); this.setAnimationId(animation);
super.execute(ref, role, sensorInfo, dt, store); super.execute(ref, role, sensorInfo, dt, store);
} }
return true; return true;
}
} }
} }
} }

View File

@@ -27,7 +27,12 @@ public class ActionStartObjective extends ActionBase {
@Override @Override
public boolean execute(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, InfoProvider sensorInfo, double dt, @Nonnull Store<EntityStore> store) { 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); super.execute(ref, role, sensorInfo, dt, store);
NPCObjectivesPlugin.startObjective(role.getStateSupport().getInteractionIterationTarget(), this.objectiveId, store); Ref<EntityStore> interactionIterationTarget = role.getStateSupport().getInteractionIterationTarget();
return true; if (interactionIterationTarget == null) {
return false;
} else {
NPCObjectivesPlugin.startObjective(interactionIterationTarget, this.objectiveId, store);
return true;
}
} }
} }

View File

@@ -30,39 +30,42 @@ public class SensorHasTask extends SensorBase {
public boolean matches(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, double dt, @Nonnull Store<EntityStore> store) { public boolean matches(@Nonnull Ref<EntityStore> ref, @Nonnull Role role, double dt, @Nonnull Store<EntityStore> store) {
if (!super.matches(ref, role, dt, store)) { if (!super.matches(ref, role, dt, store)) {
return false; return false;
} else { } else if (this.tasksById != null && this.tasksById.length != 0) {
Ref<EntityStore> target = role.getStateSupport().getInteractionIterationTarget(); Ref<EntityStore> targetRef = role.getStateSupport().getInteractionIterationTarget();
if (target == null) { if (targetRef != null && targetRef.isValid()) {
return false; Archetype<EntityStore> targetArchetype = store.getArchetype(targetRef);
} else {
Archetype<EntityStore> targetArchetype = store.getArchetype(target);
if (targetArchetype.contains(DeathComponent.getComponentType())) { if (targetArchetype.contains(DeathComponent.getComponentType())) {
return false; return false;
} else { } 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(); return match;
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;
} }
} else {
return false;
} }
} else {
return false;
} }
} }

View File

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

View File

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

View File

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

View File

@@ -6,6 +6,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ObjectiveExistsValidator extends AssetValidator { public class ObjectiveExistsValidator extends AssetValidator {
@Nonnull
private static final ObjectiveExistsValidator DEFAULT_INSTANCE = new ObjectiveExistsValidator(); private static final ObjectiveExistsValidator DEFAULT_INSTANCE = new ObjectiveExistsValidator();
private ObjectiveExistsValidator() { private ObjectiveExistsValidator() {
@@ -38,6 +39,7 @@ public class ObjectiveExistsValidator extends AssetValidator {
return ObjectiveAsset.class.getSimpleName(); return ObjectiveAsset.class.getSimpleName();
} }
@Nonnull
public static ObjectiveExistsValidator required() { public static ObjectiveExistsValidator required() {
return DEFAULT_INSTANCE; return DEFAULT_INSTANCE;
} }

View File

@@ -10,17 +10,18 @@ import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class KillTrackerResource implements Resource<EntityStore> { public class KillTrackerResource implements Resource<EntityStore> {
@Nonnull
private final List<KillTaskTransaction> killTasks = new ObjectArrayList<>(); private final List<KillTaskTransaction> killTasks = new ObjectArrayList<>();
public static ResourceType<EntityStore, KillTrackerResource> getResourceType() { public static ResourceType<EntityStore, KillTrackerResource> getResourceType() {
return NPCObjectivesPlugin.get().getKillTrackerResourceType(); return NPCObjectivesPlugin.get().getKillTrackerResourceType();
} }
public void watch(KillTaskTransaction task) { public void watch(@Nonnull KillTaskTransaction task) {
this.killTasks.add(task); this.killTasks.add(task);
} }
public void unwatch(KillTaskTransaction task) { public void unwatch(@Nonnull KillTaskTransaction task) {
this.killTasks.remove(task); this.killTasks.remove(task);
} }

View File

@@ -3,35 +3,55 @@ package com.hypixel.hytale.builtin.adventure.npcobjectives.systems;
import com.hypixel.hytale.builtin.adventure.npcobjectives.resources.KillTrackerResource; import com.hypixel.hytale.builtin.adventure.npcobjectives.resources.KillTrackerResource;
import com.hypixel.hytale.builtin.adventure.npcobjectives.transaction.KillTaskTransaction; import com.hypixel.hytale.builtin.adventure.npcobjectives.transaction.KillTaskTransaction;
import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Query; 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.DeathComponent;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems; import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.entities.NPCEntity;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class KillTrackerSystem extends DeathSystems.OnDeathSystem { public class KillTrackerSystem extends DeathSystems.OnDeathSystem {
@Nullable @Nonnull
private final ComponentType<EntityStore, NPCEntity> npcEntityComponentType;
@Nonnull
private final ResourceType<EntityStore, KillTrackerResource> killTrackerResourceType;
public KillTrackerSystem(
@Nonnull ComponentType<EntityStore, NPCEntity> npcEntityComponentType, @Nonnull ResourceType<EntityStore, KillTrackerResource> killTrackerResourceType
) {
this.npcEntityComponentType = npcEntityComponentType;
this.killTrackerResourceType = killTrackerResourceType;
}
@Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return NPCEntity.getComponentType(); return this.npcEntityComponentType;
} }
public void onComponentAdded( public void onComponentAdded(
@Nonnull Ref<EntityStore> ref, @Nonnull DeathComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer @Nonnull Ref<EntityStore> ref, @Nonnull DeathComponent component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer
) { ) {
NPCEntity entity = store.getComponent(ref, NPCEntity.getComponentType()); NPCEntity npcEntityComponent = store.getComponent(ref, this.npcEntityComponentType);
KillTrackerResource tracker = store.getResource(KillTrackerResource.getResourceType());
List<KillTaskTransaction> killTasks = tracker.getKillTasks();
int size = killTasks.size();
for (int i = size - 1; i >= 0; i--) { assert npcEntityComponent != null;
KillTaskTransaction entry = killTasks.get(i);
entry.getTask().checkKilledEntity(store, ref, entry.getObjective(), entity, component.getDeathInfo()); KillTrackerResource killTrackerResource = store.getResource(this.killTrackerResourceType);
List<KillTaskTransaction> killTasks = killTrackerResource.getKillTasks();
Damage deathInfo = component.getDeathInfo();
if (deathInfo != null) {
int size = killTasks.size();
for (int i = size - 1; i >= 0; i--) {
KillTaskTransaction entry = killTasks.get(i);
entry.getTask().checkKilledEntity(store, ref, entry.getObjective(), npcEntityComponent, deathInfo);
}
} }
} }
} }

View File

@@ -2,6 +2,7 @@ package com.hypixel.hytale.builtin.adventure.npcobjectives.systems;
import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin; import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin;
import com.hypixel.hytale.component.AddReason; import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder; import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.RemoveReason; import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.Store;
@@ -11,18 +12,24 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.spawning.beacons.LegacySpawnBeaconEntity; import com.hypixel.hytale.server.spawning.beacons.LegacySpawnBeaconEntity;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class SpawnBeaconCheckRemovalSystem extends HolderSystem<EntityStore> { public class SpawnBeaconCheckRemovalSystem extends HolderSystem<EntityStore> {
@Nullable @Nonnull
private final ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType;
public SpawnBeaconCheckRemovalSystem(@Nonnull ComponentType<EntityStore, LegacySpawnBeaconEntity> legacySpawnBeaconEntityComponentType) {
this.legacySpawnBeaconEntityComponentType = legacySpawnBeaconEntityComponentType;
}
@Nonnull
@Override @Override
public Query<EntityStore> getQuery() { public Query<EntityStore> getQuery() {
return LegacySpawnBeaconEntity.getComponentType(); return this.legacySpawnBeaconEntityComponentType;
} }
@Override @Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) { public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(LegacySpawnBeaconEntity.getComponentType()); LegacySpawnBeaconEntity spawnBeaconComponent = holder.getComponent(this.legacySpawnBeaconEntityComponentType);
assert spawnBeaconComponent != null; assert spawnBeaconComponent != null;

View File

@@ -6,6 +6,7 @@ import com.hypixel.hytale.builtin.adventure.npcobjectives.transaction.KillTaskTr
import com.hypixel.hytale.builtin.adventure.objectives.Objective; import com.hypixel.hytale.builtin.adventure.objectives.Objective;
import com.hypixel.hytale.builtin.adventure.objectives.ObjectivePlugin; 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.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.task.ObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.transaction.RegistrationTransactionRecord; import com.hypixel.hytale.builtin.adventure.objectives.transaction.RegistrationTransactionRecord;
import com.hypixel.hytale.builtin.adventure.objectives.transaction.SpawnEntityTransactionRecord; 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.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store; 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.Transform;
import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3i; 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.entity.UUIDComponent;
import com.hypixel.hytale.server.core.modules.entity.damage.Damage; 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.World;
import com.hypixel.hytale.server.core.universe.world.npc.INonPlayerCharacter; 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.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.NPCPlugin;
import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.entities.NPCEntity;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BountyObjectiveTask extends ObjectiveTask implements KillTask { public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
@Nonnull
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
@Nonnull
public static final BuilderCodec<BountyObjectiveTask> CODEC = BuilderCodec.builder( public static final BuilderCodec<BountyObjectiveTask> CODEC = BuilderCodec.builder(
BountyObjectiveTask.class, BountyObjectiveTask::new, ObjectiveTask.BASE_CODEC BountyObjectiveTask.class, BountyObjectiveTask::new, ObjectiveTask.BASE_CODEC
) )
@@ -65,36 +70,47 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
return (BountyObjectiveTaskAsset)super.getAsset(); return (BountyObjectiveTaskAsset)super.getAsset();
} }
@Nonnull @Nullable
@Override @Override
protected TransactionRecord[] setup0(@Nonnull Objective objective, @Nonnull World world, @Nonnull Store<EntityStore> store) { protected TransactionRecord[] setup0(@Nonnull Objective objective, @Nonnull World world, @Nonnull Store<EntityStore> store) {
if (this.serializedTransactionRecords != null) { if (this.serializedTransactionRecords != null) {
return RegistrationTransactionRecord.append(this.serializedTransactionRecords, this.eventRegistry); return RegistrationTransactionRecord.append(this.serializedTransactionRecords, this.eventRegistry);
} else { } else {
Vector3d objectivePosition = objective.getPosition(store); Vector3d objectivePosition = objective.getPosition(store);
if (objectivePosition == null) {
assert objectivePosition != null; return null;
} else {
Vector3i spawnPosition = this.getAsset().getWorldLocationProvider().runCondition(world, objectivePosition.clone().floor().toVector3i()); Vector3i spawnPosition = this.getAsset().getWorldLocationProvider().runCondition(world, objectivePosition.clone().floor().toVector3i());
TransactionRecord[] transactionRecords = new TransactionRecord[2]; if (spawnPosition == null) {
Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair = NPCPlugin.get() return null;
.spawnNPC(store, this.getAsset().getNpcId(), null, spawnPosition.toVector3d(), Vector3f.ZERO); } else {
Ref<EntityStore> npcReference = npcPair.first(); TransactionRecord[] transactionRecords = new TransactionRecord[2];
UUIDComponent npcUuidComponent = store.getComponent(npcReference, UUIDComponent.getComponentType()); String npcId = this.getAsset().getNpcId();
Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair = NPCPlugin.get().spawnNPC(store, npcId, null, spawnPosition.toVector3d(), Vector3f.ZERO);
assert npcUuidComponent != null; if (npcPair == null) {
return null;
UUID npcUuid = npcUuidComponent.getUuid(); } else {
ObjectivePlugin.get().getLogger().at(Level.INFO).log("Spawned Entity '" + this.getAsset().getNpcId() + "' at position: " + spawnPosition); Ref<EntityStore> npcReference = npcPair.first();
transactionRecords[0] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), npcUuid); UUIDComponent npcUuidComponent = store.getComponent(npcReference, UUIDComponent.getComponentType());
this.entityUuid = npcUuid; if (npcUuidComponent == null) {
this.addMarker( return null;
new MapMarker(getBountyMarkerIDFromUUID(npcUuid), "Bounty Target", "Home.png", PositionUtil.toTransformPacket(new Transform(spawnPosition)), null) } else {
); UUID npcUuid = npcUuidComponent.getUuid();
KillTaskTransaction transaction = new KillTaskTransaction(this, objective, store); ObjectivePlugin.get().getLogger().at(Level.INFO).log("Spawned Entity '" + npcId + "' at position: " + spawnPosition);
store.getResource(KillTrackerResource.getResourceType()).watch(transaction); transactionRecords[0] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), npcUuid);
transactionRecords[1] = transaction; this.entityUuid = npcUuid;
return transactionRecords; 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 @Override
public void checkKilledEntity( 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()); UUIDComponent uuidComponent = store.getComponent(npcRef, UUIDComponent.getComponentType());
@@ -129,7 +145,8 @@ public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
@Nonnull @Nonnull
public com.hypixel.hytale.protocol.ObjectiveTask toPacket(@Nonnull Objective objective) { public com.hypixel.hytale.protocol.ObjectiveTask toPacket(@Nonnull Objective objective) {
com.hypixel.hytale.protocol.ObjectiveTask packet = new com.hypixel.hytale.protocol.ObjectiveTask(); 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.currentCompletion = this.completed ? 1 : 0;
packet.completionNeeded = 1; packet.completionNeeded = 1;
return packet; return packet;

View File

@@ -12,6 +12,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class KillNPCObjectiveTask extends KillObjectiveTask { public class KillNPCObjectiveTask extends KillObjectiveTask {
@Nonnull
public static final BuilderCodec<KillNPCObjectiveTask> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillNPCObjectiveTask> CODEC = BuilderCodec.builder(
KillNPCObjectiveTask.class, KillNPCObjectiveTask::new, KillObjectiveTask.CODEC KillNPCObjectiveTask.class, KillNPCObjectiveTask::new, KillObjectiveTask.CODEC
) )

View File

@@ -8,8 +8,6 @@ import com.hypixel.hytale.builtin.tagset.config.NPCGroup;
import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store; 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.UUIDComponent;
import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.modules.entity.damage.Damage; 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; import javax.annotation.Nonnull;
public abstract class KillObjectiveTask extends CountObjectiveTask implements KillTask { public abstract class KillObjectiveTask extends CountObjectiveTask implements KillTask {
@Nonnull
public static final BuilderCodec<KillObjectiveTask> CODEC = BuilderCodec.abstractBuilder(KillObjectiveTask.class, CountObjectiveTask.CODEC).build(); public static final BuilderCodec<KillObjectiveTask> CODEC = BuilderCodec.abstractBuilder(KillObjectiveTask.class, CountObjectiveTask.CODEC).build();
public KillObjectiveTask(@Nonnull KillObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) { 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) { if (index == Integer.MIN_VALUE) {
throw new IllegalArgumentException("Unknown npc group! " + key); throw new IllegalArgumentException("Unknown npc group! " + key);
} else if (TagSetPlugin.get(NPCGroup.class).tagInSet(index, npc.getNPCTypeIndex())) { } else if (TagSetPlugin.get(NPCGroup.class).tagInSet(index, npc.getNPCTypeIndex())) {
if (info.getSource() instanceof Damage.EntitySource) { if (info.getSource() instanceof Damage.EntitySource entitySource) {
Ref<EntityStore> attackerEntityRef = ((Damage.EntitySource)info.getSource()).getRef(); Ref var11 = entitySource.getRef();
Entity attackerEntity = EntityUtils.getEntity(attackerEntityRef, attackerEntityRef.getStore()); if (store.getArchetype(var11).contains(Player.getComponentType())) {
if (attackerEntity instanceof Player) { UUIDComponent sourceUuidComponent = store.getComponent(var11, UUIDComponent.getComponentType());
UUIDComponent attackerUuidComponent = store.getComponent(attackerEntityRef, UUIDComponent.getComponentType()); if (sourceUuidComponent != null) {
if (objective.getActivePlayerUUIDs().contains(sourceUuidComponent.getUuid())) {
assert attackerUuidComponent != null; this.increaseTaskCompletion(store, npcRef, 1, objective);
}
if (objective.getActivePlayerUUIDs().contains(attackerUuidComponent.getUuid())) {
this.increaseTaskCompletion(store, npcRef, 1, objective);
} }
} }
} }

View File

@@ -18,6 +18,7 @@ import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f; 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.entity.UUIDComponent;
import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
@@ -31,6 +32,7 @@ import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask { public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
@Nonnull
public static final BuilderCodec<KillSpawnBeaconObjectiveTask> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillSpawnBeaconObjectiveTask> CODEC = BuilderCodec.builder(
KillSpawnBeaconObjectiveTask.class, KillSpawnBeaconObjectiveTask::new, KillObjectiveTask.CODEC KillSpawnBeaconObjectiveTask.class, KillSpawnBeaconObjectiveTask::new, KillObjectiveTask.CODEC
) )
@@ -91,7 +93,12 @@ public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
WorldLocationProvider worldLocationCondition = spawnBeaconConfig.getWorldLocationProvider(); WorldLocationProvider worldLocationCondition = spawnBeaconConfig.getWorldLocationProvider();
if (worldLocationCondition != null) { 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) { if (spawnPosition == null) {
@@ -103,11 +110,12 @@ public class KillSpawnBeaconObjectiveTask extends KillObjectiveTask {
); );
spawnBeaconPair.second().setObjectiveUUID(objective.getObjectiveUUID()); spawnBeaconPair.second().setObjectiveUUID(objective.getObjectiveUUID());
UUIDComponent spawnBeaconUuidComponent = componentAccessor.getComponent(spawnBeaconPair.first(), UUIDComponent.getComponentType()); UUIDComponent spawnBeaconUuidComponent = componentAccessor.getComponent(spawnBeaconPair.first(), UUIDComponent.getComponentType());
if (spawnBeaconUuidComponent == null) {
assert 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); logger.at(Level.INFO).log("Spawned SpawnBeacon '" + spawnBeaconId + "' at position: " + position);
transactionRecords[i] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), spawnBeaconUuidComponent.getUuid()); transactionRecords[i] = new SpawnEntityTransactionRecord(world.getWorldConfig().getUuid(), spawnBeaconUuidComponent.getUuid());
}
} }
} }

View File

@@ -24,11 +24,13 @@ import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask { public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask {
@Nonnull
public static final BuilderCodec<KillSpawnMarkerObjectiveTask> CODEC = BuilderCodec.builder( public static final BuilderCodec<KillSpawnMarkerObjectiveTask> CODEC = BuilderCodec.builder(
KillSpawnMarkerObjectiveTask.class, KillSpawnMarkerObjectiveTask::new, KillObjectiveTask.CODEC KillSpawnMarkerObjectiveTask.class, KillSpawnMarkerObjectiveTask::new, KillObjectiveTask.CODEC
) )
.build(); .build();
private static final ComponentType<EntityStore, SpawnMarkerEntity> SPAWN_MARKER_COMPONENT_TYPE = SpawnMarkerEntity.getComponentType(); private static final ComponentType<EntityStore, SpawnMarkerEntity> SPAWN_MARKER_COMPONENT_TYPE = SpawnMarkerEntity.getComponentType();
@Nonnull
private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType(); private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
public KillSpawnMarkerObjectiveTask(@Nonnull KillSpawnMarkerObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) { public KillSpawnMarkerObjectiveTask(@Nonnull KillSpawnMarkerObjectiveTaskAsset asset, int taskSetIndex, int taskIndex) {
@@ -55,21 +57,17 @@ public class KillSpawnMarkerObjectiveTask extends KillObjectiveTask {
String[] spawnMarkerIds = asset.getSpawnMarkerIds(); String[] spawnMarkerIds = asset.getSpawnMarkerIds();
HytaleLogger logger = ObjectivePlugin.get().getLogger(); HytaleLogger logger = ObjectivePlugin.get().getLogger();
for (Ref<EntityStore> entityReference : results) { for (Ref<EntityStore> ref : results) {
SpawnMarkerEntity entitySpawnMarkerComponent = store.getComponent(entityReference, SPAWN_MARKER_COMPONENT_TYPE); SpawnMarkerEntity entitySpawnMarkerComponent = store.getComponent(ref, SPAWN_MARKER_COMPONENT_TYPE);
if (entitySpawnMarkerComponent != null) {
assert entitySpawnMarkerComponent != null; String spawnMarkerId = entitySpawnMarkerComponent.getSpawnMarkerId();
if (ArrayUtil.contains(spawnMarkerIds, spawnMarkerId)) {
String spawnMarkerId = entitySpawnMarkerComponent.getSpawnMarkerId(); world.execute(() -> entitySpawnMarkerComponent.trigger(ref, store));
if (ArrayUtil.contains(spawnMarkerIds, spawnMarkerId)) { TransformComponent transformComponent = store.getComponent(ref, TRANSFORM_COMPONENT_TYPE);
world.execute(() -> entitySpawnMarkerComponent.trigger(entityReference, store)); if (transformComponent != null) {
logger.at(Level.INFO) logger.at(Level.INFO).log("Triggered SpawnMarker '" + spawnMarkerId + "' at position: " + transformComponent.getPosition());
.log( }
"Triggered SpawnMarker '" }
+ spawnMarkerId
+ "' at position: "
+ store.getComponent(entityReference, TRANSFORM_COMPONENT_TYPE).getPosition()
);
} }
} }
} }

View File

@@ -6,7 +6,10 @@ import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.modules.entity.damage.Damage; import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.entities.NPCEntity;
import javax.annotation.Nonnull;
public interface KillTask { public interface KillTask {
void checkKilledEntity(Store<EntityStore> var1, Ref<EntityStore> var2, Objective var3, NPCEntity var4, Damage var5); void checkKilledEntity(
@Nonnull Store<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull Objective var3, @Nonnull NPCEntity var4, @Nonnull Damage var5
);
} }

View File

@@ -17,13 +17,16 @@ import java.util.Map.Entry;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class NPCReputationHolderSystem extends HolderSystem<EntityStore> { public class NPCReputationHolderSystem extends HolderSystem<EntityStore> {
@Nonnull
private final ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType; private final ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType;
@Nonnull
private final ComponentType<EntityStore, NPCEntity> npcEntityComponentType; private final ComponentType<EntityStore, NPCEntity> npcEntityComponentType;
@Nonnull @Nonnull
private final Query<EntityStore> query; private final Query<EntityStore> query;
public NPCReputationHolderSystem( public NPCReputationHolderSystem(
ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType, ComponentType<EntityStore, NPCEntity> npcEntityComponentType @Nonnull ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType,
@Nonnull ComponentType<EntityStore, NPCEntity> npcEntityComponentType
) { ) {
this.reputationGroupComponentType = reputationGroupComponentType; this.reputationGroupComponentType = reputationGroupComponentType;
this.npcEntityComponentType = npcEntityComponentType; this.npcEntityComponentType = npcEntityComponentType;
@@ -38,8 +41,11 @@ public class NPCReputationHolderSystem extends HolderSystem<EntityStore> {
@Override @Override
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) { public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
NPCEntity npcEntity = holder.getComponent(this.npcEntityComponentType); NPCEntity npcComponent = holder.getComponent(this.npcEntityComponentType);
int npcTypeIndex = npcEntity.getNPCTypeIndex();
assert npcComponent != null;
int npcTypeIndex = npcComponent.getNPCTypeIndex();
for (Entry<String, ReputationGroup> reputationEntry : ReputationGroup.getAssetMap().getAssetMap().entrySet()) { for (Entry<String, ReputationGroup> reputationEntry : ReputationGroup.getAssetMap().getAssetMap().entrySet()) {
for (String npcGroup : reputationEntry.getValue().getNpcGroups()) { for (String npcGroup : reputationEntry.getValue().getNpcGroups()) {

View File

@@ -1,8 +1,14 @@
package com.hypixel.hytale.builtin.adventure.npcreputation; package com.hypixel.hytale.builtin.adventure.npcreputation;
import com.hypixel.hytale.builtin.adventure.reputation.ReputationGroupComponent; import com.hypixel.hytale.builtin.adventure.reputation.ReputationGroupComponent;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.npc.blackboard.Blackboard;
import com.hypixel.hytale.server.npc.entities.NPCEntity; import com.hypixel.hytale.server.npc.entities.NPCEntity;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -13,7 +19,12 @@ public class NPCReputationPlugin extends JavaPlugin {
@Override @Override
protected void setup() { protected void setup() {
this.getEntityStoreRegistry().registerSystem(new ReputationAttitudeSystem()); ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
this.getEntityStoreRegistry().registerSystem(new NPCReputationHolderSystem(ReputationGroupComponent.getComponentType(), NPCEntity.getComponentType())); ResourceType<EntityStore, Blackboard> blackboardResourceType = Blackboard.getResourceType();
ComponentType<EntityStore, Player> playerComponentType = Player.getComponentType();
ComponentType<EntityStore, ReputationGroupComponent> reputationGroupComponentType = ReputationGroupComponent.getComponentType();
ComponentType<EntityStore, NPCEntity> npcEntityComponentType = NPCEntity.getComponentType();
entityStoreRegistry.registerSystem(new ReputationAttitudeSystem(blackboardResourceType, playerComponentType));
entityStoreRegistry.registerSystem(new NPCReputationHolderSystem(reputationGroupComponentType, npcEntityComponentType));
} }
} }

View File

@@ -1,6 +1,7 @@
package com.hypixel.hytale.builtin.adventure.npcreputation; package com.hypixel.hytale.builtin.adventure.npcreputation;
import com.hypixel.hytale.builtin.adventure.reputation.ReputationPlugin; import com.hypixel.hytale.builtin.adventure.reputation.ReputationPlugin;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.system.StoreSystem; import com.hypixel.hytale.component.system.StoreSystem;
@@ -11,14 +12,24 @@ import com.hypixel.hytale.server.npc.blackboard.view.attitude.AttitudeView;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ReputationAttitudeSystem extends StoreSystem<EntityStore> { public class ReputationAttitudeSystem extends StoreSystem<EntityStore> {
private final ResourceType<EntityStore, Blackboard> resourceType = Blackboard.getResourceType(); @Nonnull
private final ResourceType<EntityStore, Blackboard> blackboardResourceType;
@Nonnull
private final ComponentType<EntityStore, Player> playerComponentType;
public ReputationAttitudeSystem(
@Nonnull ResourceType<EntityStore, Blackboard> blackboardResourceType, @Nonnull ComponentType<EntityStore, Player> playerComponentType
) {
this.blackboardResourceType = blackboardResourceType;
this.playerComponentType = playerComponentType;
}
@Override @Override
public void onSystemAddedToStore(@Nonnull Store<EntityStore> store) { public void onSystemAddedToStore(@Nonnull Store<EntityStore> store) {
Blackboard blackboard = store.getResource(this.resourceType); Blackboard blackboardResource = store.getResource(this.blackboardResourceType);
AttitudeView view = blackboard.getView(AttitudeView.class, 0L); AttitudeView attitudeView = blackboardResource.getView(AttitudeView.class, 0L);
view.registerProvider(100, (ref, role, targetRef, accessor) -> { attitudeView.registerProvider(100, (ref, role, targetRef, accessor) -> {
Player playerComponent = store.getComponent(targetRef, Player.getComponentType()); Player playerComponent = store.getComponent(targetRef, this.playerComponentType);
return playerComponent == null ? null : ReputationPlugin.get().getAttitude(store, targetRef, ref); return playerComponent == null ? null : ReputationPlugin.get().getAttitude(store, targetRef, ref);
}); });
} }

View File

@@ -14,6 +14,7 @@ import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ActionOpenBarterShop extends ActionBase { public class ActionOpenBarterShop extends ActionBase {
@Nonnull
protected final String shopId; protected final String shopId;
public ActionOpenBarterShop(@Nonnull BuilderActionOpenBarterShop builder, @Nonnull BuilderSupport support) { public ActionOpenBarterShop(@Nonnull BuilderActionOpenBarterShop builder, @Nonnull BuilderSupport support) {

View File

@@ -14,6 +14,7 @@ import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ActionOpenShop extends ActionBase { public class ActionOpenShop extends ActionBase {
@Nonnull
protected final String shopId; protected final String shopId;
public ActionOpenShop(@Nonnull BuilderActionOpenShop builder, @Nonnull BuilderSupport support) { public ActionOpenShop(@Nonnull BuilderActionOpenShop builder, @Nonnull BuilderSupport support) {
@@ -34,15 +35,17 @@ public class ActionOpenShop extends ActionBase {
return false; return false;
} else { } else {
PlayerRef playerRefComponent = store.getComponent(playerReference, PlayerRef.getComponentType()); PlayerRef playerRefComponent = store.getComponent(playerReference, PlayerRef.getComponentType());
if (playerRefComponent == null) {
assert playerRefComponent != null; return false;
} else {
Player playerComponent = store.getComponent(playerReference, Player.getComponentType()); Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
if (playerComponent == null) {
assert playerComponent != null; return false;
} else {
playerComponent.getPageManager().openCustomPage(ref, store, new ShopPage(playerRefComponent, this.shopId)); playerComponent.getPageManager().openCustomPage(ref, store, new ShopPage(playerRefComponent, this.shopId));
return true; return true;
}
}
} }
} }
} }

View File

@@ -6,6 +6,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class BarterShopExistsValidator extends AssetValidator { public class BarterShopExistsValidator extends AssetValidator {
@Nonnull
private static final BarterShopExistsValidator DEFAULT_INSTANCE = new BarterShopExistsValidator(); private static final BarterShopExistsValidator DEFAULT_INSTANCE = new BarterShopExistsValidator();
private BarterShopExistsValidator() { private BarterShopExistsValidator() {

View File

@@ -6,6 +6,7 @@ import java.util.EnumSet;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ShopExistsValidator extends AssetValidator { public class ShopExistsValidator extends AssetValidator {
@Nonnull
private static final ShopExistsValidator DEFAULT_INSTANCE = new ShopExistsValidator(); private static final ShopExistsValidator DEFAULT_INSTANCE = new ShopExistsValidator();
private ShopExistsValidator() { private ShopExistsValidator() {

View File

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

View File

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

View File

@@ -28,8 +28,9 @@ public class ReputationCompletion extends ObjectiveCompletion {
Player playerComponent = componentAccessor.getComponent(participantReference, Player.getComponentType()); Player playerComponent = componentAccessor.getComponent(participantReference, Player.getComponentType());
if (playerComponent != null) { if (playerComponent != null) {
UUIDComponent uuidComponent = componentAccessor.getComponent(participantReference, UUIDComponent.getComponentType()); UUIDComponent uuidComponent = componentAccessor.getComponent(participantReference, UUIDComponent.getComponentType());
if (uuidComponent == null) {
assert uuidComponent != null; return;
}
String reputationGroupId = asset.getReputationGroupId(); String reputationGroupId = asset.getReputationGroupId();
int amount = asset.getAmount(); int amount = asset.getAmount();

View File

@@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ReputationCompletionAsset extends ObjectiveCompletionAsset { public class ReputationCompletionAsset extends ObjectiveCompletionAsset {
@Nonnull
public static final BuilderCodec<ReputationCompletionAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<ReputationCompletionAsset> CODEC = BuilderCodec.builder(
ReputationCompletionAsset.class, ReputationCompletionAsset::new, ObjectiveCompletionAsset.BASE_CODEC ReputationCompletionAsset.class, ReputationCompletionAsset::new, ObjectiveCompletionAsset.BASE_CODEC
) )

View File

@@ -9,6 +9,7 @@ import com.hypixel.hytale.codec.validation.Validators;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public final class ReputationObjectiveRewardHistoryData extends ObjectiveRewardHistoryData { public final class ReputationObjectiveRewardHistoryData extends ObjectiveRewardHistoryData {
@Nonnull
public static final BuilderCodec<ReputationObjectiveRewardHistoryData> CODEC = BuilderCodec.builder( public static final BuilderCodec<ReputationObjectiveRewardHistoryData> CODEC = BuilderCodec.builder(
ReputationObjectiveRewardHistoryData.class, ReputationObjectiveRewardHistoryData::new, ObjectiveRewardHistoryData.BASE_CODEC ReputationObjectiveRewardHistoryData.class, ReputationObjectiveRewardHistoryData::new, ObjectiveRewardHistoryData.BASE_CODEC
) )

View File

@@ -17,6 +17,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class DialogPage extends InteractiveCustomUIPage<DialogPage.DialogPageEventData> { public class DialogPage extends InteractiveCustomUIPage<DialogPage.DialogPageEventData> {
@Nonnull
public static final String LAYOUT = "Pages/DialogPage.ui"; public static final String LAYOUT = "Pages/DialogPage.ui";
private final UseEntityObjectiveTaskAsset.DialogOptions dialogOptions; 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) { public void handleDataEvent(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull DialogPage.DialogPageEventData data) {
Player playerComponent = store.getComponent(ref, Player.getComponentType()); 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 { public static class DialogPageEventData {
@Nonnull
public static final BuilderCodec<DialogPage.DialogPageEventData> CODEC = BuilderCodec.builder( public static final BuilderCodec<DialogPage.DialogPageEventData> CODEC = BuilderCodec.builder(
DialogPage.DialogPageEventData.class, DialogPage.DialogPageEventData::new DialogPage.DialogPageEventData.class, DialogPage.DialogPageEventData::new
) )

View File

@@ -43,6 +43,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class Objective implements NetworkSerializable<com.hypixel.hytale.protocol.Objective> { public class Objective implements NetworkSerializable<com.hypixel.hytale.protocol.Objective> {
@Nonnull
public static final BuilderCodec<Objective> CODEC = BuilderCodec.builder(Objective.class, Objective::new) 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) .append(new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY), (objective, uuid) -> objective.objectiveUUID = uuid, objective -> objective.objectiveUUID)
.add() .add()
@@ -225,39 +226,47 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
} }
public boolean setupCurrentTasks(@Nonnull Store<EntityStore> store) { public boolean setupCurrentTasks(@Nonnull Store<EntityStore> store) {
for (ObjectiveTask task : this.currentTasks) { if (this.currentTasks == null) {
if (!task.isComplete()) { return false;
TransactionRecord[] taskTransactions = task.setup(this, store); } else {
if (taskTransactions != null && TransactionUtil.anyFailed(taskTransactions)) { for (ObjectiveTask task : this.currentTasks) {
ObjectivePlugin.get() if (!task.isComplete()) {
.getLogger() TransactionRecord[] taskTransactions = task.setup(this, store);
.at(Level.WARNING) if (taskTransactions != null && TransactionUtil.anyFailed(taskTransactions)) {
.log("Failed to setup objective tasks, transaction records:%s", Arrays.toString((Object[])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) { for (ObjectiveTask taskSetup : this.currentTasks) {
taskSetup.revertTransactionRecords(); taskSetup.revertTransactionRecords();
if (taskSetup == task) { if (taskSetup == task) {
break; break;
}
} }
}
return false; return false;
}
} }
} }
}
return true; return true;
}
} }
public boolean checkTaskSetCompletion(@Nonnull Store<EntityStore> store) { public boolean checkTaskSetCompletion(@Nonnull Store<EntityStore> store) {
for (ObjectiveTask task : this.currentTasks) { if (this.currentTasks == null) {
if (!task.isComplete()) { return false;
return false; } else {
for (ObjectiveTask task : this.currentTasks) {
if (!task.isComplete()) {
return false;
}
} }
}
this.taskSetComplete(store); this.taskSetComplete(store);
return true; return true;
}
} }
protected void taskSetComplete(@Nonnull Store<EntityStore> store) { protected void taskSetComplete(@Nonnull Store<EntityStore> store) {
@@ -269,13 +278,12 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
this.taskSetComplete(store); this.taskSetComplete(store);
} else { } else {
TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(this.toPacket()); TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(this.toPacket());
this.forEachParticipant((participantReference, message, trackOrUpdateObjective) -> { this.forEachParticipant((participantReference, trackOrUpdateObjective) -> {
PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType()); PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
if (playerRefComponent != null) { if (playerRefComponent != null) {
playerRefComponent.sendMessage(message);
playerRefComponent.getPacketHandler().writeNoCache(trackOrUpdateObjective); playerRefComponent.getPacketHandler().writeNoCache(trackOrUpdateObjective);
} }
}, this.getTaskInfoMessage(), trackObjectivePacket); }, trackObjectivePacket);
this.checkTaskSetCompletion(store); this.checkTaskSetCompletion(store);
} }
} else { } else {
@@ -304,28 +312,21 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
} }
public void cancel() { public void cancel() {
for (ObjectiveTask currentTask : this.currentTasks) { if (this.currentTasks != null) {
currentTask.revertTransactionRecords(); for (ObjectiveTask currentTask : this.currentTasks) {
currentTask.revertTransactionRecords();
}
} }
} }
public void unload() { public void unload() {
for (ObjectiveTask currentTask : this.currentTasks) { if (this.currentTasks != null) {
currentTask.unloadTransactionRecords(); 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) { public void reloadObjectiveAsset(@Nonnull Map<String, ObjectiveAsset> reloadedAssets) {
ObjectiveTaskAsset[] taskAssets = this.checkPossibleAssetReload(reloadedAssets); ObjectiveTaskAsset[] taskAssets = this.checkPossibleAssetReload(reloadedAssets);
if (taskAssets != null) { if (taskAssets != null) {
@@ -404,13 +405,17 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
@Nullable @Nullable
private ObjectiveTask findMatchingObjectiveTask(@Nonnull ObjectiveTaskAsset taskAsset) { private ObjectiveTask findMatchingObjectiveTask(@Nonnull ObjectiveTaskAsset taskAsset) {
for (ObjectiveTask objectiveTask : this.currentTasks) { if (this.currentTasks == null) {
if (objectiveTask.getAsset().matchesAsset(taskAsset)) { return null;
return objectiveTask; } else {
for (ObjectiveTask objectiveTask : this.currentTasks) {
if (objectiveTask.getAsset().matchesAsset(taskAsset)) {
return objectiveTask;
}
} }
}
return null; return null;
}
} }
private void cancelReload(@Nonnull ObjectiveTask[] newTasks) { 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) { private void revertRemovedTasks(@Nonnull ObjectiveTask[] newTasks) {
for (ObjectiveTask objectiveTask : this.currentTasks) { if (this.currentTasks != null) {
boolean foundMatchingTask = false; for (ObjectiveTask objectiveTask : this.currentTasks) {
boolean foundMatchingTask = false;
for (ObjectiveTask newTask : newTasks) { for (ObjectiveTask newTask : newTasks) {
if (newTask.equals(objectiveTask)) { if (newTask.equals(objectiveTask)) {
foundMatchingTask = true; foundMatchingTask = true;
break; break;
}
} }
}
if (!foundMatchingTask) { if (!foundMatchingTask) {
objectiveTask.revertTransactionRecords(); objectiveTask.revertTransactionRecords();
}
} }
} }
} }
@@ -463,7 +470,10 @@ public class Objective implements NetworkSerializable<com.hypixel.hytale.protoco
for (UUID playerUUID : this.playerUUIDs) { for (UUID playerUUID : this.playerUUIDs) {
PlayerRef playerRef = Universe.get().getPlayer(playerUUID); PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
if (playerRef != null) { 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()); ObjectiveAsset objectiveAsset = Objects.requireNonNull(this.getObjectiveAsset());
com.hypixel.hytale.protocol.Objective packet = new com.hypixel.hytale.protocol.Objective(); com.hypixel.hytale.protocol.Objective packet = new com.hypixel.hytale.protocol.Objective();
packet.objectiveUuid = this.objectiveUUID; packet.objectiveUuid = this.objectiveUUID;
packet.objectiveTitleKey = objectiveAsset.getTitleKey(); packet.objectiveTitleKey = Message.translation(objectiveAsset.getTitleKey()).getFormattedMessage();
packet.objectiveDescriptionKey = this.getCurrentDescription(); packet.objectiveDescriptionKey = Message.translation(this.getCurrentDescription()).getFormattedMessage();
if (this.objectiveLineHistoryData != null) { if (this.objectiveLineHistoryData != null) {
packet.objectiveLineId = this.objectiveLineHistoryData.getId(); packet.objectiveLineId = this.objectiveLineHistoryData.getId();
} }

View File

@@ -20,10 +20,13 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class ObjectiveDataStore { public class ObjectiveDataStore {
@Nonnull
private final Map<UUID, Objective> objectives = new ConcurrentHashMap<>(); private final Map<UUID, Objective> objectives = new ConcurrentHashMap<>();
@Nonnull
private final Map<UUID, Map<String, Set<UUID>>> entityObjectiveUUIDsPerPlayer = new ConcurrentHashMap<>(); private final Map<UUID, Map<String, Set<UUID>>> entityObjectiveUUIDsPerPlayer = new ConcurrentHashMap<>();
@Nonnull @Nonnull
private final DataStore<Objective> dataStore; private final DataStore<Objective> dataStore;
@Nonnull
private final Map<Class<? extends ObjectiveTask>, Set<ObjectiveTaskRef<? extends ObjectiveTask>>> taskRefByType = new ConcurrentHashMap<>(); private final Map<Class<? extends ObjectiveTask>, Set<ObjectiveTaskRef<? extends ObjectiveTask>>> taskRefByType = new ConcurrentHashMap<>();
@Nonnull @Nonnull
private final HytaleLogger logger; private final HytaleLogger logger;

View File

@@ -45,10 +45,12 @@ import com.hypixel.hytale.builtin.adventure.objectives.task.ReachLocationTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.TreasureMapObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.TreasureMapObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseBlockObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.UseBlockObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask; import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask;
import com.hypixel.hytale.builtin.weather.components.WeatherTracker;
import com.hypixel.hytale.codec.Codec; import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.common.util.ArrayUtil; import com.hypixel.hytale.common.util.ArrayUtil;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.ResourceType; import com.hypixel.hytale.component.ResourceType;
@@ -56,6 +58,7 @@ import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.AndQuery; import com.hypixel.hytale.component.query.AndQuery;
import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.spatial.SpatialResource; import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.function.function.TriFunction; import com.hypixel.hytale.function.function.TriFunction;
import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.protocol.packets.assets.TrackOrUpdateObjective; import com.hypixel.hytale.protocol.packets.assets.TrackOrUpdateObjective;
@@ -71,7 +74,6 @@ import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
import com.hypixel.hytale.server.core.asset.type.model.config.Model; import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset; import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.asset.type.weather.config.Weather; import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
import com.hypixel.hytale.server.core.entity.LivingEntity;
import com.hypixel.hytale.server.core.entity.UUIDComponent; import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData; import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData;
@@ -83,9 +85,11 @@ import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel; import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction; import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.prefab.PrefabCopyableComponent;
import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.datastore.DataStoreProvider; import com.hypixel.hytale.server.core.universe.datastore.DataStoreProvider;
@@ -110,15 +114,20 @@ import javax.annotation.Nullable;
public class ObjectivePlugin extends JavaPlugin { public class ObjectivePlugin extends JavaPlugin {
protected static ObjectivePlugin instance; protected static ObjectivePlugin instance;
@Nonnull
public static final String OBJECTIVE_LOCATION_MARKER_MODEL_ID = "Objective_Location_Marker"; public static final String OBJECTIVE_LOCATION_MARKER_MODEL_ID = "Objective_Location_Marker";
public static final long SAVE_INTERVAL_MINUTES = 5L; public static final long SAVE_INTERVAL_MINUTES = 5L;
@Nonnull
private final Map<Class<? extends ObjectiveTaskAsset>, TriFunction<ObjectiveTaskAsset, Integer, Integer, ? extends ObjectiveTask>> taskGenerators = new ConcurrentHashMap<>(); 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<>(); 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 final Config<ObjectivePlugin.ObjectivePluginConfig> config = this.withConfig(ObjectivePlugin.ObjectivePluginConfig.CODEC);
private Model objectiveLocationMarkerModel; private Model objectiveLocationMarkerModel;
private ComponentType<EntityStore, ObjectiveHistoryComponent> objectiveHistoryComponentType; private ComponentType<EntityStore, ObjectiveHistoryComponent> objectiveHistoryComponentType;
private ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponentType; private ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponentType;
private ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponentType; private ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponentType;
@Nullable
private ObjectiveDataStore objectiveDataStore; private ObjectiveDataStore objectiveDataStore;
public static ObjectivePlugin get() { public static ObjectivePlugin get() {
@@ -137,6 +146,7 @@ public class ObjectivePlugin extends JavaPlugin {
return this.objectiveLocationMarkerModel; return this.objectiveLocationMarkerModel;
} }
@Nullable
public ObjectiveDataStore getObjectiveDataStore() { public ObjectiveDataStore getObjectiveDataStore() {
return this.objectiveDataStore; return this.objectiveDataStore;
} }
@@ -144,6 +154,8 @@ public class ObjectivePlugin extends JavaPlugin {
@Override @Override
protected void setup() { protected void setup() {
instance = this; instance = this;
EventRegistry eventRegistry = this.getEventRegistry();
ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
AssetRegistry.register( AssetRegistry.register(
((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder( ((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(
ObjectiveAsset.class, new DefaultAssetMap() ObjectiveAsset.class, new DefaultAssetMap()
@@ -185,10 +197,10 @@ public class ObjectivePlugin extends JavaPlugin {
.build() .build()
); );
this.objectiveDataStore = new ObjectiveDataStore(this.config.get().getDataStoreProvider().create(Objective.CODEC)); this.objectiveDataStore = new ObjectiveDataStore(this.config.get().getDataStoreProvider().create(Objective.CODEC));
this.reachLocationMarkerComponentType = this.getEntityStoreRegistry() this.reachLocationMarkerComponentType = entityStoreRegistry.registerComponent(ReachLocationMarker.class, "ReachLocationMarker", ReachLocationMarker.CODEC);
.registerComponent(ReachLocationMarker.class, "ReachLocationMarker", ReachLocationMarker.CODEC); this.objectiveLocationMarkerComponentType = entityStoreRegistry.registerComponent(
this.objectiveLocationMarkerComponentType = this.getEntityStoreRegistry() ObjectiveLocationMarker.class, "ObjectiveLocation", ObjectiveLocationMarker.CODEC
.registerComponent(ObjectiveLocationMarker.class, "ObjectiveLocation", ObjectiveLocationMarker.CODEC); );
this.registerTask( this.registerTask(
"Craft", CraftObjectiveTaskAsset.class, CraftObjectiveTaskAsset.CODEC, CraftObjectiveTask.class, CraftObjectiveTask.CODEC, CraftObjectiveTask::new "Craft", CraftObjectiveTaskAsset.class, CraftObjectiveTaskAsset.CODEC, CraftObjectiveTask.class, CraftObjectiveTask.CODEC, CraftObjectiveTask::new
); );
@@ -231,46 +243,64 @@ public class ObjectivePlugin extends JavaPlugin {
this.registerCompletion( this.registerCompletion(
"ClearObjectiveItems", ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset.CODEC, ClearObjectiveItemsCompletion::new "ClearObjectiveItems", ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset.CODEC, ClearObjectiveItemsCompletion::new
); );
this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveLineAsset.class, this::onObjectiveLineAssetLoaded); eventRegistry.register(LoadedAssetsEvent.class, ObjectiveLineAsset.class, this::onObjectiveLineAssetLoaded);
this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveAsset.class, this::onObjectiveAssetLoaded); eventRegistry.register(LoadedAssetsEvent.class, ObjectiveAsset.class, this::onObjectiveAssetLoaded);
this.getEventRegistry().register(PlayerDisconnectEvent.class, this::onPlayerDisconnect); eventRegistry.register(PlayerDisconnectEvent.class, this::onPlayerDisconnect);
this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveLocationMarkerAsset.class, ObjectivePlugin::onObjectiveLocationMarkerChange); eventRegistry.register(LoadedAssetsEvent.class, ObjectiveLocationMarkerAsset.class, ObjectivePlugin::onObjectiveLocationMarkerChange);
this.getEventRegistry().register(LoadedAssetsEvent.class, ModelAsset.class, this::onModelAssetChange); eventRegistry.register(LoadedAssetsEvent.class, ModelAsset.class, this::onModelAssetChange);
this.getEventRegistry().registerGlobal(LivingEntityInventoryChangeEvent.class, this::onLivingEntityInventoryChange); eventRegistry.registerGlobal(LivingEntityInventoryChangeEvent.class, this::onLivingEntityInventoryChange);
this.getEventRegistry().registerGlobal(AddWorldEvent.class, this::onWorldAdded); eventRegistry.registerGlobal(AddWorldEvent.class, this::onWorldAdded);
this.getCommandRegistry().registerCommand(new ObjectiveCommand()); this.getCommandRegistry().registerCommand(new ObjectiveCommand());
EntityModule entityModule = EntityModule.get(); EntityModule entityModule = EntityModule.get();
ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType(); ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent = entityModule.getPlayerSpatialResourceType(); ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent = entityModule.getPlayerSpatialResourceType();
this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.EntityAdded(this.reachLocationMarkerComponentType)); ComponentType<EntityStore, NetworkId> networkIdComponentType = NetworkId.getComponentType();
this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.EnsureNetworkSendable()); ComponentType<EntityStore, TransformComponent> transformComponentType = TransformComponent.getComponentType();
this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.Ticking(this.reachLocationMarkerComponentType, playerSpatialComponent)); ComponentType<EntityStore, UUIDComponent> uuidComponentType = UUIDComponent.getComponentType();
this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.EnsureNetworkSendableSystem()); ComponentType<EntityStore, WeatherTracker> weatherTrackerComponentType = WeatherTracker.getComponentType();
this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.InitSystem(this.objectiveLocationMarkerComponentType)); ComponentType<EntityStore, ModelComponent> modelComponentType = ModelComponent.getComponentType();
this.getEntityStoreRegistry() ComponentType<EntityStore, PrefabCopyableComponent> prefabCopyableComponentType = PrefabCopyableComponent.getComponentType();
.registerSystem( entityStoreRegistry.registerSystem(new ReachLocationMarkerSystems.EntityAdded(this.reachLocationMarkerComponentType, transformComponentType));
new ObjectiveLocationMarkerSystems.TickingSystem(this.objectiveLocationMarkerComponentType, playerRefComponentType, playerSpatialComponent) entityStoreRegistry.registerSystem(new ReachLocationMarkerSystems.EnsureNetworkSendable(this.reachLocationMarkerComponentType, networkIdComponentType));
); entityStoreRegistry.registerSystem(
new ReachLocationMarkerSystems.Ticking(this.reachLocationMarkerComponentType, playerSpatialComponent, transformComponentType, uuidComponentType)
);
entityStoreRegistry.registerSystem(
new ObjectiveLocationMarkerSystems.EnsureNetworkSendableSystem(this.objectiveLocationMarkerComponentType, networkIdComponentType)
);
entityStoreRegistry.registerSystem(
new ObjectiveLocationMarkerSystems.InitSystem(
this.objectiveLocationMarkerComponentType, modelComponentType, transformComponentType, prefabCopyableComponentType
)
);
entityStoreRegistry.registerSystem(
new ObjectiveLocationMarkerSystems.TickingSystem(
this.objectiveLocationMarkerComponentType,
playerRefComponentType,
playerSpatialComponent,
transformComponentType,
weatherTrackerComponentType,
uuidComponentType
)
);
CommonObjectiveHistoryData.CODEC.register("Objective", ObjectiveHistoryData.class, ObjectiveHistoryData.CODEC); CommonObjectiveHistoryData.CODEC.register("Objective", ObjectiveHistoryData.class, ObjectiveHistoryData.CODEC);
CommonObjectiveHistoryData.CODEC.register("ObjectiveLine", ObjectiveLineHistoryData.class, ObjectiveLineHistoryData.CODEC); CommonObjectiveHistoryData.CODEC.register("ObjectiveLine", ObjectiveLineHistoryData.class, ObjectiveLineHistoryData.CODEC);
ObjectiveRewardHistoryData.CODEC.register("Item", ItemObjectiveRewardHistoryData.class, ItemObjectiveRewardHistoryData.CODEC); ObjectiveRewardHistoryData.CODEC.register("Item", ItemObjectiveRewardHistoryData.class, ItemObjectiveRewardHistoryData.CODEC);
this.objectiveHistoryComponentType = this.getEntityStoreRegistry() this.objectiveHistoryComponentType = entityStoreRegistry.registerComponent(
.registerComponent(ObjectiveHistoryComponent.class, "ObjectiveHistory", ObjectiveHistoryComponent.CODEC); ObjectiveHistoryComponent.class, "ObjectiveHistory", ObjectiveHistoryComponent.CODEC
this.getEntityStoreRegistry().registerSystem(new ObjectivePlayerSetupSystem(this.objectiveHistoryComponentType, Player.getComponentType())); );
this.getEntityStoreRegistry().registerSystem(new ObjectiveItemEntityRemovalSystem()); entityStoreRegistry.registerSystem(new ObjectivePlayerSetupSystem(this.objectiveHistoryComponentType, Player.getComponentType()));
entityStoreRegistry.registerSystem(new ObjectiveItemEntityRemovalSystem());
this.getCodecRegistry(Interaction.CODEC).register("StartObjective", StartObjectiveInteraction.class, StartObjectiveInteraction.CODEC); this.getCodecRegistry(Interaction.CODEC).register("StartObjective", StartObjectiveInteraction.class, StartObjectiveInteraction.CODEC);
this.getCodecRegistry(Interaction.CODEC).register("CanBreakRespawnPoint", CanBreakRespawnPointInteraction.class, CanBreakRespawnPointInteraction.CODEC); this.getCodecRegistry(Interaction.CODEC).register("CanBreakRespawnPoint", CanBreakRespawnPointInteraction.class, CanBreakRespawnPointInteraction.CODEC);
BlockStateModule.get().registerBlockState(TreasureChestState.class, "TreasureChest", TreasureChestState.CODEC); BlockStateModule.get().registerBlockState(TreasureChestState.class, "TreasureChest", TreasureChestState.CODEC);
this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ObjectiveGameplayConfig.class, "Objective", ObjectiveGameplayConfig.CODEC); this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ObjectiveGameplayConfig.class, "Objective", ObjectiveGameplayConfig.CODEC);
this.getEntityStoreRegistry() entityStoreRegistry.registerSystem(
.registerSystem( new EntityModule.TangibleMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true
new EntityModule.TangibleMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true );
); entityStoreRegistry.registerSystem(
this.getEntityStoreRegistry() new EntityModule.HiddenFromPlayerMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true
.registerSystem( );
new EntityModule.HiddenFromPlayerMigrationSystem(Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())),
true
);
} }
@Override @Override
@@ -280,13 +310,17 @@ public class ObjectivePlugin extends JavaPlugin {
throw new IllegalStateException(String.format("Default objective location marker model '%s' not found", "Objective_Location_Marker")); throw new IllegalStateException(String.format("Default objective location marker model '%s' not found", "Objective_Location_Marker"));
} else { } else {
this.objectiveLocationMarkerModel = Model.createUnitScaleModel(modelAsset); this.objectiveLocationMarkerModel = Model.createUnitScaleModel(modelAsset);
HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> this.objectiveDataStore.saveToDiskAllObjectives(), 5L, 5L, TimeUnit.MINUTES); if (this.objectiveDataStore != null) {
HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> this.objectiveDataStore.saveToDiskAllObjectives(), 5L, 5L, TimeUnit.MINUTES);
}
} }
} }
@Override @Override
protected void shutdown() { protected void shutdown() {
this.objectiveDataStore.saveToDiskAllObjectives(); if (this.objectiveDataStore != null) {
this.objectiveDataStore.saveToDiskAllObjectives();
}
} }
public ComponentType<EntityStore, ReachLocationMarker> getReachLocationMarkerComponentType() { public ComponentType<EntityStore, ReachLocationMarker> getReachLocationMarkerComponentType() {
@@ -305,10 +339,12 @@ public class ObjectivePlugin extends JavaPlugin {
Codec<U> implementationCodec, Codec<U> implementationCodec,
TriFunction<T, Integer, Integer, U> generator TriFunction<T, Integer, Integer, U> generator
) { ) {
ObjectiveTaskAsset.CODEC.register(id, assetClass, assetCodec); if (this.objectiveDataStore != null) {
ObjectiveTask.CODEC.register(id, implementationClass, implementationCodec); ObjectiveTaskAsset.CODEC.register(id, assetClass, assetCodec);
this.taskGenerators.put(assetClass, generator); ObjectiveTask.CODEC.register(id, implementationClass, implementationCodec);
this.objectiveDataStore.registerTaskRef(implementationClass); this.taskGenerators.put(assetClass, generator);
this.objectiveDataStore.registerTaskRef(implementationClass);
}
} }
public <T extends ObjectiveCompletionAsset, U extends ObjectiveCompletion> void registerCompletion( public <T extends ObjectiveCompletionAsset, U extends ObjectiveCompletion> void registerCompletion(
@@ -342,79 +378,90 @@ public class ObjectivePlugin extends JavaPlugin {
@Nullable UUID markerUUID, @Nullable UUID markerUUID,
@Nonnull Store<EntityStore> store @Nonnull Store<EntityStore> store
) { ) {
ObjectiveAsset asset = ObjectiveAsset.getAssetMap().getAsset(objectiveId); if (this.objectiveDataStore == null) {
if (asset == null) {
this.getLogger().at(Level.WARNING).log("Failed to find objective asset '%s'", objectiveId);
return null;
} else if (markerUUID == null && !asset.isValidForPlayer()) {
this.getLogger().at(Level.WARNING).log("Objective %s can't be used for Player", asset.getId());
return null; return null;
} else { } else {
Objective objective = new Objective(asset, objectiveUUID, playerUUIDs, worldUUID, markerUUID); ObjectiveAsset asset = ObjectiveAsset.getAssetMap().getAsset(objectiveId);
boolean setupResult = objective.setup(store); if (asset == null) {
Message assetTitleMessage = Message.translation(asset.getTitleKey()); this.getLogger().at(Level.WARNING).log("Failed to find objective asset '%s'", objectiveId);
if (!setupResult || !this.objectiveDataStore.addObjective(objective.getObjectiveUUID(), objective)) { return null;
this.getLogger().at(Level.WARNING).log("Failed to start objective %s", asset.getId()); } else if (markerUUID == null && !asset.isValidForPlayer()) {
if (objective.getPlayerUUIDs() == null) { this.getLogger().at(Level.WARNING).log("Objective %s can't be used for Player", asset.getId());
return null; return null;
} else {
objective.forEachParticipant(participantReference -> {
PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
if (playerRefComponent != null) {
playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.failed").param("title", assetTitleMessage));
}
});
return null;
}
} else if (objective.getPlayerUUIDs() == null) {
return objective;
} else { } else {
TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(objective.toPacket()); Objective objective = new Objective(asset, objectiveUUID, playerUUIDs, worldUUID, markerUUID);
String objectiveAssetId = asset.getId(); boolean setupResult = objective.setup(store);
objective.forEachParticipant(participantReference -> { Message assetTitleMessage = Message.translation(asset.getTitleKey());
Player playerComponent = store.getComponent(participantReference, Player.getComponentType()); if (!setupResult || !this.objectiveDataStore.addObjective(objective.getObjectiveUUID(), objective)) {
if (playerComponent != null) { this.getLogger().at(Level.WARNING).log("Failed to start objective %s", asset.getId());
if (!this.canPlayerDoObjective(playerComponent, objectiveAssetId)) { if (objective.getPlayerUUIDs() == null) {
playerComponent.sendMessage(Message.translation("server.modules.objective.playerAlreadyDoingObjective").param("title", assetTitleMessage)); return null;
} else { } else {
objective.forEachParticipant(participantReference -> {
PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType()); PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
if (playerRefComponent != null) {
assert playerRefComponent != null; playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.failed").param("title", assetTitleMessage));
}
UUIDComponent uuidComponent = store.getComponent(participantReference, UUIDComponent.getComponentType()); });
return null;
assert uuidComponent != null;
objective.addActivePlayerUUID(uuidComponent.getUuid());
PlayerConfigData playerConfigData = playerComponent.getPlayerConfigData();
HashSet<UUID> activeObjectiveUUIDs = new HashSet<>(playerConfigData.getActiveObjectiveUUIDs());
activeObjectiveUUIDs.add(objective.getObjectiveUUID());
playerConfigData.setActiveObjectiveUUIDs(activeObjectiveUUIDs);
playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.success").param("title", assetTitleMessage));
playerRefComponent.sendMessage(objective.getTaskInfoMessage());
playerRefComponent.getPacketHandler().writeNoCache(trackObjectivePacket);
}
} }
}); } else if (objective.getPlayerUUIDs() == null) {
objective.markDirty(); return objective;
return objective; } else {
TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(objective.toPacket());
String objectiveAssetId = asset.getId();
objective.forEachParticipant(
participantReference -> {
Player playerComponent = store.getComponent(participantReference, Player.getComponentType());
if (playerComponent != null) {
if (!this.canPlayerDoObjective(playerComponent, objectiveAssetId)) {
playerComponent.sendMessage(
Message.translation("server.modules.objective.playerAlreadyDoingObjective").param("title", assetTitleMessage)
);
} else {
PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
assert playerRefComponent != null;
UUIDComponent uuidComponent = store.getComponent(participantReference, UUIDComponent.getComponentType());
assert uuidComponent != null;
objective.addActivePlayerUUID(uuidComponent.getUuid());
PlayerConfigData playerConfigData = playerComponent.getPlayerConfigData();
HashSet<UUID> activeObjectiveUUIDs = new HashSet<>(playerConfigData.getActiveObjectiveUUIDs());
activeObjectiveUUIDs.add(objective.getObjectiveUUID());
playerConfigData.setActiveObjectiveUUIDs(activeObjectiveUUIDs);
playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.success").param("title", assetTitleMessage));
playerRefComponent.getPacketHandler().writeNoCache(trackObjectivePacket);
}
}
}
);
objective.markDirty();
return objective;
}
} }
} }
} }
public boolean canPlayerDoObjective(@Nonnull Player player, @Nonnull String objectiveAssetId) { public boolean canPlayerDoObjective(@Nonnull Player player, @Nonnull String objectiveAssetId) {
Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); if (this.objectiveDataStore == null) {
if (activeObjectiveUUIDs == null) { return false;
return true;
} else { } else {
for (UUID objectiveUUID : activeObjectiveUUIDs) { Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); if (activeObjectiveUUIDs == null) {
if (objective != null && objective.getObjectiveId().equals(objectiveAssetId)) { return true;
return false; } else {
for (UUID objectiveUUID : activeObjectiveUUIDs) {
Objective objective = this.objectiveDataStore.getObjective(objectiveUUID);
if (objective != null && objective.getObjectiveId().equals(objectiveAssetId)) {
return false;
}
} }
}
return true; return true;
}
} }
} }
@@ -469,56 +516,62 @@ public class ObjectivePlugin extends JavaPlugin {
} }
public boolean canPlayerDoObjectiveLine(@Nonnull Player player, @Nonnull String objectiveLineId) { public boolean canPlayerDoObjectiveLine(@Nonnull Player player, @Nonnull String objectiveLineId) {
Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); if (this.objectiveDataStore == null) {
if (activeObjectiveUUIDs == null) { return false;
return true;
} else { } else {
for (UUID objectiveUUID : activeObjectiveUUIDs) { Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); if (activeObjectiveUUIDs == null) {
if (objective != null) { return true;
ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData(); } else {
if (objectiveLineHistoryData != null && objectiveLineId.equals(objectiveLineHistoryData.getId())) { for (UUID objectiveUUID : activeObjectiveUUIDs) {
return false; Objective objective = this.objectiveDataStore.getObjective(objectiveUUID);
if (objective != null) {
ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData();
if (objectiveLineHistoryData != null && objectiveLineId.equals(objectiveLineHistoryData.getId())) {
return false;
}
} }
} }
}
return true; return true;
}
} }
} }
public void objectiveCompleted(@Nonnull Objective objective, @Nonnull Store<EntityStore> store) { public void objectiveCompleted(@Nonnull Objective objective, @Nonnull Store<EntityStore> store) {
for (UUID playerUUID : objective.getPlayerUUIDs()) { if (this.objectiveDataStore != null) {
this.untrackObjectiveForPlayer(objective, playerUUID); for (UUID playerUUID : objective.getPlayerUUIDs()) {
} this.untrackObjectiveForPlayer(objective, playerUUID);
}
UUID objectiveUUID = objective.getObjectiveUUID(); UUID objectiveUUID = objective.getObjectiveUUID();
this.objectiveDataStore.removeObjective(objectiveUUID); this.objectiveDataStore.removeObjective(objectiveUUID);
if (this.objectiveDataStore.removeFromDisk(objectiveUUID.toString())) { if (this.objectiveDataStore.removeFromDisk(objectiveUUID.toString())) {
ObjectiveLineAsset objectiveLineAsset = objective.getObjectiveLineAsset(); ObjectiveLineAsset objectiveLineAsset = objective.getObjectiveLineAsset();
if (objectiveLineAsset == null) { if (objectiveLineAsset == null) {
this.storeObjectiveHistoryData(objective); this.storeObjectiveHistoryData(objective);
} else {
ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData();
assert objectiveLineHistoryData != null;
objectiveLineHistoryData.addObjectiveHistoryData(objective.getObjectiveHistoryData());
String nextObjectiveId = objectiveLineAsset.getNextObjectiveId(objective.getObjectiveId());
if (nextObjectiveId != null) {
Objective newObjective = this.startObjective(
nextObjectiveId, objectiveUUID, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID(), store
);
if (newObjective != null) {
newObjective.setObjectiveLineHistoryData(objectiveLineHistoryData);
newObjective.checkTaskSetCompletion(store);
}
} else { } else {
this.storeObjectiveLineHistoryData(objectiveLineHistoryData, objective.getPlayerUUIDs()); ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData();
String[] nextObjectiveLineIds = objectiveLineHistoryData.getNextObjectiveLineIds();
if (nextObjectiveLineIds != null) { assert objectiveLineHistoryData != null;
for (String nextObjectiveLineId : nextObjectiveLineIds) {
this.startObjectiveLine(store, nextObjectiveLineId, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID()); objectiveLineHistoryData.addObjectiveHistoryData(objective.getObjectiveHistoryData());
String nextObjectiveId = objectiveLineAsset.getNextObjectiveId(objective.getObjectiveId());
if (nextObjectiveId != null) {
Objective newObjective = this.startObjective(
nextObjectiveId, objectiveUUID, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID(), store
);
if (newObjective != null) {
newObjective.setObjectiveLineHistoryData(objectiveLineHistoryData);
newObjective.checkTaskSetCompletion(store);
}
} else {
this.storeObjectiveLineHistoryData(objectiveLineHistoryData, objective.getPlayerUUIDs());
String[] nextObjectiveLineIds = objectiveLineHistoryData.getNextObjectiveLineIds();
if (nextObjectiveLineIds != null) {
for (String nextObjectiveLineId : nextObjectiveLineIds) {
this.startObjectiveLine(store, nextObjectiveLineId, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID());
}
} }
} }
} }
@@ -587,118 +640,130 @@ public class ObjectivePlugin extends JavaPlugin {
} }
public void cancelObjective(@Nonnull UUID objectiveUUID, @Nonnull Store<EntityStore> store) { public void cancelObjective(@Nonnull UUID objectiveUUID, @Nonnull Store<EntityStore> store) {
Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); if (this.objectiveDataStore != null) {
if (objective != null) { Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
objective.cancel(); if (objective != null) {
objective.cancel();
for (UUID playerUUID : objective.getPlayerUUIDs()) { for (UUID playerUUID : objective.getPlayerUUIDs()) {
this.untrackObjectiveForPlayer(objective, playerUUID); this.untrackObjectiveForPlayer(objective, playerUUID);
}
this.objectiveDataStore.removeObjective(objectiveUUID);
this.objectiveDataStore.removeFromDisk(objectiveUUID.toString());
} }
this.objectiveDataStore.removeObjective(objectiveUUID);
this.objectiveDataStore.removeFromDisk(objectiveUUID.toString());
} }
} }
public void untrackObjectiveForPlayer(@Nonnull Objective objective, @Nonnull UUID playerUUID) { public void untrackObjectiveForPlayer(@Nonnull Objective objective, @Nonnull UUID playerUUID) {
UUID objectiveUUID = objective.getObjectiveUUID(); if (this.objectiveDataStore != null) {
ObjectiveTask[] currentTasks = objective.getCurrentTasks(); UUID objectiveUUID = objective.getObjectiveUUID();
for (ObjectiveTask task : currentTasks) {
if (task instanceof UseEntityObjectiveTask) {
this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, ((UseEntityObjectiveTask)task).getAsset().getTaskId(), playerUUID);
}
}
PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
if (playerRef != null) {
Player player = playerRef.getComponent(Player.getComponentType());
HashSet<UUID> activeObjectiveUUIDs = new HashSet<>(player.getPlayerConfigData().getActiveObjectiveUUIDs());
activeObjectiveUUIDs.remove(objectiveUUID);
player.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs);
playerRef.getPacketHandler().writeNoCache(new UntrackObjective(objectiveUUID));
}
}
public void addPlayerToExistingObjective(@Nonnull Store<EntityStore> store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) {
Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
if (objective != null) {
objective.addActivePlayerUUID(playerUUID);
ObjectiveDataStore objectiveDataStore = get().getObjectiveDataStore();
ObjectiveTask[] currentTasks = objective.getCurrentTasks(); ObjectiveTask[] currentTasks = objective.getCurrentTasks();
for (ObjectiveTask task : currentTasks) { for (ObjectiveTask task : currentTasks) {
if (task instanceof UseEntityObjectiveTask) { if (task instanceof UseEntityObjectiveTask useEntityObjectiveTask) {
objectiveDataStore.addEntityTaskForPlayer(playerUUID, ((UseEntityObjectiveTask)task).getAsset().getTaskId(), objectiveUUID); this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, useEntityObjectiveTask.getAsset().getTaskId(), playerUUID);
} }
} }
PlayerRef playerRef = Universe.get().getPlayer(playerUUID); PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
if (playerRef != null && playerRef.isValid()) { if (playerRef != null) {
Ref<EntityStore> playerReference = playerRef.getReference(); Player player = playerRef.getComponent(Player.getComponentType());
if (playerReference != null && playerReference.isValid()) { HashSet<UUID> activeObjectiveUUIDs = new HashSet<>(player.getPlayerConfigData().getActiveObjectiveUUIDs());
Player playerComponent = store.getComponent(playerReference, Player.getComponentType()); activeObjectiveUUIDs.remove(objectiveUUID);
player.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs);
playerRef.getPacketHandler().writeNoCache(new UntrackObjective(objectiveUUID));
}
}
}
assert playerComponent != null; public void addPlayerToExistingObjective(@Nonnull Store<EntityStore> store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) {
if (this.objectiveDataStore != null) {
Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
if (objective != null) {
objective.addActivePlayerUUID(playerUUID);
ObjectiveDataStore objectiveDataStore = get().getObjectiveDataStore();
ObjectiveTask[] currentTasks = objective.getCurrentTasks();
HashSet<UUID> activeObjectiveUUIDs = new HashSet<>(playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs()); for (ObjectiveTask task : currentTasks) {
activeObjectiveUUIDs.add(objectiveUUID); if (task instanceof UseEntityObjectiveTask) {
playerComponent.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs); objectiveDataStore.addEntityTaskForPlayer(playerUUID, ((UseEntityObjectiveTask)task).getAsset().getTaskId(), objectiveUUID);
playerRef.getPacketHandler().writeNoCache(new TrackOrUpdateObjective(objective.toPacket())); }
}
PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
if (playerRef != null && playerRef.isValid()) {
Ref<EntityStore> playerReference = playerRef.getReference();
if (playerReference != null && playerReference.isValid()) {
Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
assert playerComponent != null;
HashSet<UUID> activeObjectiveUUIDs = new HashSet<>(playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs());
activeObjectiveUUIDs.add(objectiveUUID);
playerComponent.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs);
playerRef.getPacketHandler().writeNoCache(new TrackOrUpdateObjective(objective.toPacket()));
}
} }
} }
} }
} }
public void removePlayerFromExistingObjective(@Nonnull Store<EntityStore> store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) { public void removePlayerFromExistingObjective(@Nonnull Store<EntityStore> store, @Nonnull UUID playerUUID, @Nonnull UUID objectiveUUID) {
Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store); if (this.objectiveDataStore != null) {
if (objective != null) { Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
objective.removeActivePlayerUUID(playerUUID); if (objective != null) {
if (objective.getActivePlayerUUIDs().isEmpty()) { objective.removeActivePlayerUUID(playerUUID);
this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective); if (objective.getActivePlayerUUIDs().isEmpty()) {
this.objectiveDataStore.unloadObjective(objectiveUUID); this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective);
} this.objectiveDataStore.unloadObjective(objectiveUUID);
}
this.untrackObjectiveForPlayer(objective, playerUUID); this.untrackObjectiveForPlayer(objective, playerUUID);
}
} }
} }
private void onPlayerDisconnect(@Nonnull PlayerDisconnectEvent event) { private void onPlayerDisconnect(@Nonnull PlayerDisconnectEvent event) {
PlayerRef playerRef = event.getPlayerRef(); if (this.objectiveDataStore != null) {
Ref<EntityStore> ref = playerRef.getReference(); PlayerRef playerRef = event.getPlayerRef();
if (ref != null) { Ref<EntityStore> ref = playerRef.getReference();
Store<EntityStore> store = ref.getStore(); if (ref != null) {
World world = store.getExternalData().getWorld(); Store<EntityStore> store = ref.getStore();
world.execute( World world = store.getExternalData().getWorld();
() -> { world.execute(
if (ref.isValid()) { () -> {
UUID playerUUID = playerRef.getUuid(); if (ref.isValid()) {
this.getLogger().at(Level.INFO).log("Checking objectives for disconnecting player '" + playerRef.getUsername() + "' (" + playerUUID + ")"); UUID playerUUID = playerRef.getUuid();
Player playerComponent = store.getComponent(ref, Player.getComponentType()); this.getLogger().at(Level.INFO).log("Checking objectives for disconnecting player '" + playerRef.getUsername() + "' (" + playerUUID + ")");
if (playerComponent != null) { Player playerComponent = store.getComponent(ref, Player.getComponentType());
Set<UUID> activeObjectiveUUIDs = playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs(); if (playerComponent != null) {
if (activeObjectiveUUIDs == null) { Set<UUID> activeObjectiveUUIDs = playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs();
this.getLogger().at(Level.INFO).log("No active objectives found for player '" + playerRef.getUsername() + "' (" + playerUUID + ")"); if (activeObjectiveUUIDs == null) {
} else { this.getLogger().at(Level.INFO).log("No active objectives found for player '" + playerRef.getUsername() + "' (" + playerUUID + ")");
this.getLogger() } else {
.at(Level.INFO) this.getLogger()
.log("Processing " + activeObjectiveUUIDs.size() + " active objectives for '" + playerRef.getUsername() + "' (" + playerUUID + ")"); .at(Level.INFO)
.log(
"Processing " + activeObjectiveUUIDs.size() + " active objectives for '" + playerRef.getUsername() + "' (" + playerUUID + ")"
);
for (UUID objectiveUUID : activeObjectiveUUIDs) { for (UUID objectiveUUID : activeObjectiveUUIDs) {
Objective objective = this.objectiveDataStore.getObjective(objectiveUUID); Objective objective = this.objectiveDataStore.getObjective(objectiveUUID);
if (objective != null) { if (objective != null) {
objective.removeActivePlayerUUID(playerUUID); objective.removeActivePlayerUUID(playerUUID);
if (objective.getActivePlayerUUIDs().isEmpty()) { if (objective.getActivePlayerUUIDs().isEmpty()) {
this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective); this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective);
this.objectiveDataStore.unloadObjective(objectiveUUID); this.objectiveDataStore.unloadObjective(objectiveUUID);
}
} }
} }
} }
} }
} }
} }
} );
); }
} }
} }
@@ -728,7 +793,11 @@ public class ObjectivePlugin extends JavaPlugin {
} }
private void onObjectiveAssetLoaded(@Nonnull LoadedAssetsEvent<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> event) { private void onObjectiveAssetLoaded(@Nonnull LoadedAssetsEvent<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> event) {
this.objectiveDataStore.getObjectiveCollection().forEach(objective -> objective.reloadObjectiveAsset(event.getLoadedAssets())); if (this.objectiveDataStore != null) {
for (Objective objective : this.objectiveDataStore.getObjectiveCollection()) {
objective.reloadObjectiveAsset(event.getLoadedAssets());
}
}
} }
private static void onObjectiveLocationMarkerChange( private static void onObjectiveLocationMarkerChange(
@@ -785,6 +854,8 @@ public class ObjectivePlugin extends JavaPlugin {
oldModel.getGradientId(), oldModel.getGradientId(),
oldModel.getEyeHeight(), oldModel.getEyeHeight(),
oldModel.getCrouchOffset(), oldModel.getCrouchOffset(),
oldModel.getSittingOffset(),
oldModel.getSleepingOffset(),
oldModel.getAnimationSetMap(), oldModel.getAnimationSetMap(),
oldModel.getCamera(), oldModel.getCamera(),
oldModel.getLight(), oldModel.getLight(),
@@ -815,43 +886,47 @@ public class ObjectivePlugin extends JavaPlugin {
} }
private void onLivingEntityInventoryChange(@Nonnull LivingEntityInventoryChangeEvent event) { private void onLivingEntityInventoryChange(@Nonnull LivingEntityInventoryChangeEvent event) {
LivingEntity entity = event.getEntity(); if (this.objectiveDataStore != null) {
if (entity instanceof Player player) { if (event.getEntity() instanceof Player player) {
Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs(); Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
if (!activeObjectiveUUIDs.isEmpty()) { if (!activeObjectiveUUIDs.isEmpty()) {
Set<UUID> inventoryItemObjectiveUUIDs = null; Set<UUID> inventoryItemObjectiveUUIDs = null;
CombinedItemContainer inventory = entity.getInventory().getCombinedHotbarFirst(); CombinedItemContainer inventory = player.getInventory().getCombinedHotbarFirst();
for (short i = 0; i < inventory.getCapacity(); i++) { for (short i = 0; i < inventory.getCapacity(); i++) {
ItemStack itemStack = inventory.getItemStack(i); ItemStack itemStack = inventory.getItemStack(i);
if (!ItemStack.isEmpty(itemStack)) { if (!ItemStack.isEmpty(itemStack)) {
UUID objectiveUUID = itemStack.getFromMetadataOrNull(StartObjectiveInteraction.OBJECTIVE_UUID); UUID objectiveUUID = itemStack.getFromMetadataOrNull(StartObjectiveInteraction.OBJECTIVE_UUID);
if (objectiveUUID != null) { if (objectiveUUID != null) {
if (inventoryItemObjectiveUUIDs == null) { if (inventoryItemObjectiveUUIDs == null) {
inventoryItemObjectiveUUIDs = new HashSet<>(activeObjectiveUUIDs); inventoryItemObjectiveUUIDs = new HashSet<>(activeObjectiveUUIDs);
}
inventoryItemObjectiveUUIDs.add(objectiveUUID);
} }
inventoryItemObjectiveUUIDs.add(objectiveUUID);
} }
} }
}
for (UUID activeObjectiveUUID : activeObjectiveUUIDs) { Ref<EntityStore> reference = player.getReference();
if (inventoryItemObjectiveUUIDs == null || !inventoryItemObjectiveUUIDs.contains(activeObjectiveUUID)) { if (reference != null && reference.isValid()) {
Objective objective = this.objectiveDataStore.getObjective(activeObjectiveUUID); Store<EntityStore> store = reference.getStore();
if (objective != null) { World world = store.getExternalData().getWorld();
ObjectiveAsset objectiveAsset = objective.getObjectiveAsset();
if (objectiveAsset != null && objectiveAsset.isRemoveOnItemDrop()) {
Ref<EntityStore> reference = entity.getReference();
Store<EntityStore> store = reference.getStore();
World world = store.getExternalData().getWorld();
world.execute(() -> {
UUIDComponent uuidComponent = store.getComponent(reference, UUIDComponent.getComponentType());
assert uuidComponent != null; for (UUID activeObjectiveUUID : activeObjectiveUUIDs) {
if (inventoryItemObjectiveUUIDs == null || !inventoryItemObjectiveUUIDs.contains(activeObjectiveUUID)) {
Objective objective = this.objectiveDataStore.getObjective(activeObjectiveUUID);
if (objective != null) {
ObjectiveAsset objectiveAsset = objective.getObjectiveAsset();
if (objectiveAsset != null && objectiveAsset.isRemoveOnItemDrop()) {
world.execute(() -> {
UUIDComponent uuidComponent = store.getComponent(reference, UUIDComponent.getComponentType());
get().removePlayerFromExistingObjective(store, uuidComponent.getUuid(), activeObjectiveUUID); assert uuidComponent != null;
});
get().removePlayerFromExistingObjective(store, uuidComponent.getUuid(), activeObjectiveUUID);
});
}
}
} }
} }
} }
@@ -860,33 +935,37 @@ public class ObjectivePlugin extends JavaPlugin {
} }
} }
private void onWorldAdded(AddWorldEvent event) { private void onWorldAdded(@Nonnull AddWorldEvent event) {
event.getWorld().getWorldMapManager().addMarkerProvider("objectives", ObjectiveMarkerProvider.INSTANCE); event.getWorld().getWorldMapManager().addMarkerProvider("objectives", ObjectiveMarkerProvider.INSTANCE);
} }
@Nonnull @Nonnull
public String getObjectiveDataDump() { public String getObjectiveDataDump() {
StringBuilder sb = new StringBuilder("Objective Data\n"); StringBuilder sb = new StringBuilder("Objective Data\n");
if (this.objectiveDataStore != null) {
for (Objective objective : this.objectiveDataStore.getObjectiveCollection()) { for (Objective objective : this.objectiveDataStore.getObjectiveCollection()) {
sb.append("Objective ID: ") sb.append("Objective ID: ")
.append(objective.getObjectiveId()) .append(objective.getObjectiveId())
.append("\n\t") .append("\n\t")
.append("UUID: ") .append("UUID: ")
.append(objective.getObjectiveUUID()) .append(objective.getObjectiveUUID())
.append("\n\t") .append("\n\t")
.append("Players: ") .append("Players: ")
.append(Arrays.toString(objective.getPlayerUUIDs().toArray())) .append(Arrays.toString(objective.getPlayerUUIDs().toArray()))
.append("\n\t") .append("\n\t")
.append("Active players: ") .append("Active players: ")
.append(Arrays.toString(objective.getActivePlayerUUIDs().toArray())) .append(Arrays.toString(objective.getActivePlayerUUIDs().toArray()))
.append("\n\n"); .append("\n\n");
}
} else {
sb.append("Objective data store is not initialized.\n");
} }
return sb.toString(); return sb.toString();
} }
public static class ObjectivePluginConfig { public static class ObjectivePluginConfig {
@Nonnull
public static final BuilderCodec<ObjectivePlugin.ObjectivePluginConfig> CODEC = BuilderCodec.builder( public static final BuilderCodec<ObjectivePlugin.ObjectivePluginConfig> CODEC = BuilderCodec.builder(
ObjectivePlugin.ObjectivePluginConfig.class, ObjectivePlugin.ObjectivePluginConfig::new ObjectivePlugin.ObjectivePluginConfig.class, ObjectivePlugin.ObjectivePluginConfig::new
) )

View File

@@ -23,6 +23,7 @@ import java.util.UUID;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class TreasureChestState extends ItemContainerState implements BreakValidatedBlockState { public class TreasureChestState extends ItemContainerState implements BreakValidatedBlockState {
@Nonnull
public static final BuilderCodec<TreasureChestState> CODEC = BuilderCodec.builder(TreasureChestState.class, TreasureChestState::new, BlockState.BASE_CODEC) public static final BuilderCodec<TreasureChestState> CODEC = BuilderCodec.builder(TreasureChestState.class, TreasureChestState::new, BlockState.BASE_CODEC)
.append( .append(
new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY), new KeyedCodec<>("ObjectiveUUID", Codec.UUID_BINARY),

View File

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

View File

@@ -53,38 +53,36 @@ public class ObjectiveLocationMarkerCommand extends AbstractCommandCollection {
protected void execute( protected void execute(
@Nonnull CommandContext context, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull World world @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(ref, TransformComponent.getComponentType());
TransformComponent playerTransformComponent = store.getComponent(playerReference, TransformComponent.getComponentType()); if (playerTransformComponent != null) {
String objectiveLocationMarkerId = this.locationMarkerArg.get(context);
assert playerTransformComponent != null; if (ObjectiveLocationMarkerAsset.getAssetMap().getAsset(objectiveLocationMarkerId) == null) {
context.sendMessage(Message.translation("server.commands.objective.locationMarker.notFound").param("id", objectiveLocationMarkerId));
String objectiveLocationMarkerId = this.locationMarkerArg.get(context); context.sendMessage(
if (ObjectiveLocationMarkerAsset.getAssetMap().getAsset(objectiveLocationMarkerId) == null) { Message.translation("server.general.failed.didYouMean")
context.sendMessage(Message.translation("server.commands.objective.locationMarker.notFound").param("id", objectiveLocationMarkerId)); .param(
context.sendMessage( "choices",
Message.translation("server.general.failed.didYouMean") StringUtil.sortByFuzzyDistance(
.param( objectiveLocationMarkerId, ObjectiveLocationMarkerAsset.getAssetMap().getAssetMap().keySet(), CommandUtil.RECOMMEND_COUNT
"choices", )
StringUtil.sortByFuzzyDistance( .toString()
objectiveLocationMarkerId, ObjectiveLocationMarkerAsset.getAssetMap().getAssetMap().keySet(), CommandUtil.RECOMMEND_COUNT )
) );
.toString() } else {
) Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
); holder.addComponent(ObjectiveLocationMarker.getComponentType(), new ObjectiveLocationMarker(objectiveLocationMarkerId));
} else { Model model = ObjectivePlugin.get().getObjectiveLocationMarkerModel();
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder(); holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
holder.addComponent(ObjectiveLocationMarker.getComponentType(), new ObjectiveLocationMarker(objectiveLocationMarkerId)); holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
Model model = ObjectivePlugin.get().getObjectiveLocationMarkerModel(); holder.addComponent(Nameplate.getComponentType(), new Nameplate(objectiveLocationMarkerId));
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model)); TransformComponent transform = new TransformComponent(playerTransformComponent.getPosition(), playerTransformComponent.getRotation());
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference())); holder.addComponent(TransformComponent.getComponentType(), transform);
holder.addComponent(Nameplate.getComponentType(), new Nameplate(objectiveLocationMarkerId)); holder.ensureComponent(UUIDComponent.getComponentType());
TransformComponent transform = new TransformComponent(playerTransformComponent.getPosition(), playerTransformComponent.getRotation()); holder.ensureComponent(Intangible.getComponentType());
holder.addComponent(TransformComponent.getComponentType(), transform); holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType());
holder.ensureComponent(UUIDComponent.getComponentType()); store.addEntity(holder, AddReason.SPAWN);
holder.ensureComponent(Intangible.getComponentType()); context.sendMessage(Message.translation("server.commands.objective.locationMarker.added").param("id", objectiveLocationMarkerId));
holder.ensureComponent(HiddenFromAdventurePlayers.getComponentType()); }
store.addEntity(holder, AddReason.SPAWN);
context.sendMessage(Message.translation("server.commands.objective.locationMarker.added").param("id", objectiveLocationMarkerId));
} }
} }
} }

View File

@@ -12,6 +12,7 @@ import java.util.Map;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ObjectiveHistoryComponent implements Component<EntityStore> { public class ObjectiveHistoryComponent implements Component<EntityStore> {
@Nonnull
public static final BuilderCodec<ObjectiveHistoryComponent> CODEC = BuilderCodec.builder(ObjectiveHistoryComponent.class, ObjectiveHistoryComponent::new) public static final BuilderCodec<ObjectiveHistoryComponent> CODEC = BuilderCodec.builder(ObjectiveHistoryComponent.class, ObjectiveHistoryComponent::new)
.append( .append(
new KeyedCodec<>("ObjectiveHistory", new MapCodec<>(ObjectiveHistoryData.CODEC, Object2ObjectOpenHashMap::new, false)), new KeyedCodec<>("ObjectiveHistory", new MapCodec<>(ObjectiveHistoryData.CODEC, Object2ObjectOpenHashMap::new, false)),

View File

@@ -23,6 +23,7 @@ import java.util.logging.Level;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveAsset>> { public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveAsset>> {
@Nonnull
public static final AssetBuilderCodec<String, ObjectiveAsset> CODEC = AssetBuilderCodec.builder( public static final AssetBuilderCodec<String, ObjectiveAsset> CODEC = AssetBuilderCodec.builder(
ObjectiveAsset.class, ObjectiveAsset.class,
ObjectiveAsset::new, ObjectiveAsset::new,
@@ -87,6 +88,7 @@ public class ObjectiveAsset implements JsonAssetWithMap<String, DefaultAssetMap<
} }
}) })
.build(); .build();
@Nonnull
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveAsset::getAssetStore)); public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveAsset::getAssetStore));
private static AssetStore<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> ASSET_STORE; private static AssetStore<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> ASSET_STORE;
protected AssetExtraInfo.Data extraData; protected AssetExtraInfo.Data extraData;

View File

@@ -79,6 +79,7 @@ public class ObjectiveLineAsset implements JsonAssetWithMap<String, DefaultAsset
} }
}) })
.build(); .build();
@Nonnull
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLineAsset::getAssetStore)); public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLineAsset::getAssetStore));
private static AssetStore<String, ObjectiveLineAsset, DefaultAssetMap<String, ObjectiveLineAsset>> ASSET_STORE; private static AssetStore<String, ObjectiveLineAsset, DefaultAssetMap<String, ObjectiveLineAsset>> ASSET_STORE;
protected AssetExtraInfo.Data extraData; protected AssetExtraInfo.Data extraData;

View File

@@ -20,6 +20,7 @@ import java.util.Arrays;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> { public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> {
@Nonnull
public static final AssetBuilderCodec<String, ObjectiveLocationMarkerAsset> CODEC = AssetBuilderCodec.builder( public static final AssetBuilderCodec<String, ObjectiveLocationMarkerAsset> CODEC = AssetBuilderCodec.builder(
ObjectiveLocationMarkerAsset.class, ObjectiveLocationMarkerAsset.class,
ObjectiveLocationMarkerAsset::new, ObjectiveLocationMarkerAsset::new,
@@ -74,6 +75,7 @@ public class ObjectiveLocationMarkerAsset implements JsonAssetWithMap<String, De
} }
}) })
.build(); .build();
@Nonnull
public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLocationMarkerAsset::getAssetStore)); public static final ValidatorCache<String> VALIDATOR_CACHE = new ValidatorCache<>(new AssetKeyValidator<>(ObjectiveLocationMarkerAsset::getAssetStore));
private static AssetStore<String, ObjectiveLocationMarkerAsset, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> ASSET_STORE; private static AssetStore<String, ObjectiveLocationMarkerAsset, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> ASSET_STORE;
protected AssetExtraInfo.Data data; protected AssetExtraInfo.Data data;

View File

@@ -4,6 +4,7 @@ import com.hypixel.hytale.codec.builder.BuilderCodec;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ClearObjectiveItemsCompletionAsset extends ObjectiveCompletionAsset { public class ClearObjectiveItemsCompletionAsset extends ObjectiveCompletionAsset {
@Nonnull
public static final BuilderCodec<ClearObjectiveItemsCompletionAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<ClearObjectiveItemsCompletionAsset> CODEC = BuilderCodec.builder(
ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset::new, BASE_CODEC ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset::new, BASE_CODEC
) )

View File

@@ -8,6 +8,7 @@ import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class GiveItemsCompletionAsset extends ObjectiveCompletionAsset { public class GiveItemsCompletionAsset extends ObjectiveCompletionAsset {
@Nonnull
public static final BuilderCodec<GiveItemsCompletionAsset> CODEC = BuilderCodec.builder( public static final BuilderCodec<GiveItemsCompletionAsset> CODEC = BuilderCodec.builder(
GiveItemsCompletionAsset.class, GiveItemsCompletionAsset::new, BASE_CODEC GiveItemsCompletionAsset.class, GiveItemsCompletionAsset::new, BASE_CODEC
) )

View File

@@ -5,7 +5,9 @@ import com.hypixel.hytale.codec.lookup.CodecMapCodec;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public abstract class ObjectiveCompletionAsset { public abstract class ObjectiveCompletionAsset {
@Nonnull
public static final CodecMapCodec<ObjectiveCompletionAsset> CODEC = new CodecMapCodec<>("Type"); public static final CodecMapCodec<ObjectiveCompletionAsset> CODEC = new CodecMapCodec<>("Type");
@Nonnull
public static final BuilderCodec<ObjectiveCompletionAsset> BASE_CODEC = BuilderCodec.abstractBuilder(ObjectiveCompletionAsset.class).build(); public static final BuilderCodec<ObjectiveCompletionAsset> BASE_CODEC = BuilderCodec.abstractBuilder(ObjectiveCompletionAsset.class).build();
protected ObjectiveCompletionAsset() { protected ObjectiveCompletionAsset() {

View File

@@ -12,7 +12,9 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class ObjectiveGameplayConfig { public class ObjectiveGameplayConfig {
@Nonnull
public static final String ID = "Objective"; public static final String ID = "Objective";
@Nonnull
public static final BuilderCodec<ObjectiveGameplayConfig> CODEC = BuilderCodec.builder(ObjectiveGameplayConfig.class, ObjectiveGameplayConfig::new) public static final BuilderCodec<ObjectiveGameplayConfig> CODEC = BuilderCodec.builder(ObjectiveGameplayConfig.class, ObjectiveGameplayConfig::new)
.appendInherited( .appendInherited(
new KeyedCodec<>("StarterObjectiveLinePerWorld", new MapCodec<>(Codec.STRING, Object2ObjectOpenHashMap::new, true)), new KeyedCodec<>("StarterObjectiveLinePerWorld", new MapCodec<>(Codec.STRING, Object2ObjectOpenHashMap::new, true)),

View File

@@ -16,6 +16,7 @@ import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea { public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
@Nonnull
public static final BuilderCodec<ObjectiveLocationAreaBox> CODEC = BuilderCodec.builder(ObjectiveLocationAreaBox.class, ObjectiveLocationAreaBox::new) public static final BuilderCodec<ObjectiveLocationAreaBox> CODEC = BuilderCodec.builder(ObjectiveLocationAreaBox.class, ObjectiveLocationAreaBox::new)
.append( .append(
new KeyedCodec<>("EntryBox", Box.CODEC), new KeyedCodec<>("EntryBox", Box.CODEC),
@@ -33,7 +34,9 @@ public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
.add() .add()
.afterDecode(ObjectiveLocationAreaBox::computeAreaBoxes) .afterDecode(ObjectiveLocationAreaBox::computeAreaBoxes)
.build(); .build();
@Nonnull
private static final Box DEFAULT_ENTRY_BOX = new Box(-5.0, -5.0, -5.0, 5.0, 5.0, 5.0); 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 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 entryArea;
private Box exitArea; private Box exitArea;
@@ -115,7 +118,7 @@ public class ObjectiveLocationAreaBox extends ObjectiveLocationMarkerArea {
private static void getPlayersInArea( private static void getPlayersInArea(
@Nonnull SpatialResource<Ref<EntityStore>, EntityStore> spatialComponent, @Nonnull SpatialResource<Ref<EntityStore>, EntityStore> spatialComponent,
List<Ref<EntityStore>> results, @Nonnull List<Ref<EntityStore>> results,
@Nonnull Vector3d markerPosition, @Nonnull Vector3d markerPosition,
@Nonnull Box box @Nonnull Box box
) { ) {

View File

@@ -18,6 +18,7 @@ import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ObjectiveLocationAreaRadius extends ObjectiveLocationMarkerArea { public class ObjectiveLocationAreaRadius extends ObjectiveLocationMarkerArea {
@Nonnull
public static final BuilderCodec<ObjectiveLocationAreaRadius> CODEC = BuilderCodec.builder( public static final BuilderCodec<ObjectiveLocationAreaRadius> CODEC = BuilderCodec.builder(
ObjectiveLocationAreaRadius.class, ObjectiveLocationAreaRadius::new ObjectiveLocationAreaRadius.class, ObjectiveLocationAreaRadius::new
) )

View File

@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class SetupObjective extends ObjectiveTypeSetup { public class SetupObjective extends ObjectiveTypeSetup {
@Nonnull
public static final BuilderCodec<SetupObjective> CODEC = BuilderCodec.builder(SetupObjective.class, SetupObjective::new) public static final BuilderCodec<SetupObjective> CODEC = BuilderCodec.builder(SetupObjective.class, SetupObjective::new)
.append( .append(
new KeyedCodec<>("ObjectiveId", Codec.STRING), (setupObjective, s) -> setupObjective.objectiveId = s, setupObjective -> setupObjective.objectiveId new KeyedCodec<>("ObjectiveId", Codec.STRING), (setupObjective, s) -> setupObjective.objectiveId = s, setupObjective -> setupObjective.objectiveId

View File

@@ -15,6 +15,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class SetupObjectiveLine extends ObjectiveTypeSetup { public class SetupObjectiveLine extends ObjectiveTypeSetup {
@Nonnull
public static final BuilderCodec<SetupObjectiveLine> CODEC = BuilderCodec.builder(SetupObjectiveLine.class, SetupObjectiveLine::new) public static final BuilderCodec<SetupObjectiveLine> CODEC = BuilderCodec.builder(SetupObjectiveLine.class, SetupObjectiveLine::new)
.append( .append(
new KeyedCodec<>("ObjectiveLineId", Codec.STRING), new KeyedCodec<>("ObjectiveLineId", Codec.STRING),

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