Fixed EnergyStorage Bug and implemented it with directional energy extraction

This commit is contained in:
Flotschispielt
2026-02-13 22:17:46 +01:00
parent ba5f5e11b4
commit 9bd333d74f
8 changed files with 436 additions and 42 deletions

View File

@@ -0,0 +1,19 @@
package org.KaiFlo.SolarCell.Enums;
public enum BlockRotation {
NORTH,
EAST,
SOUTH,
WEST;
public static BlockRotation getEnum(int rotationIndex) {
return switch ( rotationIndex )
{
case 0 -> NORTH;
case 1 -> WEST;
case 2 -> SOUTH;
case 3 -> EAST;
default -> NORTH;
};
}
}

View File

@@ -9,6 +9,7 @@ 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.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.KaiFlo.SolarCell.Enums.BlockRotation;
import org.checkerframework.checker.nullness.compatqual.NonNullDecl; import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
import java.util.*; import java.util.*;
@@ -33,6 +34,61 @@ public class BlockHelper {
} }
} }
public static void executeForDirection(
int centerX, int centerY, int centerZ,
World world,
CommandBuffer<ChunkStore> commandBuffer,
BlockRotation direction,
ChunkSafeCallback chunkSafeCallback){
Map<Long, List<BlockPos>> positionsByChunk = new HashMap<>();
addBlockInDirectionToPositions(centerX, centerY, centerZ, direction, positionsByChunk);
addBlockDownwardToPositions(centerX, centerY, centerZ, positionsByChunk);
executeChunkSafeCallbackForPositions(world, commandBuffer, chunkSafeCallback, positionsByChunk);
}
private static void addBlockInDirectionToPositions(
int centerX, int centerY, int centerZ, BlockRotation direction, Map<Long, List<BlockPos>> positionsByChunk) {
int xPos = centerX;
int zPos = centerZ;
if(direction == BlockRotation.NORTH || direction == BlockRotation.SOUTH){
zPos += direction == BlockRotation.SOUTH ? 1 : -1;
}else{
xPos += direction == BlockRotation.EAST ? 1 : -1;
}
int chunkX = Math.floorDiv(xPos, 32);
int chunkZ = Math.floorDiv(zPos, 32);
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
int localX = Math.floorMod(xPos, 32);
int localZ = Math.floorMod(zPos, 32);
positionsByChunk
.computeIfAbsent(chunkIndex, _ -> new ArrayList<>())
.add(new BlockPos(xPos, centerY, zPos, localX, localZ));
}
private static void addBlockDownwardToPositions(
int centerX, int centerY, int centerZ, Map<Long, List<BlockPos>> positionsByChunk) {
int yPos = centerY - 1;
int chunkX = Math.floorDiv(centerX, 32);
int chunkZ = Math.floorDiv(centerZ, 32);
long chunkIndex = ChunkUtil.indexChunk(chunkX, chunkZ);
int localX = Math.floorMod(centerX, 32);
int localZ = Math.floorMod(centerZ, 32);
positionsByChunk
.computeIfAbsent(chunkIndex, _ -> new ArrayList<>())
.add(new BlockPos(centerX, yPos, centerZ, localX, localZ));
}
public static void executeForCubeAroundChunkSafe( public static void executeForCubeAroundChunkSafe(
int centerX, int centerY, int centerZ, int centerX, int centerY, int centerZ,
int size, int size,
@@ -69,40 +125,43 @@ public class BlockHelper {
} }
} }
} }
executeChunkSafeCallbackForPositions(world, commandBuffer, chunkSafeCallback, positionsByChunk);
}
private static void executeChunkSafeCallbackForPositions(World world, CommandBuffer<ChunkStore> commandBuffer, ChunkSafeCallback chunkSafeCallback, Map<Long, List<BlockPos>> positionsByChunk) {
world.execute(() -> { world.execute(() -> {
for (var entry : positionsByChunk.entrySet()) { for (var entry : positionsByChunk.entrySet()) {
long chunkIndex = entry.getKey(); long chunkIndexCI = entry.getKey();
List<BlockPos> blockPositions = entry.getValue(); List<BlockPos> blockPositions = entry.getValue();
WorldChunk chunk = world.getChunkIfLoaded(chunkIndex); WorldChunk worldChunk = world.getChunkIfLoaded(chunkIndexCI);
if (chunk == null) continue; if (worldChunk == null) continue;
var blockComponentChunk = commandBuffer.getComponent( var blockComponentChunk = commandBuffer.getComponent(
chunk.getReference(), worldChunk.getReference(),
BlockComponentChunk.getComponentType() BlockComponentChunk.getComponentType()
); );
if (blockComponentChunk == null) continue; if (blockComponentChunk == null) continue;
for (BlockPos pos : blockPositions) { for (BlockPos pos : blockPositions) {
int index = ChunkUtil.indexBlockInColumn( int index = ChunkUtil.indexBlockInColumn(
pos.localX(), pos.y(), pos.localZ() pos.localX(), pos.y(), pos.localZ()
); );
var targetRef = blockComponentChunk.getEntityReference(index); var targetRef = blockComponentChunk.getEntityReference(index);
if (targetRef == null) continue; if (targetRef == null) continue;
chunkSafeCallback.accept( chunkSafeCallback.accept(
pos.x(), pos.y(), pos.z(), pos.x(), pos.y(), pos.z(),
targetRef, targetRef,
blockComponentChunk, blockComponentChunk,
chunk worldChunk
); );
} }
} }
}); });
} }
record BlockPos(int x, int y, int z, int localX, int localZ) {} record BlockPos(int x, int y, int z, int localX, int localZ) {}
public interface Callback { public interface Callback {
void accept(int x, int y, int z); void accept(int x, int y, int z);

View File

@@ -4,18 +4,20 @@ import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Component; import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.protocol.Vector3i; import com.hypixel.hytale.protocol.Vector3i;
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.chunk.BlockComponentChunk; import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
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.NotificationUtil;
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.Enums.BlockRotation;
import org.KaiFlo.SolarCell.Systems.ITickingSystem; import org.KaiFlo.SolarCell.Systems.ITickingSystem;
import java.util.List; import java.util.List;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.HyLogger; import static org.KaiFlo.SolarCell.Helpers.BlockHelper.*;
import static org.KaiFlo.SolarCell.Helpers.BlockHelper.executeForCubeAroundChunkSafe;
import static org.KaiFlo.SolarCell.Helpers.ComponentHelper.getComponentOfType; import static org.KaiFlo.SolarCell.Helpers.ComponentHelper.getComponentOfType;
public class BatteryStorageTicking implements ITickingSystem { public class BatteryStorageTicking implements ITickingSystem {
@@ -26,41 +28,34 @@ public class BatteryStorageTicking implements ITickingSystem {
if (energyStorage == null) return; if (energyStorage == null) return;
var energySourceComponent = getComponentOfType(foundComponents, EnergySourceComponent.class).orElse(null); var energySourceComponent = getComponentOfType(foundComponents, EnergySourceComponent.class).orElse(null);
if (energySourceComponent != null) return; if (energySourceComponent != null) return;
executeForCubeAroundChunkSafe(globalPosition.x, globalPosition.y, globalPosition.z, 5, false, world, commandBuffer,
(x, y, z, targetRef, _, _) -> {
if (energyStorage.getCurrentEnergyAmount() >= energyStorage.getMaxCapacity()) {
return;
}
int blockRotationIndex = world.getBlockRotationIndex(globalPosition.x, globalPosition.y, globalPosition.z);
// HyLogger.atInfo().log("Block at " + globalPosition.x+", "+ globalPosition.y+", " +globalPosition.z+": "+blockRotationIndex);
var rotation = BlockRotation.getEnum(blockRotationIndex);
executeForDirection(globalPosition.x, globalPosition.y, globalPosition.z, world, commandBuffer, rotation,
(x, y, z, targetRef, _, _) -> {
if (energyStorage.getCurrentEnergyAmount() >= energyStorage.getMaxCapacity()) return;
var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageComponent.getComponentType()); var targetEnergyStorage = commandBuffer.getComponent(targetRef, EnergyStorageComponent.getComponentType());
if (targetEnergyStorage == null) return; if (targetEnergyStorage == null) return;
if (targetEnergyStorage.getCurrentEnergyAmount() < energyStorage.getCurrentEnergyAmount()) return; if (targetEnergyStorage.getCurrentEnergyAmount() < energyStorage.getCurrentEnergyAmount() && commandBuffer.getComponent(targetRef, EnergySourceComponent.getComponentType()) == null) return;
long diff = targetEnergyStorage.getCurrentEnergyAmount() var extractEnergy = Math.min(energyStorage.getReceiveEnergyPerTick(), targetEnergyStorage.getCurrentEnergyAmount());
- energyStorage.getCurrentEnergyAmount();
var diffWasNegative = diff < 0;
diff = Math.abs(diff);
long extractTarget = Math.min( transmitEnergy(energyStorage,targetEnergyStorage,extractEnergy,globalPosition, x, y, z);
Math.ceilDiv(diff,2),
Math.min(
targetEnergyStorage.getExtractEnergyPerTick(),
energyStorage.getReceiveEnergyPerTick()
)
);
if (extractTarget<=0){
return;
}
if (diffWasNegative) {
transmitEnergy(targetEnergyStorage,energyStorage,extractTarget,new Vector3i(x,y,z), globalPosition.x, globalPosition.y, globalPosition.z);
}else {
transmitEnergy(energyStorage,targetEnergyStorage,extractTarget,globalPosition, x, y, z);
}
//Input bei Lüftungsgitter
//INPUT index 0 --> North
//INPUT index 1 --> West
//INPUT index 2 --> South
//INPUT index 3 --> East
} }
); );
} }
private static void transmitEnergy( EnergyStorageComponent energyStorage, EnergyStorageComponent targetEnergyStorage,long extractTarget, Vector3i globalPosition, int x, int y, int z) { private static void transmitEnergy( EnergyStorageComponent energyStorage, EnergyStorageComponent targetEnergyStorage,long extractTarget, Vector3i globalPosition, int x, int y, int z) {
long energy = 1; long energy = 1;
if (extractTarget > 1 && !(energyStorage.getCurrentEnergyAmount()+1>=energyStorage.getMaxCapacity())) { if (extractTarget > 1 && !(energyStorage.getCurrentEnergyAmount()+1>=energyStorage.getMaxCapacity())) {

File diff suppressed because one or more lines are too long

View File

@@ -155,6 +155,110 @@
"doubleSided": false, "doubleSided": false,
"shadingMode": "flat" "shadingMode": "flat"
} }
},
{
"id": "4",
"name": "cube",
"position": {"x": 2, "y": 11, "z": -14},
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
"shape": {
"type": "box",
"offset": {"x": -2, "y": 5, "z": 0},
"stretch": {"x": 1, "y": 1, "z": 1},
"settings": {
"isPiece": false,
"size": {"x": 10, "y": 10, "z": 2},
"isStaticBox": true
},
"textureLayout": {
"back": {
"offset": {"x": 3, "y": 1},
"mirror": {"x": false, "y": false},
"angle": 0
},
"right": {
"offset": {"x": 0, "y": 1},
"mirror": {"x": false, "y": false},
"angle": 0
},
"front": {
"offset": {"x": 0, "y": 1},
"mirror": {"x": false, "y": false},
"angle": 0
},
"left": {
"offset": {"x": 0, "y": 1},
"mirror": {"x": false, "y": false},
"angle": 0
},
"top": {
"offset": {"x": 0, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
},
"bottom": {
"offset": {"x": 0, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
}
},
"unwrapMode": "custom",
"visible": true,
"doubleSided": false,
"shadingMode": "flat"
}
},
{
"id": "5",
"name": "cube",
"position": {"x": 0, "y": 15, "z": -15},
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1},
"shape": {
"type": "box",
"offset": {"x": 0, "y": 1, "z": 0},
"stretch": {"x": 1, "y": 1, "z": 1},
"settings": {
"isPiece": false,
"size": {"x": 6, "y": 6, "z": 2},
"isStaticBox": true
},
"textureLayout": {
"back": {
"offset": {"x": 0, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
},
"right": {
"offset": {"x": 0, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
},
"front": {
"offset": {"x": 1, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
},
"left": {
"offset": {"x": 0, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
},
"top": {
"offset": {"x": 1, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
},
"bottom": {
"offset": {"x": 1, "y": 0},
"mirror": {"x": false, "y": false},
"angle": 0
}
},
"unwrapMode": "custom",
"visible": true,
"doubleSided": false,
"shadingMode": "flat"
}
} }
], ],
"format": "prop", "format": "prop",

View File

@@ -0,0 +1,217 @@
{
"TranslationProperties": {
"Name": "server.items.Bench_Furnace.name",
"Description": "server.items.Bench_Furnace.description"
},
"Icon": "Icons/ItemsGenerated/Bench_Furnace.png",
"Categories": [
"Furniture.Benches"
],
"Recipe": {
"Input": [
{
"ResourceTypeId": "Wood_Trunk",
"Quantity": 6
},
{
"ResourceTypeId": "Rock",
"Quantity": 6
}
],
"Output": [
{
"ItemId": "Bench_Furnace",
"Metadata": {
"BlockState": {
"Type": "processingBench",
"FuelContainer": {
"Capacity": 2
}
}
}
}
],
"BenchRequirement": [
{
"Type": "Crafting",
"Categories": [
"Workbench_Crafting"
],
"Id": "Workbench"
}
],
"TimeSeconds": 3
},
"BlockType": {
"Material": "Solid",
"DrawType": "Model",
"Opacity": "Solid",
"CustomModel": "Items/EnergyStorages/EnergyStorage1.blockymodel",
"CustomModelTexture": [
{
"Texture": "Items/EnergyStorages/texture.png",
"Weight": 1
}
],
"VariantRotation": "NESW",
"Bench": {
"Type": "Processing",
"AllowNoInputProcessing": true,
"Input": [
{
"FilterValidIngredients": true
},
{
"FilterValidIngredients": true
}
],
"Fuel": [
{
"ResourceTypeId": "Fuel",
"Icon": "Icons/Processing/FuelSlotIcon.png"
}
],
"LocalOpenSoundEventId": "SFX_Furnace_Bench_Open",
"LocalCloseSoundEventId": "SFX_Furnace_Bench_Close",
"CompletedSoundEventId": "SFX_Furnace_Bench_Processing_Complete",
"EndSoundEventId": "SFX_Furnace_Bench_Processing_End",
"FailedSoundEventId": "SFX_Furnace_Bench_Processing_Failed",
"BenchUpgradeSoundEventId": "SFX_Workbench_Upgrade_Start_Default",
"BenchUpgradeCompletedSoundEventId": "SFX_Workbench_Upgrade_Complete_Default",
"ExtraOutput": {
"Outputs": [
{
"ItemId": "Ingredient_Charcoal"
}
],
"PerFuelItemsConsumed": 2,
"IgnoredFuelSources": [
{
"ItemId": "Ingredient_Charcoal"
},
{
"ItemId": "Ingredient_Fibre"
},
{
"ItemId": "Ingredient_Tree_Sap"
}
]
},
"OutputSlotsCount": 4,
"Id": "Furnace",
"TierLevels": [
{
"UpgradeRequirement": {
"Material": [
{
"ItemId": "Ingredient_Bar_Copper",
"Quantity": 5
},
{
"ItemId": "Ingredient_Bar_Iron",
"Quantity": 5
},
{
"ItemId": "Ingredient_Bar_Thorium",
"Quantity": 5
},
{
"ItemId": "Ingredient_Bar_Cobalt",
"Quantity": 5
}
],
"TimeSeconds": 3
},
"CraftingTimeReductionModifier": 0.0
},
{
"CraftingTimeReductionModifier": 0.3,
"ExtraInputSlot": 1
}
]
},
"State": {
"Id": "processingBench",
"Definitions": {
"Processing": {
"Looping": true,
"Light": {
"Color": "#B72"
},
"CustomModelTexture": [
{
"Texture": "Blocks/Benches/Furnace_Texture.png",
"Weight": 1
}
],
"Particles": [
{
"SystemId": "Fire_Furnace_On",
"TargetNodeName": "Fire",
"Scale": 0.7,
"PositionOffset": {
"X": 0,
"Z": 0.3
}
}
],
"AmbientSoundEventId": "SFX_Furnace_Bench_Processing",
"CustomModelAnimation": "Blocks/Benches/Furnace_Smelting.blockyanim"
},
"ProcessCompleted": {
"Light": {
"Color": "#B72"
},
"CustomModelTexture": [
{
"Texture": "Blocks/Benches/Furnace_Texture.png",
"Weight": 1
}
],
"AmbientSoundEventId": "SFX_Furnace_Bench_Processing",
"Looping": true,
"CustomModelAnimation": "Blocks/Benches/Furnace_Smelting.blockyanim"
}
}
},
"Gathering": {
"Breaking": {
"GatherType": "Benches"
}
},
"BlockParticleSetId": "Stone",
"ParticleColor": "#5C583E",
"Support": {
"Down": [
{
"FaceType": "Full"
}
]
},
"BlockSoundSetId": "Stone",
"Interactions": {
"Use": "Open_Processing_Bench"
}
},
"PlayerAnimationsId": "Block",
"IconProperties": {
"Scale": 0.365,
"Rotation": [
22.5,
45,
22.5
],
"Translation": [
12,
-17.4
]
},
"Tags": {
"Type": [
"Bench"
]
},
"MaxStack": 1,
"ItemLevel": 1,
"ItemSoundSetId": "ISS_Blocks_Stone"
}

View File

@@ -20,7 +20,7 @@
"Components": { "Components": {
"EnergyStorage": { "EnergyStorage": {
"MaxCapacity": 10000, "MaxCapacity": 10000,
"ExtractEnergyPerTick": 1000, "ExtractEnergyPerTick": 500,
"ReceiveEnergyPerTick": 1000, "ReceiveEnergyPerTick": 1000,
"CurrentEnergyAmount": 100 "CurrentEnergyAmount": 100
} }

View File

@@ -26,7 +26,7 @@
}, },
"EnergySource": { "EnergySource": {
"EnergyCapacity": -1, "EnergyCapacity": -1,
"GeneratesPerTick": 1 "GeneratesPerTick": 200
} }
} }
}, },