From 4cb965adb9bdd03d2b34f82df346cc9bcf5233ca Mon Sep 17 00:00:00 2001 From: Tim Kainz Date: Fri, 6 Feb 2026 17:42:04 +0100 Subject: [PATCH 1/4] Added Interfaces and SolarCellComponent --- .../{ => Commands}/ExampleCommand.java | 35 +++++----------- .../EnergySource/AbstractEnergySource.java | 18 +++++++++ .../EnergySource/IEnergySource.java | 19 +++++++++ .../Implementations/SolarCellComponent.java | 40 +++++++++++++++++++ .../org/KaiFlo/SolarCell/SolarCellPlugin.java | 3 ++ src/main/resources/manifest.json | 3 +- 6 files changed, 91 insertions(+), 27 deletions(-) rename src/main/java/org/KaiFlo/SolarCell/{ => Commands}/ExampleCommand.java (67%) create mode 100644 src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java create mode 100644 src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java create mode 100644 src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java diff --git a/src/main/java/org/KaiFlo/SolarCell/ExampleCommand.java b/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java similarity index 67% rename from src/main/java/org/KaiFlo/SolarCell/ExampleCommand.java rename to src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java index a303e6a..52ec703 100644 --- a/src/main/java/org/KaiFlo/SolarCell/ExampleCommand.java +++ b/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java @@ -1,38 +1,23 @@ -package org.KaiFlo.SolarCell; +package org.KaiFlo.SolarCell.Commands; -import com.hypixel.hytale.component.Archetype; -import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.logger.HytaleLogger; -import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3i; -import com.hypixel.hytale.protocol.BlockPlacementSettings; import com.hypixel.hytale.protocol.GameMode; import com.hypixel.hytale.server.core.Message; -import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.server.core.command.system.CommandContext; -import com.hypixel.hytale.server.core.command.system.arguments.system.ArgWrapper; import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg; -import com.hypixel.hytale.server.core.command.system.arguments.system.WrappedArg; import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; import com.hypixel.hytale.server.core.command.system.basecommands.CommandBase; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; -import com.hypixel.hytale.server.core.universe.world.accessor.ChunkAccessor; -import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk; -import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; -import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import it.unimi.dsi.fastutil.longs.LongSet; import javax.annotation.Nonnull; import java.util.Objects; -import java.util.stream.Collectors; -/** - * This is an example command that will simply print the name of the plugin in chat when used. - */ public class ExampleCommand extends CommandBase { private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); @@ -51,18 +36,16 @@ public class ExampleCommand extends CommandBase { @Override protected void executeSync(@Nonnull CommandContext ctx) { ctx.sendMessage(Message.raw("Hello from the " + pluginName + " v" + pluginVersion + " plugin!")); - World defaultWorld = Universe.get().getDefaultWorld(); - var chunkStore = Objects.requireNonNull(defaultWorld).getChunkStore(); - LongSet chunkIndexes = chunkStore.getChunkIndexes(); + World defaultWorld = Objects.requireNonNull(Universe.get().getDefaultWorld()); defaultWorld.execute(() -> { Store store = defaultWorld.getEntityStore().getStore(); - Vector3i position = Objects.requireNonNull(store.getComponent(Objects.requireNonNull(ctx.senderAsPlayerRef()), TransformComponent.getComponentType())) - .getPosition() - .toVector3i(); + var playerRef = ctx.senderAsPlayerRef(); + var playerTransform = store.getComponent(Objects.requireNonNull(playerRef), TransformComponent.getComponentType()); + Vector3i playerPosition = Objects.requireNonNull(playerTransform).getPosition().toVector3i(); var size = sizeArg.get(ctx); if (size == null) size = 5; - executeForCubeAround(position.x, position.y, position.z, size, (x, y, z) -> { + executeForCubeAround(playerPosition.x, playerPosition.y, playerPosition.z, size, (x, y, z) -> { // BlockType blockType = defaultWorld.getBlockType(x, y, z); // if (blockType != null) { // LOGGER.atInfo().log(blockType.getId() + " at " + x + "," + y + "," + z); @@ -89,8 +72,8 @@ public class ExampleCommand extends CommandBase { } } } +} - interface Callback { - void onBlockPosition(int x, int y, int z); - } +interface Callback { + void onBlockPosition(int x, int y, int z); } \ No newline at end of file diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java new file mode 100644 index 0000000..7cf3d26 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/AbstractEnergySource.java @@ -0,0 +1,18 @@ +package org.KaiFlo.SolarCell.Components.EnergySource; + +public class AbstractEnergySource implements IEnergySource{ + @Override + public boolean isEndless() { + return true; + } + + @Override + public long getEnergyCapacity() { + return -1; + } + + @Override + public long getEnergyRatePerTick() { + return 1; + } +} diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java new file mode 100644 index 0000000..628f2fc --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/IEnergySource.java @@ -0,0 +1,19 @@ +package org.KaiFlo.SolarCell.Components.EnergySource; + +public interface IEnergySource { + + /** + * @return True if energy source is endless, False otherwise + */ + boolean isEndless(); + + /** + * @return If the energy source is not endless, returns the Capacity of the energy source, otherwise -1 + */ + long getEnergyCapacity(); + + /** + * @return The amount of energy the source produces per Tick + */ + long getEnergyRatePerTick(); +} diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java new file mode 100644 index 0000000..44207f4 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java @@ -0,0 +1,40 @@ +package org.KaiFlo.SolarCell.Components.EnergySource.Implementations; + +import com.hypixel.hytale.codec.builder.BuilderCodec; +import com.hypixel.hytale.component.Component; +import com.hypixel.hytale.logger.HytaleLogger; +import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; +import org.KaiFlo.SolarCell.Components.EnergySource.AbstractEnergySource; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; + +public class SolarCellComponent extends AbstractEnergySource implements Component { + public static final BuilderCodec CODEC = BuilderCodec.builder(SolarCellComponent.class, SolarCellComponent::new).build(); + + private final HytaleLogger Logger = HytaleLogger.getLogger(); + private long energyRatePerTick = 5; + + private SolarCellComponent copyFrom(SolarCellComponent other) { + this.energyRatePerTick = other.energyRatePerTick; + return this; + } + + @NullableDecl + @Override + public Component clone() { + try { + super.clone(); + } catch (CloneNotSupportedException e) { + Logger.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); + } + return new SolarCellComponent().copyFrom(this); + } + + @Override + public long getEnergyRatePerTick() { + return energyRatePerTick; + } + + public void setEnergyRatePerTick(long energyRatePerTick) { + this.energyRatePerTick = energyRatePerTick; + } +} diff --git a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java index 17a9734..9cf65aa 100644 --- a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java +++ b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java @@ -3,6 +3,8 @@ package org.KaiFlo.SolarCell; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import org.KaiFlo.SolarCell.Commands.ExampleCommand; +import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; import javax.annotation.Nonnull; @@ -25,5 +27,6 @@ public class SolarCellPlugin extends JavaPlugin { protected void setup() { LOGGER.atInfo().log("Setting up plugin " + this.getName()); this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString())); + this.getChunkStoreRegistry().registerComponent(SolarCellComponent.class,"SolarCell",SolarCellComponent.CODEC); } } \ No newline at end of file diff --git a/src/main/resources/manifest.json b/src/main/resources/manifest.json index 0773ced..675ff8e 100644 --- a/src/main/resources/manifest.json +++ b/src/main/resources/manifest.json @@ -14,7 +14,8 @@ "Website": "https://github.com/KainTim/hytale-solar-cell-plugin", "ServerVersion": "*", "Dependencies": { - + "Hytale:EntityModule": "*", + "Hytale:BlockModule": "*" }, "OptionalDependencies": { From 6fc02d82b4220f7d4dc86167ab332db2d487b4cf Mon Sep 17 00:00:00 2001 From: Tim Kainz Date: Fri, 6 Feb 2026 18:14:31 +0100 Subject: [PATCH 2/4] Added SolarCellInitializer --- .../Implementations/SolarCellComponent.java | 6 +++ .../org/KaiFlo/SolarCell/SolarCellPlugin.java | 29 +++++++++---- .../EnergySource/SolarCellInitializer.java | 41 +++++++++++++++++++ 3 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java index 44207f4..eccc36b 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java @@ -2,9 +2,11 @@ package org.KaiFlo.SolarCell.Components.EnergySource.Implementations; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.component.Component; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.KaiFlo.SolarCell.Components.EnergySource.AbstractEnergySource; +import org.KaiFlo.SolarCell.SolarCellPlugin; import org.checkerframework.checker.nullness.compatqual.NullableDecl; public class SolarCellComponent extends AbstractEnergySource implements Component { @@ -13,6 +15,10 @@ public class SolarCellComponent extends AbstractEnergySource implements Componen private final HytaleLogger Logger = HytaleLogger.getLogger(); private long energyRatePerTick = 5; + public static ComponentType getComponentType() { + return SolarCellPlugin.get().getSolarCellComponentType(); + } + private SolarCellComponent copyFrom(SolarCellComponent other) { this.energyRatePerTick = other.energyRatePerTick; return this; diff --git a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java index 9cf65aa..2d332cf 100644 --- a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java +++ b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java @@ -1,23 +1,28 @@ package org.KaiFlo.SolarCell; +import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; +import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.KaiFlo.SolarCell.Commands.ExampleCommand; import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; +import org.KaiFlo.SolarCell.Systems.EnergySource.SolarCellInitializer; import javax.annotation.Nonnull; -/** - * This class serves as the entrypoint for your plugin. Use the setup method to register into game registries or add - * event listeners. - */ - -@SuppressWarnings("unused") public class SolarCellPlugin extends JavaPlugin { + protected static SolarCellPlugin instance; + + public static SolarCellPlugin get() { + return instance; + } + private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); + private ComponentType solarCellComponentType; + public SolarCellPlugin(@Nonnull JavaPluginInit init) { super(init); LOGGER.atInfo().log("Hello from " + this.getName() + " version " + this.getManifest().getVersion().toString()); @@ -25,8 +30,18 @@ public class SolarCellPlugin extends JavaPlugin { @Override protected void setup() { + instance = this; LOGGER.atInfo().log("Setting up plugin " + this.getName()); + + solarCellComponentType = this.getChunkStoreRegistry().registerComponent(SolarCellComponent.class, "SolarCell", SolarCellComponent.CODEC); + this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString())); - this.getChunkStoreRegistry().registerComponent(SolarCellComponent.class,"SolarCell",SolarCellComponent.CODEC); + + this.getChunkStoreRegistry().registerSystem(new SolarCellInitializer()); + + } + + public ComponentType getSolarCellComponentType() { + return solarCellComponentType; } } \ No newline at end of file diff --git a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java new file mode 100644 index 0000000..b331272 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java @@ -0,0 +1,41 @@ +package org.KaiFlo.SolarCell.Systems.EnergySource; + +import com.hypixel.hytale.component.*; +import com.hypixel.hytale.component.query.Query; +import com.hypixel.hytale.component.system.RefSystem; +import com.hypixel.hytale.math.util.ChunkUtil; +import com.hypixel.hytale.server.core.modules.block.BlockModule; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; +import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; +import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; +import org.checkerframework.checker.nullness.compatqual.NonNullDecl; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; + +public class SolarCellInitializer extends RefSystem { + @Override + public void onEntityAdded(@NonNullDecl Ref ref, @NonNullDecl AddReason addReason, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) { + BlockModule.BlockStateInfo blockInfo = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); + if(blockInfo == null) return; + + WorldChunk worldChunk = commandBuffer.getComponent(blockInfo.getChunkRef(), WorldChunk.getComponentType()); + if(worldChunk == null) return; + + int x = ChunkUtil.xFromBlockInColumn(blockInfo.getIndex()); + int y = ChunkUtil.yFromBlockInColumn(blockInfo.getIndex()); + int z = ChunkUtil.zFromBlockInColumn(blockInfo.getIndex()); + + worldChunk.setTicking(x, y, z, true); + } + + + @Override + public void onEntityRemove(@NonNullDecl Ref ref, @NonNullDecl RemoveReason removeReason, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) { + //Nothing to do yet + } + + @NullableDecl + @Override + public Query getQuery() { + return Query.and(SolarCellComponent.getComponentType(), BlockModule.BlockStateInfo.getComponentType()); + } +} From 486254b6dde2206c51e9c71d7f3333d58691a6e3 Mon Sep 17 00:00:00 2001 From: Tim Kainz Date: Sat, 7 Feb 2026 00:24:59 +0100 Subject: [PATCH 3/4] Added SolarCell Ticking System --- .../SolarCell/Commands/ExampleCommand.java | 17 +---- .../KaiFlo/SolarCell/Helpers/BlockHelper.java | 19 ++++++ .../org/KaiFlo/SolarCell/SolarCellPlugin.java | 2 + .../EnergySource/SolarCellTickingSystem.java | 59 +++++++++++++++++ .../Server/Item/Items/SolarCell.json | 66 +++++++++++++++++++ 5 files changed, 148 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java create mode 100644 src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java create mode 100644 src/main/resources/Server/Item/Items/SolarCell.json diff --git a/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java b/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java index 52ec703..2bf37f3 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java +++ b/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java @@ -13,7 +13,7 @@ import com.hypixel.hytale.server.core.modules.entity.component.TransformComponen import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; -import it.unimi.dsi.fastutil.longs.LongSet; +import org.KaiFlo.SolarCell.Helpers.BlockHelper; import javax.annotation.Nonnull; import java.util.Objects; @@ -45,7 +45,7 @@ public class ExampleCommand extends CommandBase { Vector3i playerPosition = Objects.requireNonNull(playerTransform).getPosition().toVector3i(); var size = sizeArg.get(ctx); if (size == null) size = 5; - executeForCubeAround(playerPosition.x, playerPosition.y, playerPosition.z, size, (x, y, z) -> { + BlockHelper.executeForCubeAround(playerPosition.x, playerPosition.y, playerPosition.z, size, (x, y, z) -> { // BlockType blockType = defaultWorld.getBlockType(x, y, z); // if (blockType != null) { // LOGGER.atInfo().log(blockType.getId() + " at " + x + "," + y + "," + z); @@ -63,17 +63,4 @@ public class ExampleCommand extends CommandBase { }); } - void executeForCubeAround(int x, int y, int z, int size, Callback callback) { - for (int x1 = x - size / 2; x1 < x + size / 2; x1++) { - for (int y1 = y - size / 2; y1 < y + size / 2; y1++) { - for (int z1 = z - size / 2; z1 < z + size / 2; z1++) { - callback.onBlockPosition(x1, y1, z1); - } - } - } - } } - -interface Callback { - void onBlockPosition(int x, int y, int z); -} \ No newline at end of file diff --git a/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java b/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java new file mode 100644 index 0000000..c107577 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java @@ -0,0 +1,19 @@ +package org.KaiFlo.SolarCell.Helpers; + +public class BlockHelper { + + public static void executeForCubeAround(int x, int y, int z, int size, Callback callback) { + for (int x1 = x - size / 2; x1 < x + size / 2; x1++) { + for (int y1 = y - size / 2; y1 < y + size / 2; y1++) { + for (int z1 = z - size / 2; z1 < z + size / 2; z1++) { + callback.accept(x1, y1, z1); + } + } + } + } + public interface Callback { + void accept(int x, int y, int z); + } +} + + diff --git a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java index 2d332cf..c88f6b1 100644 --- a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java +++ b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java @@ -8,6 +8,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.KaiFlo.SolarCell.Commands.ExampleCommand; import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; import org.KaiFlo.SolarCell.Systems.EnergySource.SolarCellInitializer; +import org.KaiFlo.SolarCell.Systems.EnergySource.SolarCellTickingSystem; import javax.annotation.Nonnull; @@ -38,6 +39,7 @@ public class SolarCellPlugin extends JavaPlugin { this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString())); this.getChunkStoreRegistry().registerSystem(new SolarCellInitializer()); + this.getChunkStoreRegistry().registerSystem(new SolarCellTickingSystem()); } diff --git a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java new file mode 100644 index 0000000..0cdaa10 --- /dev/null +++ b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java @@ -0,0 +1,59 @@ +package org.KaiFlo.SolarCell.Systems.EnergySource; + +import com.hypixel.hytale.component.ArchetypeChunk; +import com.hypixel.hytale.component.CommandBuffer; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.component.query.Query; +import com.hypixel.hytale.component.system.tick.EntityTickingSystem; +import com.hypixel.hytale.math.util.ChunkUtil; +import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy; +import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk; +import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; +import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection; +import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; +import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; +import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; +import org.checkerframework.checker.nullness.compatqual.NonNullDecl; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; + +public class SolarCellTickingSystem extends EntityTickingSystem { + + @Override + public void tick(float v, int i, @NonNullDecl ArchetypeChunk archetypeChunk, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) { + var blockSection = archetypeChunk.getComponent(i, BlockSection.getComponentType()); + if (blockSection == null || blockSection.getTickingBlocksCount() != 0) return; + + var chunkSection = archetypeChunk.getComponent(i, ChunkSection.getComponentType()); + if (chunkSection == null) return; + + var blockComponentChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), BlockComponentChunk.getComponentType()); + var worldChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), WorldChunk.getComponentType()); + if (blockComponentChunk == null || worldChunk == null) return; + + var world = worldChunk.getWorld(); + + blockSection.forEachTicking(blockComponentChunk, commandBuffer, chunkSection.getY(), + (_, _, localX, localY, localZ, _) -> { + var blockRef = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ)); + if (blockRef == null) return BlockTickStrategy.IGNORED; + var solarCellComponent = commandBuffer.getComponent(blockRef, SolarCellComponent.getComponentType()); + if (solarCellComponent == null) return BlockTickStrategy.IGNORED; + + int globalX = localX + (worldChunk.getX() * 32); + int globalZ = localZ + (worldChunk.getZ() * 32); + + world.execute(() -> { + world.setBlock(globalX + 1, localY, globalZ, "Rock_Ice"); + }); + + return BlockTickStrategy.CONTINUE; + }); + + } + + @NullableDecl + @Override + public Query getQuery() { + return Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType()); + } +} diff --git a/src/main/resources/Server/Item/Items/SolarCell.json b/src/main/resources/Server/Item/Items/SolarCell.json new file mode 100644 index 0000000..5c94050 --- /dev/null +++ b/src/main/resources/Server/Item/Items/SolarCell.json @@ -0,0 +1,66 @@ +{ + "TranslationProperties": { + "Name": "server.items.Rock_Stone.name" + }, + "ItemLevel": 10, + "MaxStack": 100, + "Icon": "Icons/ItemsGenerated/Rock_Stone_Stalactite_Small.png", + "Categories": [ + "Blocks.Rocks" + ], + "PlayerAnimationsId": "Block", + "Set": "Rock_Stone", + "BlockType": { + "Material": "Solid", + "DrawType": "Cube", + "Group": "Stone", + "Flags": {}, + "Gathering": { + "Breaking": { + "GatherType": "Rocks", + "ItemId": "Rock_Stone_Cobble" + } + }, + "BlockParticleSetId": "Stone", + "Textures": [ + { + "All": "BlockTextures/Rock_Stone.png", + "Weight": 2 + }, + { + "All": "BlockTextures/Rock_Stone_2.png", + "Weight": 1 + }, + { + "All": "BlockTextures/Rock_Stone_3.png", + "Weight": 1 + } + ], + "ParticleColor": "#737055", + "BlockSoundSetId": "Stone", + "Aliases": [ + "stone", + "stone00" + ], + "BlockBreakingDecalId": "Breaking_Decals_Rock", + "BlockEntity": { + "Components": { + "SolarCell": {} + } + } + }, + "ResourceTypes": [ + { + "Id": "Rock" + }, + { + "Id": "Rock_Stone" + } + ], + "Tags": { + "Type": [ + "Rock" + ] + }, + "ItemSoundSetId": "ISS_Blocks_Stone" +} From 75900d50f9c77b1c16c87f9e780037eade030235 Mon Sep 17 00:00:00 2001 From: Tim Kainz Date: Sat, 7 Feb 2026 01:58:54 +0100 Subject: [PATCH 4/4] Implemented transfering between two Solarpanels --- .../SolarCell/Commands/ExampleCommand.java | 2 +- ...ponent.java => EnergySourceComponent.java} | 10 +++--- .../KaiFlo/SolarCell/Helpers/BlockHelper.java | 9 +++-- .../org/KaiFlo/SolarCell/SolarCellPlugin.java | 16 ++++----- ....java => EnergyProducerTickingSystem.java} | 35 +++++++++++++------ ...ava => EnergySourceInitializerSystem.java} | 8 +++-- .../Server/Item/Items/SolarCell.json | 8 ++++- 7 files changed, 58 insertions(+), 30 deletions(-) rename src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/{SolarCellComponent.java => EnergySourceComponent.java} (73%) rename src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/{SolarCellTickingSystem.java => EnergyProducerTickingSystem.java} (52%) rename src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/{SolarCellInitializer.java => EnergySourceInitializerSystem.java} (82%) diff --git a/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java b/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java index 2bf37f3..73b4ebc 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java +++ b/src/main/java/org/KaiFlo/SolarCell/Commands/ExampleCommand.java @@ -45,7 +45,7 @@ public class ExampleCommand extends CommandBase { Vector3i playerPosition = Objects.requireNonNull(playerTransform).getPosition().toVector3i(); var size = sizeArg.get(ctx); if (size == null) size = 5; - BlockHelper.executeForCubeAround(playerPosition.x, playerPosition.y, playerPosition.z, size, (x, y, z) -> { + BlockHelper.executeForCubeAround(playerPosition.x, playerPosition.y, playerPosition.z, size,true, (x, y, z) -> { // BlockType blockType = defaultWorld.getBlockType(x, y, z); // if (blockType != null) { // LOGGER.atInfo().log(blockType.getId() + " at " + x + "," + y + "," + z); diff --git a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java similarity index 73% rename from src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java rename to src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java index eccc36b..1a0fcd2 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/SolarCellComponent.java +++ b/src/main/java/org/KaiFlo/SolarCell/Components/EnergySource/Implementations/EnergySourceComponent.java @@ -9,17 +9,17 @@ import org.KaiFlo.SolarCell.Components.EnergySource.AbstractEnergySource; import org.KaiFlo.SolarCell.SolarCellPlugin; import org.checkerframework.checker.nullness.compatqual.NullableDecl; -public class SolarCellComponent extends AbstractEnergySource implements Component { - public static final BuilderCodec CODEC = BuilderCodec.builder(SolarCellComponent.class, SolarCellComponent::new).build(); +public class EnergySourceComponent extends AbstractEnergySource implements Component { + public static final BuilderCodec CODEC = BuilderCodec.builder(EnergySourceComponent.class, EnergySourceComponent::new).build(); private final HytaleLogger Logger = HytaleLogger.getLogger(); private long energyRatePerTick = 5; - public static ComponentType getComponentType() { + public static ComponentType getComponentType() { return SolarCellPlugin.get().getSolarCellComponentType(); } - private SolarCellComponent copyFrom(SolarCellComponent other) { + private EnergySourceComponent copyFrom(EnergySourceComponent other) { this.energyRatePerTick = other.energyRatePerTick; return this; } @@ -32,7 +32,7 @@ public class SolarCellComponent extends AbstractEnergySource implements Componen } catch (CloneNotSupportedException e) { Logger.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); } - return new SolarCellComponent().copyFrom(this); + return new EnergySourceComponent().copyFrom(this); } @Override diff --git a/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java b/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java index c107577..83f60f2 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java +++ b/src/main/java/org/KaiFlo/SolarCell/Helpers/BlockHelper.java @@ -2,11 +2,16 @@ package org.KaiFlo.SolarCell.Helpers; public class BlockHelper { - public static void executeForCubeAround(int x, int y, int z, int size, Callback callback) { + public static void executeForCubeAround(int x, int y, int z, int size, boolean own, Callback callback) { for (int x1 = x - size / 2; x1 < x + size / 2; x1++) { for (int y1 = y - size / 2; y1 < y + size / 2; y1++) { for (int z1 = z - size / 2; z1 < z + size / 2; z1++) { - callback.accept(x1, y1, z1); + if (!(x1 == x && y1 == y && z1 == z)) { + callback.accept(x1, y1, z1); + } + else if (own) { + callback.accept(x1, y1, z1); + } } } } diff --git a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java index c88f6b1..8bfa2ed 100644 --- a/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java +++ b/src/main/java/org/KaiFlo/SolarCell/SolarCellPlugin.java @@ -6,9 +6,9 @@ import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import org.KaiFlo.SolarCell.Commands.ExampleCommand; -import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; -import org.KaiFlo.SolarCell.Systems.EnergySource.SolarCellInitializer; -import org.KaiFlo.SolarCell.Systems.EnergySource.SolarCellTickingSystem; +import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent; +import org.KaiFlo.SolarCell.Systems.EnergySource.EnergySourceInitializerSystem; +import org.KaiFlo.SolarCell.Systems.EnergySource.EnergyProducerTickingSystem; import javax.annotation.Nonnull; @@ -22,7 +22,7 @@ public class SolarCellPlugin extends JavaPlugin { private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass(); - private ComponentType solarCellComponentType; + private ComponentType solarCellComponentType; public SolarCellPlugin(@Nonnull JavaPluginInit init) { super(init); @@ -34,16 +34,16 @@ public class SolarCellPlugin extends JavaPlugin { instance = this; LOGGER.atInfo().log("Setting up plugin " + this.getName()); - solarCellComponentType = this.getChunkStoreRegistry().registerComponent(SolarCellComponent.class, "SolarCell", SolarCellComponent.CODEC); + solarCellComponentType = this.getChunkStoreRegistry().registerComponent(EnergySourceComponent.class, "SolarCell", EnergySourceComponent.CODEC); this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString())); - this.getChunkStoreRegistry().registerSystem(new SolarCellInitializer()); - this.getChunkStoreRegistry().registerSystem(new SolarCellTickingSystem()); + this.getChunkStoreRegistry().registerSystem(new EnergySourceInitializerSystem()); + this.getChunkStoreRegistry().registerSystem(new EnergyProducerTickingSystem()); } - public ComponentType getSolarCellComponentType() { + public ComponentType getSolarCellComponentType() { return solarCellComponentType; } } \ No newline at end of file diff --git a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java similarity index 52% rename from src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java rename to src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java index 0cdaa10..21b6106 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellTickingSystem.java +++ b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergyProducerTickingSystem.java @@ -5,6 +5,7 @@ import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.tick.EntityTickingSystem; +import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickStrategy; import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk; @@ -12,11 +13,14 @@ import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection; import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; -import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; +import dev.zkiller.energystorage.components.EnergyStorageBlockComponent; +import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent; +import org.KaiFlo.SolarCell.Helpers.BlockHelper; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl; -public class SolarCellTickingSystem extends EntityTickingSystem { +public class EnergyProducerTickingSystem extends EntityTickingSystem { + private final HytaleLogger LOGGER = HytaleLogger.getLogger(); @Override public void tick(float v, int i, @NonNullDecl ArchetypeChunk archetypeChunk, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) { @@ -30,20 +34,31 @@ public class SolarCellTickingSystem extends EntityTickingSystem { var worldChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), WorldChunk.getComponentType()); if (blockComponentChunk == null || worldChunk == null) return; - var world = worldChunk.getWorld(); - blockSection.forEachTicking(blockComponentChunk, commandBuffer, chunkSection.getY(), - (_, _, localX, localY, localZ, _) -> { - var blockRef = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ)); + (blockCompChunk, _, localX, localY, localZ, _) -> { + var blockRef = blockCompChunk.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ)); if (blockRef == null) return BlockTickStrategy.IGNORED; - var solarCellComponent = commandBuffer.getComponent(blockRef, SolarCellComponent.getComponentType()); - if (solarCellComponent == null) return BlockTickStrategy.IGNORED; + var thisEnergySourceComponent = commandBuffer.getComponent(blockRef, EnergySourceComponent.getComponentType()); + var thisEnergyStorageComponent = commandBuffer.getComponent(blockRef, EnergyStorageBlockComponent.getComponentType()); + if (thisEnergySourceComponent == null || thisEnergyStorageComponent == null) + return BlockTickStrategy.IGNORED; int globalX = localX + (worldChunk.getX() * 32); int globalZ = localZ + (worldChunk.getZ() * 32); - world.execute(() -> { - world.setBlock(globalX + 1, localY, globalZ, "Rock_Ice"); + BlockHelper.executeForCubeAround(globalX, localY, globalZ, 5, false, (x, y, z) -> { + var index = ChunkUtil.indexBlockInColumn(x, y, z); + var targetRef = blockCompChunk.getEntityReference(index); + if (targetRef == null) return; + var targetEnergySource = commandBuffer.getComponent(targetRef, EnergySourceComponent.getComponentType()); + var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageBlockComponent.getComponentType()); + if (targetEnergySource == null || targetEnergyStorage == null) return; + + var energy = targetEnergyStorage.extractEnergy(targetEnergySource.getEnergyRatePerTick(), false); + var inserted = thisEnergyStorageComponent.receiveEnergy(energy, false); + LOGGER.atInfo().log("Inserted " + inserted + "/" + energy + " |" + targetEnergyStorage.getEnergyStored() + "| into storage" + + " at Block " + globalX + ", " + localY + ", " + globalZ + ", " + + thisEnergyStorageComponent.getEnergyStored() + "/" + thisEnergyStorageComponent.getMaxEnergyStored()); }); return BlockTickStrategy.CONTINUE; diff --git a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergySourceInitializerSystem.java similarity index 82% rename from src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java rename to src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergySourceInitializerSystem.java index b331272..1a5a24e 100644 --- a/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/SolarCellInitializer.java +++ b/src/main/java/org/KaiFlo/SolarCell/Systems/EnergySource/EnergySourceInitializerSystem.java @@ -3,15 +3,16 @@ package org.KaiFlo.SolarCell.Systems.EnergySource; import com.hypixel.hytale.component.*; import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.system.RefSystem; +import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.server.core.modules.block.BlockModule; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; -import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.SolarCellComponent; +import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent; import org.checkerframework.checker.nullness.compatqual.NonNullDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl; -public class SolarCellInitializer extends RefSystem { +public class EnergySourceInitializerSystem extends RefSystem { @Override public void onEntityAdded(@NonNullDecl Ref ref, @NonNullDecl AddReason addReason, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) { BlockModule.BlockStateInfo blockInfo = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType()); @@ -25,6 +26,7 @@ public class SolarCellInitializer extends RefSystem { int z = ChunkUtil.zFromBlockInColumn(blockInfo.getIndex()); worldChunk.setTicking(x, y, z, true); + HytaleLogger.getLogger().atInfo().log(String.valueOf(worldChunk.isTicking(x, y, z))); } @@ -36,6 +38,6 @@ public class SolarCellInitializer extends RefSystem { @NullableDecl @Override public Query getQuery() { - return Query.and(SolarCellComponent.getComponentType(), BlockModule.BlockStateInfo.getComponentType()); + return Query.and(EnergySourceComponent.getComponentType(), BlockModule.BlockStateInfo.getComponentType()); } } diff --git a/src/main/resources/Server/Item/Items/SolarCell.json b/src/main/resources/Server/Item/Items/SolarCell.json index 5c94050..1eead07 100644 --- a/src/main/resources/Server/Item/Items/SolarCell.json +++ b/src/main/resources/Server/Item/Items/SolarCell.json @@ -45,7 +45,13 @@ "BlockBreakingDecalId": "Breaking_Decals_Rock", "BlockEntity": { "Components": { - "SolarCell": {} + "SolarCell": {}, + "EnergyStorageComponent": { + "EnergyStored": 5, + "MaxEnergy": 80000, + "MaxReceive": 1000, + "MaxExtract": 1000 + } } } },