Added Somewhat functional Transmission between storages

This commit is contained in:
2026-02-08 02:00:22 +01:00
parent 59e8fc1734
commit 3950bdab08
15 changed files with 293 additions and 104 deletions

View File

@@ -11,7 +11,7 @@ import org.KaiFlo.SolarCell.Components.EnergyConsumer.IEnergyConsumer;
import org.KaiFlo.SolarCell.SolarCellPlugin; import org.KaiFlo.SolarCell.SolarCellPlugin;
import org.checkerframework.checker.nullness.compatqual.NullableDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.LOGGER; import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
public class EnergyConsumerComponent implements Component<ChunkStore>, IEnergyConsumer { public class EnergyConsumerComponent implements Component<ChunkStore>, IEnergyConsumer {
public static final BuilderCodec<EnergyConsumerComponent> CODEC = BuilderCodec.builder(EnergyConsumerComponent.class, EnergyConsumerComponent::new) public static final BuilderCodec<EnergyConsumerComponent> CODEC = BuilderCodec.builder(EnergyConsumerComponent.class, EnergyConsumerComponent::new)
@@ -59,7 +59,7 @@ public class EnergyConsumerComponent implements Component<ChunkStore>, IEnergyCo
try { try {
super.clone(); super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
LOGGER.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); HyLogger.atWarning().log("Cloning of " + this.getClass().getName() + " failed.");
} }
return new EnergyConsumerComponent().copyFrom(this); return new EnergyConsumerComponent().copyFrom(this);
} }

View File

@@ -11,10 +11,9 @@ import org.KaiFlo.SolarCell.Components.EnergySource.IEnergySource;
import org.KaiFlo.SolarCell.SolarCellPlugin; import org.KaiFlo.SolarCell.SolarCellPlugin;
import org.checkerframework.checker.nullness.compatqual.NullableDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.LOGGER; import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
public class EnergySourceComponent implements Component<ChunkStore>, IEnergySource { public class EnergySourceComponent implements Component<ChunkStore>, IEnergySource {
@SuppressWarnings("unchecked")
public static final BuilderCodec<EnergySourceComponent> CODEC = BuilderCodec.builder(EnergySourceComponent.class, EnergySourceComponent::new) public static final BuilderCodec<EnergySourceComponent> CODEC = BuilderCodec.builder(EnergySourceComponent.class, EnergySourceComponent::new)
.append(new KeyedCodec<>("GeneratesPerTick", Codec.LONG), .append(new KeyedCodec<>("GeneratesPerTick", Codec.LONG),
(component, value) -> component.generatesPerTick = value, (component, value) -> component.generatesPerTick = value,
@@ -27,7 +26,7 @@ public class EnergySourceComponent implements Component<ChunkStore>, IEnergySour
(component, value) -> component.energyCapacity = value, (component, value) -> component.energyCapacity = value,
(component) -> component.energyCapacity (component) -> component.energyCapacity
) )
.addValidator(Validators.or(Validators.equal(-1L), Validators.greaterThanOrEqual(0L))) .addValidator(Validators.greaterThanOrEqual(-1L))
.documentation("EnergyCapacity defines how long energy can be produced (Set to -1 if endless energy production)") .documentation("EnergyCapacity defines how long energy can be produced (Set to -1 if endless energy production)")
.add() .add()
.build(); .build();
@@ -51,7 +50,7 @@ public class EnergySourceComponent implements Component<ChunkStore>, IEnergySour
try { try {
super.clone(); super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
LOGGER.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); HyLogger.atWarning().log("Cloning of " + this.getClass().getName() + " failed.");
} }
return new EnergySourceComponent().copyFrom(this); return new EnergySourceComponent().copyFrom(this);
} }

View File

@@ -11,7 +11,9 @@ import org.KaiFlo.SolarCell.Components.EnergyStorage.IEnergyStorage;
import org.KaiFlo.SolarCell.SolarCellPlugin; import org.KaiFlo.SolarCell.SolarCellPlugin;
import org.checkerframework.checker.nullness.compatqual.NullableDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.LOGGER; import java.util.Arrays;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
public class EnergyStorageComponent implements Component<ChunkStore>, IEnergyStorage { public class EnergyStorageComponent implements Component<ChunkStore>, IEnergyStorage {
public static final BuilderCodec<EnergyStorageComponent> CODEC = BuilderCodec.builder(EnergyStorageComponent.class, EnergyStorageComponent::new) public static final BuilderCodec<EnergyStorageComponent> CODEC = BuilderCodec.builder(EnergyStorageComponent.class, EnergyStorageComponent::new)
@@ -100,6 +102,12 @@ public class EnergyStorageComponent implements Component<ChunkStore>, IEnergySto
public long extractEnergy(long requiredEnergy) { public long extractEnergy(long requiredEnergy) {
var extractedEnergy = Math.min(currentEnergyAmount, Math.min(requiredEnergy, extractEnergyPerTick)); var extractedEnergy = Math.min(currentEnergyAmount, Math.min(requiredEnergy, extractEnergyPerTick));
currentEnergyAmount -= extractedEnergy; currentEnergyAmount -= extractedEnergy;
if (extractedEnergy >=1000){
HyLogger.atInfo().log("Extracted Energy: " + extractedEnergy + " now at " + currentEnergyAmount);
for (StackTraceElement element : Arrays.stream(Thread.currentThread().getStackTrace()).limit(7).toList()) {
HyLogger.atInfo().log(String.valueOf(element));
}
}
return extractedEnergy; return extractedEnergy;
} }
@@ -107,6 +115,7 @@ public class EnergyStorageComponent implements Component<ChunkStore>, IEnergySto
public long receiveEnergy(long inputEnergy) { public long receiveEnergy(long inputEnergy) {
var receivedEnergy = Math.min(maxCapacity - currentEnergyAmount, Math.min(inputEnergy, receiveEnergyPerTick)); var receivedEnergy = Math.min(maxCapacity - currentEnergyAmount, Math.min(inputEnergy, receiveEnergyPerTick));
currentEnergyAmount += receivedEnergy; currentEnergyAmount += receivedEnergy;
// HyLogger.atInfo().log("Received Energy: " + receivedEnergy + " now at " + currentEnergyAmount);
return receivedEnergy; return receivedEnergy;
} }
@@ -124,7 +133,7 @@ public class EnergyStorageComponent implements Component<ChunkStore>, IEnergySto
try { try {
super.clone(); super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
LOGGER.atWarning().log("Cloning of " + this.getClass().getName() + " failed."); HyLogger.atWarning().log("Cloning of " + this.getClass().getName() + " failed.");
} }
return new EnergyStorageComponent().copyFrom(this); return new EnergyStorageComponent().copyFrom(this);
} }

View File

@@ -5,12 +5,14 @@ import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.modules.block.BlockModule; import com.hypixel.hytale.server.core.modules.block.BlockModule;
import com.hypixel.hytale.server.core.universe.world.World;
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.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore; import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.checkerframework.checker.nullness.compatqual.NonNullDecl; import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
public class BlockHelper { public class BlockHelper {
public static final HytaleLogger LOGGER = HytaleLogger.getLogger(); public static final HytaleLogger HyLogger = HytaleLogger.getLogger();
public static void executeForCubeAround(int x, int y, int z, int size, boolean own, Callback callback) { public static void executeForCubeAround(int x, int y, int z, int size, boolean own, Callback callback) {
for (int xOffset = 0; xOffset < size; xOffset++) { for (int xOffset = 0; xOffset < size; xOffset++) {
@@ -21,17 +23,67 @@ public class BlockHelper {
var zPos = (zOffset - size / 2) + z; var zPos = (zOffset - size / 2) + z;
if (!(xPos == x && yPos == y && zPos == z)) { if (!(xPos == x && yPos == y && zPos == z)) {
callback.accept(xPos, yPos, zPos); callback.accept(xPos, yPos, zPos);
} } else if (own) {
else if (own) {
callback.accept(xPos, yPos, zPos); callback.accept(xPos, yPos, zPos);
} }
} }
} }
} }
} }
public static void executeForCubeAroundChunkSafe(
int centerX, int centerY, int centerZ,
int size,
boolean includeCenter,
World world,
CommandBuffer<ChunkStore> commandBuffer,
ChunkSafeCallback chunkSafeCallback
) {
int halfSize = size / 2;
for (int xOffset = -halfSize; xOffset <= halfSize; xOffset++) {
for (int yOffset = -halfSize; yOffset <= halfSize; yOffset++) {
for (int zOffset = -halfSize; zOffset <= halfSize; zOffset++) {
int xPos = centerX + xOffset;
int yPos = centerY + yOffset;
int zPos = centerZ + zOffset;
if (!includeCenter && xPos == centerX && yPos == centerY && zPos == centerZ) {
continue;
}
int chunkX = Math.floorDiv(xPos, 32);
int chunkZ = Math.floorDiv(zPos, 32);
int localX = Math.floorMod(xPos, 32);
int localZ = Math.floorMod(zPos, 32);
WorldChunk targetChunk = world.getChunk(ChunkUtil.indexChunk(chunkX, chunkZ));
if (targetChunk == null) continue;
var blockComponentChunk = commandBuffer.getComponent(
targetChunk.getReference(),
BlockComponentChunk.getComponentType()
);
if (blockComponentChunk == null) continue;
int index = ChunkUtil.indexBlockInColumn(localX, yPos, localZ);
var targetRef = blockComponentChunk.getEntityReference(index);
if (targetRef == null) continue;
chunkSafeCallback.accept(xPos, yPos, zPos, targetRef, blockComponentChunk, targetChunk);
}
}
}
}
public interface Callback { public interface Callback {
void accept(int x, int y, int z); void accept(int x, int y, int z);
} }
public interface ChunkSafeCallback {
void accept(int x, int y, int z, Ref<ChunkStore> targetRef, BlockComponentChunk blockComponentChunk, WorldChunk targetChunk);
}
public static void setBlockRefTicking(Ref<ChunkStore> blockRef, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) { public static void setBlockRefTicking(Ref<ChunkStore> blockRef, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
BlockModule.BlockStateInfo blockInfo = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType()); BlockModule.BlockStateInfo blockInfo = commandBuffer.getComponent(blockRef, BlockModule.BlockStateInfo.getComponentType());
@@ -45,7 +97,6 @@ public class BlockHelper {
int z = ChunkUtil.zFromBlockInColumn(blockInfo.getIndex()); int z = ChunkUtil.zFromBlockInColumn(blockInfo.getIndex());
worldChunk.setTicking(x, y, z, true); worldChunk.setTicking(x, y, z, true);
HytaleLogger.getLogger().atInfo().log(String.valueOf(worldChunk.isTicking(x, y, z)));
} }
} }

View File

@@ -0,0 +1,16 @@
package org.KaiFlo.SolarCell.Helpers;
import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import java.util.List;
import java.util.Optional;
public class ComponentHelper {
public static<T> Optional<T> getComponentOfType(List<Component<ChunkStore>> components, Class<T> type){
return components.stream()
.filter(x -> x.getClass() == type)
.map(type::cast)
.findFirst();
}
}

View File

@@ -10,9 +10,13 @@ import org.KaiFlo.SolarCell.Components.EnergyConsumer.Implementations.EnergyCons
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent; import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent; import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
import org.KaiFlo.SolarCell.Systems.EnergySource.EnergySourceInitializerSystem; import org.KaiFlo.SolarCell.Systems.EnergySource.EnergySourceInitializerSystem;
import org.KaiFlo.SolarCell.Systems.EnergySource.TickingImplementations.SolarCellSourceTicking;
import org.KaiFlo.SolarCell.Systems.EnergyStorage.EnergyStorageInitializerSystem;
import org.KaiFlo.SolarCell.Systems.EnergyStorage.TickingImplementations.BatteryStorageTicking;
import org.KaiFlo.SolarCell.Systems.EnergyTickingSystem; import org.KaiFlo.SolarCell.Systems.EnergyTickingSystem;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List;
public class SolarCellPlugin extends JavaPlugin { public class SolarCellPlugin extends JavaPlugin {
@@ -44,8 +48,13 @@ public class SolarCellPlugin extends JavaPlugin {
this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString())); this.getCommandRegistry().registerCommand(new ExampleCommand(this.getName(), this.getManifest().getVersion().toString()));
var energyTickingSystem = new EnergyTickingSystem()
.withTickingSystemForComponentTypes(List.of(energyStorageComponentType), new BatteryStorageTicking())
.withTickingSystemForComponentTypes(List.of(energySourceComponentType,energyStorageComponentType), new SolarCellSourceTicking());
this.getChunkStoreRegistry().registerSystem(new EnergySourceInitializerSystem()); this.getChunkStoreRegistry().registerSystem(new EnergySourceInitializerSystem());
this.getChunkStoreRegistry().registerSystem(new EnergyTickingSystem()); this.getChunkStoreRegistry().registerSystem(new EnergyStorageInitializerSystem());
this.getChunkStoreRegistry().registerSystem(energyTickingSystem);
} }

View File

@@ -1,12 +0,0 @@
package org.KaiFlo.SolarCell.Systems.EnergySource;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.protocol.Vector3i;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
public interface IEnergySourceTicking{
void accept (EnergySourceComponent thisEnergySource, EnergyStorageComponent thisEnergyStorage, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer);
}

View File

@@ -1,33 +0,0 @@
package org.KaiFlo.SolarCell.Systems.EnergySource;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.protocol.Vector3i;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
import org.KaiFlo.SolarCell.Helpers.BlockHelper;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.LOGGER;
public class SolarCellSourceTicking implements IEnergySourceTicking{
@Override
public void accept(EnergySourceComponent thisEnergySource, EnergyStorageComponent thisEnergyStorage, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer){
BlockHelper.executeForCubeAround(globalPosition.x, globalPosition.y, globalPosition.z, 5, false, (x, y, z) -> {
var index = ChunkUtil.indexBlockInColumn(x, y, z);
var targetRef = blockComponentChunk.getEntityReference(index);
if (targetRef == null) return;
var targetEnergySource = commandBuffer.getComponent(targetRef, EnergySourceComponent.getComponentType());
var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageComponent.getComponentType());
if (targetEnergySource == null || targetEnergyStorage == null) return;
var energy = targetEnergyStorage.extractEnergy(targetEnergySource.getGeneratesPerTick());
var inserted = thisEnergyStorage.receiveEnergy(energy);
LOGGER.atInfo().log("Inserted " + inserted + "/" + energy + " |" + targetEnergyStorage.getCurrentEnergyAmount() + "| into storage" +
" at Block " + globalPosition.x + ", " + globalPosition.y + ", " + globalPosition.z + ", " +
thisEnergyStorage.getCurrentEnergyAmount() + "/" + thisEnergyStorage.getMaxCapacity());
});
}
}

View File

@@ -0,0 +1,33 @@
package org.KaiFlo.SolarCell.Systems.EnergySource.TickingImplementations;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.protocol.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
import org.KaiFlo.SolarCell.Systems.ITickingSystem;
import java.util.List;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
import static org.KaiFlo.SolarCell.Helpers.ComponentHelper.getComponentOfType;
public class SolarCellSourceTicking implements ITickingSystem {
@Override
public void accept(List<Component<ChunkStore>> foundComponents, Archetype<ChunkStore> archetype, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer, World world) {
var energyStorage = getComponentOfType(foundComponents, EnergyStorageComponent.class).orElse(null);
if (energyStorage == null) return;
var energySource = getComponentOfType(foundComponents, EnergySourceComponent.class).orElse(null);
if (energySource == null) return;
var received = energyStorage.receiveEnergy(energySource.getGeneratesPerTick());
if (received!= 0){
HyLogger.atInfo().log("Block at " + globalPosition.x+", "+ globalPosition.y+", " +globalPosition.z+" received " + received + " Energy, now at "+energyStorage.getCurrentEnergyAmount());
}
}
}

View File

@@ -0,0 +1,31 @@
package org.KaiFlo.SolarCell.Systems.EnergyStorage;
import com.hypixel.hytale.component.*;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.system.RefSystem;
import com.hypixel.hytale.server.core.modules.block.BlockModule;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.setBlockRefTicking;
public class EnergyStorageInitializerSystem extends RefSystem<ChunkStore> {
@Override
public void onEntityAdded(@NonNullDecl Ref<ChunkStore> ref, @NonNullDecl AddReason addReason, @NonNullDecl Store<ChunkStore> store, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
setBlockRefTicking(ref, commandBuffer);
}
@Override
public void onEntityRemove(@NonNullDecl Ref ref, @NonNullDecl RemoveReason removeReason, @NonNullDecl Store store, @NonNullDecl CommandBuffer commandBuffer) {
//Nothing to do yet
}
@NullableDecl
@Override
public Query<ChunkStore> getQuery() {
return Query.and(EnergyStorageComponent.getComponentType(), BlockModule.BlockStateInfo.getComponentType());
}
}

View File

@@ -0,0 +1,54 @@
package org.KaiFlo.SolarCell.Systems.EnergyStorage.TickingImplementations;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.protocol.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
import org.KaiFlo.SolarCell.Systems.ITickingSystem;
import java.util.List;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.executeForCubeAroundChunkSafe;
import static org.KaiFlo.SolarCell.Helpers.ComponentHelper.getComponentOfType;
public class BatteryStorageTicking implements ITickingSystem {
@Override
public void accept(List<Component<ChunkStore>> foundComponents, Archetype<ChunkStore> archetype, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer, World world) {
var energyStorage = getComponentOfType(foundComponents, EnergyStorageComponent.class).orElse(null);
if (energyStorage == null) return;
var energySourceComponent = getComponentOfType(foundComponents, EnergySourceComponent.class).orElse(null);
if (energySourceComponent != null) return;
if (energyStorage.getCurrentEnergyAmount() >= energyStorage.getMaxCapacity()) {
return;
}
executeForCubeAroundChunkSafe(globalPosition.x, globalPosition.y, globalPosition.z, 5, false, world, commandBuffer,
(x, y, z, targetRef, blockCompChunk, targetChunk) -> {
var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageComponent.getComponentType());
if (targetEnergyStorage == null) return;
if (targetEnergyStorage.getCurrentEnergyAmount() < energyStorage.getCurrentEnergyAmount()) return;
long energy = targetEnergyStorage.extractEnergy(Math.min(energyStorage.getMaxCapacity()-energyStorage.getCurrentEnergyAmount(),
Math.min(
targetEnergyStorage.getExtractEnergyPerTick(),
energyStorage.getReceiveEnergyPerTick()
)));
long inserted = energyStorage.receiveEnergy(energy);
if (inserted != 0 && energyStorage.getCurrentEnergyAmount() != energyStorage.getMaxCapacity()) {
HyLogger.atInfo().log("Inserted " + inserted + "/" + energy +
" |" + targetEnergyStorage.getCurrentEnergyAmount() + "| into storage" +
" at Block " + globalPosition.x + ", " + globalPosition.y + ", " + globalPosition.z + ", " +
energyStorage.getCurrentEnergyAmount() + "/" + energyStorage.getMaxCapacity());
}
}
);
}
}

View File

@@ -1,8 +1,6 @@
package org.KaiFlo.SolarCell.Systems; package org.KaiFlo.SolarCell.Systems;
import com.hypixel.hytale.component.ArchetypeChunk; import com.hypixel.hytale.component.*;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Query; import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem; import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.util.ChunkUtil;
@@ -13,33 +11,34 @@ 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.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 org.KaiFlo.SolarCell.Components.EnergyConsumer.Implementations.EnergyConsumerComponent;
import org.KaiFlo.SolarCell.Components.EnergySource.Implementations.EnergySourceComponent;
import org.KaiFlo.SolarCell.Components.EnergyStorage.Implementations.EnergyStorageComponent;
import org.KaiFlo.SolarCell.Systems.EnergySource.IEnergySourceTicking;
import org.KaiFlo.SolarCell.Systems.EnergySource.SolarCellSourceTicking;
import org.checkerframework.checker.nullness.compatqual.NonNullDecl; import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
import org.checkerframework.checker.nullness.compatqual.NullableDecl; import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import java.util.List; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class EnergyTickingSystem extends EntityTickingSystem<ChunkStore> { public class EnergyTickingSystem extends EntityTickingSystem<ChunkStore> {
private final List<IEnergySourceTicking> energySourceTicking = List.of(new SolarCellSourceTicking());
private final Map<List<ComponentType<ChunkStore, ?>>, ITickingSystem> componentsToTickingSystem = new HashMap<>();
@Override @Override
public void tick(float v, int i, @NonNullDecl ArchetypeChunk<ChunkStore> archetypeChunk, @NonNullDecl Store<ChunkStore> store, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) { public void tick(float v, int archetypeIndex, @NonNullDecl ArchetypeChunk<ChunkStore> archetypeChunk, @NonNullDecl Store<ChunkStore> store, @NonNullDecl CommandBuffer<ChunkStore> commandBuffer) {
var blockSection = archetypeChunk.getComponent(i, BlockSection.getComponentType());
var blockSection = archetypeChunk.getComponent(archetypeIndex, BlockSection.getComponentType());
if (blockSection == null || blockSection.getTickingBlocksCount() != 0) return; if (blockSection == null || blockSection.getTickingBlocksCount() != 0) return;
var chunkSection = archetypeChunk.getComponent(i, ChunkSection.getComponentType()); var chunkSection = archetypeChunk.getComponent(archetypeIndex, ChunkSection.getComponentType());
if (chunkSection == null) return; if (chunkSection == null) return;
var blockComponentChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), BlockComponentChunk.getComponentType()); var blockComponentChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), BlockComponentChunk.getComponentType());
var worldChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), WorldChunk.getComponentType()); var worldChunk = commandBuffer.getComponent(chunkSection.getChunkColumnReference(), WorldChunk.getComponentType());
if (blockComponentChunk == null || worldChunk == null) return; if (blockComponentChunk == null || worldChunk == null) return;
blockSection.forEachTicking(blockComponentChunk, commandBuffer, chunkSection.getY(), var entrySet = componentsToTickingSystem.entrySet();
(blockCompChunk, _, localX, localY, localZ, _) -> { var foundComponentTypes = new ArrayList<ComponentType<ChunkStore, ?>>();
blockSection.forEachTicking(blockComponentChunk, commandBuffer, chunkSection.getY(), (blockCompChunk, _, localX, localY, localZ, _) -> {
var blockRef = blockCompChunk.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ)); var blockRef = blockCompChunk.getEntityReference(ChunkUtil.indexBlockInColumn(localX, localY, localZ));
if (blockRef == null) return BlockTickStrategy.IGNORED; if (blockRef == null) return BlockTickStrategy.IGNORED;
@@ -47,17 +46,26 @@ public class EnergyTickingSystem extends EntityTickingSystem<ChunkStore> {
int globalZ = localZ + (worldChunk.getZ() * 32); int globalZ = localZ + (worldChunk.getZ() * 32);
var globalPosition = new Vector3i(globalX, localY, globalZ); var globalPosition = new Vector3i(globalX, localY, globalZ);
var energySourceComponent = commandBuffer.getComponent(blockRef, EnergySourceComponent.getComponentType());
var energyConsumerComponent = commandBuffer.getComponent(blockRef, EnergyConsumerComponent.getComponentType());
var energyStorageComponent = commandBuffer.getComponent(blockRef, EnergyStorageComponent.getComponentType());
if (energySourceComponent != null && energyStorageComponent != null){ var archetype = commandBuffer.getArchetype(blockRef);
energySourceTicking.forEach(energySourceTicking -> energySourceTicking.accept(energySourceComponent, energyStorageComponent,globalPosition,blockCompChunk,commandBuffer));
return BlockTickStrategy.CONTINUE; foundComponentTypes.clear();
var foundComponents = new ArrayList<Component<ChunkStore>>();
for (int i = 0; i < archetype.length(); i++) {
var type = archetype.get(i);
if (type == null) continue;
foundComponentTypes.add(type);
foundComponents.add(commandBuffer.getComponent(blockRef, type));
} }
AtomicBoolean hasAny = new AtomicBoolean(false);
return BlockTickStrategy.IGNORED; entrySet.stream()
.filter(entry -> foundComponentTypes.containsAll(entry.getKey())).map(Map.Entry::getValue)
.forEach(tickingSystem -> {
hasAny.set(true);
tickingSystem.accept(foundComponents, archetype, globalPosition, blockCompChunk, commandBuffer, worldChunk.getWorld());
});
return hasAny.get() ? BlockTickStrategy.CONTINUE : BlockTickStrategy.IGNORED;
}); });
} }
@@ -67,4 +75,9 @@ public class EnergyTickingSystem extends EntityTickingSystem<ChunkStore> {
public Query<ChunkStore> getQuery() { public Query<ChunkStore> getQuery() {
return Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType()); return Query.and(BlockSection.getComponentType(), ChunkSection.getComponentType());
} }
public EnergyTickingSystem withTickingSystemForComponentTypes(List<ComponentType<ChunkStore, ?>> componentTypes, ITickingSystem tickingSystem) {
componentsToTickingSystem.put(componentTypes, tickingSystem);
return this;
}
} }

View File

@@ -0,0 +1,16 @@
package org.KaiFlo.SolarCell.Systems;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.protocol.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import java.util.List;
public interface ITickingSystem {
void accept(List<Component<ChunkStore>> foundComponents, Archetype<ChunkStore> archetype, Vector3i globalPosition, BlockComponentChunk blockComponentChunk, CommandBuffer<ChunkStore> commandBuffer, World world);
}

View File

@@ -18,11 +18,11 @@
"BlockType": { "BlockType": {
"BlockEntity": { "BlockEntity": {
"Components": { "Components": {
"EnergyStorageComponent": { "EnergyStorage": {
"EnergyStored": 5, "MaxCapacity": 10000,
"MaxEnergy": 80000, "ExtractEnergyPerTick": 1000,
"MaxReceive": 1000, "ReceiveEnergyPerTick": 1000,
"MaxExtract": 1000 "CurrentEnergyAmount": 100
} }
} }
}, },

View File

@@ -18,12 +18,15 @@
"BlockType": { "BlockType": {
"BlockEntity": { "BlockEntity": {
"Components": { "Components": {
"SolarCell": {}, "EnergyStorage": {
"EnergyStorageComponent": { "MaxCapacity": 10000,
"EnergyStored": 5, "ExtractEnergyPerTick": 100,
"MaxEnergy": 80000, "ReceiveEnergyPerTick": 1000,
"MaxReceive": 1000, "CurrentEnergyAmount": 0
"MaxExtract": 1000 },
"EnergySource": {
"EnergyCapacity": -1,
"GeneratesPerTick": 1000
} }
} }
}, },