Fix Energy System Bugs
All checks were successful
EnergonRelics/pipeline/head This commit looks good

This commit is contained in:
TheBrokenRail 2020-07-24 13:25:50 -04:00
parent 57e1a1c40f
commit a86581d913
9 changed files with 90 additions and 99 deletions

View File

@ -11,6 +11,7 @@ import net.minecraft.entity.LightningEntity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Random; import java.util.Random;
@ -49,7 +50,7 @@ public class LightningRodBlockEntity extends EnergyProviderBlockEntity implement
} }
@Override @Override
protected void serverTick() { public List<EnergyProviderBlockEntity> startTick() {
if (cooldown <= 0) { if (cooldown <= 0) {
energy = 0; energy = 0;
@ -68,7 +69,7 @@ public class LightningRodBlockEntity extends EnergyProviderBlockEntity implement
} else { } else {
cooldown--; cooldown--;
} }
super.serverTick(); return super.startTick();
} }
@Override @Override

View File

@ -1,11 +1,13 @@
package com.thebrokenrail.energonrelics.block.entity; package com.thebrokenrail.energonrelics.block.entity;
import com.thebrokenrail.energonrelics.config.HardcodedConfig; import com.thebrokenrail.energonrelics.config.HardcodedConfig;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import com.thebrokenrail.energonrelics.energy.helper.EnergyGeneratorBlockEntity; import com.thebrokenrail.energonrelics.energy.helper.EnergyGeneratorBlockEntity;
import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
import java.util.List;
import java.util.Objects; import java.util.Objects;
public class SolarPanelBlockEntity extends EnergyGeneratorBlockEntity { public class SolarPanelBlockEntity extends EnergyGeneratorBlockEntity {
@ -37,8 +39,8 @@ public class SolarPanelBlockEntity extends EnergyGeneratorBlockEntity {
} }
@Override @Override
protected void serverTick() { public List<EnergyProviderBlockEntity> startTick() {
setEnergy(getDisplayEnergy()); setEnergy(getDisplayEnergy());
super.serverTick(); return super.startTick();
} }
} }

View File

@ -5,6 +5,7 @@ import com.thebrokenrail.energonrelics.EnergonRelics;
import com.thebrokenrail.energonrelics.block.battery.PassiveBatteryControllerBlock; import com.thebrokenrail.energonrelics.block.battery.PassiveBatteryControllerBlock;
import com.thebrokenrail.energonrelics.block.entity.battery.PassiveBatteryControllerBlockEntity; import com.thebrokenrail.energonrelics.block.entity.battery.PassiveBatteryControllerBlockEntity;
import com.thebrokenrail.energonrelics.block.reactor.ReactorControllerBlock; import com.thebrokenrail.energonrelics.block.reactor.ReactorControllerBlock;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import com.thebrokenrail.energonrelics.energy.helper.EnergyGeneratorBlockEntity; import com.thebrokenrail.energonrelics.energy.helper.EnergyGeneratorBlockEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
@ -32,7 +33,7 @@ public class ReactorControllerBlockEntity extends EnergyGeneratorBlockEntity {
} }
@Override @Override
protected void serverTick() { public List<EnergyProviderBlockEntity> startTick() {
if (getCachedState().get(ReactorControllerBlock.POWERED)) { if (getCachedState().get(ReactorControllerBlock.POWERED)) {
Reactor reactor = getReactor(); Reactor reactor = getReactor();
if (reactor != null && !reactor.core.isReacting()) { if (reactor != null && !reactor.core.isReacting()) {
@ -62,7 +63,7 @@ public class ReactorControllerBlockEntity extends EnergyGeneratorBlockEntity {
} }
} }
setEnergy(getDisplayEnergy()); setEnergy(getDisplayEnergy());
super.serverTick(); return super.startTick();
} }
@Override @Override

View File

@ -1,7 +1,7 @@
package com.thebrokenrail.energonrelics.component; package com.thebrokenrail.energonrelics.component;
import com.thebrokenrail.energonrelics.EnergonRelics; import com.thebrokenrail.energonrelics.EnergonRelics;
import com.thebrokenrail.energonrelics.energy.core.util.EnergyProvider; import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import com.thebrokenrail.energonrelics.util.BlockPosWithDimension; import com.thebrokenrail.energonrelics.util.BlockPosWithDimension;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.datafixer.NbtOps; import net.minecraft.datafixer.NbtOps;
@ -112,18 +112,18 @@ public class NetworkComponent extends PersistentState {
return entry.sources; return entry.sources;
} }
public List<EnergyProvider> getSource(World world, int id) { public List<EnergyProviderBlockEntity> getSource(World world, int id) {
List<BlockPosWithDimension> sources = getSourcePos(id); List<BlockPosWithDimension> sources = getSourcePos(id);
List<BlockPosWithDimension> valid = new ArrayList<>(); List<BlockPosWithDimension> valid = new ArrayList<>();
Iterator<BlockPosWithDimension> iterator = sources.iterator(); Iterator<BlockPosWithDimension> iterator = sources.iterator();
List<EnergyProvider> providers = new ArrayList<>(); List<EnergyProviderBlockEntity> providers = new ArrayList<>();
boolean dirty = false; boolean dirty = false;
while (iterator.hasNext()) { while (iterator.hasNext()) {
BlockPosWithDimension pos = iterator.next(); BlockPosWithDimension pos = iterator.next();
if (!valid.contains(pos)) { if (!valid.contains(pos)) {
BlockEntity entity = Objects.requireNonNull(Objects.requireNonNull(world.getServer()).getWorld(pos.dimension)).getBlockEntity(pos.pos); BlockEntity entity = Objects.requireNonNull(Objects.requireNonNull(world.getServer()).getWorld(pos.dimension)).getBlockEntity(pos.pos);
if (entity instanceof EnergyProvider && ((EnergyProvider) entity).isNetwork(id)) { if (entity instanceof EnergyProviderBlockEntity && ((EnergyProviderBlockEntity) entity).isNetwork(id)) {
providers.add((EnergyProvider) entity); providers.add((EnergyProviderBlockEntity) entity);
} else { } else {
iterator.remove(); iterator.remove();
dirty = true; dirty = true;

View File

@ -4,7 +4,7 @@ import com.thebrokenrail.energonrelics.config.HardcodedConfig;
import com.thebrokenrail.energonrelics.EnergonRelics; import com.thebrokenrail.energonrelics.EnergonRelics;
import com.thebrokenrail.energonrelics.component.NetworkComponent; import com.thebrokenrail.energonrelics.component.NetworkComponent;
import com.thebrokenrail.energonrelics.energy.core.util.Action; import com.thebrokenrail.energonrelics.energy.core.util.Action;
import com.thebrokenrail.energonrelics.energy.core.util.EnergyProvider; import com.thebrokenrail.energonrelics.energy.core.util.EnergyTicker;
import com.thebrokenrail.energonrelics.util.BlockPosWithDimension; import com.thebrokenrail.energonrelics.util.BlockPosWithDimension;
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -25,43 +25,11 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProvider, BlockEntityClientSerializable, Tickable { public class EnergyProviderBlockEntity extends BlockEntity implements BlockEntityClientSerializable, Tickable {
private static volatile boolean isTicking = false;
private static final List<EnergyProviderBlockEntity> scheduledTicks = new ArrayList<>();
private static final List<EnergyProviderBlockEntity> scheduledTicksNext = new ArrayList<>();
public static void tickScheduled() {
isTicking = true;
Collections.shuffle(scheduledTicks);
for (EnergyProviderBlockEntity provider : scheduledTicks) {
provider.serverTick();
}
scheduledTicks.clear();
isTicking = false;
for (EnergyProviderBlockEntity entity : scheduledTicksNext) {
entity.schedule();
}
scheduledTicksNext.clear();
}
private void schedule() {
List<EnergyProviderBlockEntity> list;
if (isTicking) {
list = scheduledTicksNext;
} else {
list = scheduledTicks;
}
if (!list.contains(this)) {
list.add(this);
}
}
public EnergyProviderBlockEntity(BlockEntityType<?> type) { public EnergyProviderBlockEntity(BlockEntityType<?> type) {
super(type); super(type);
} }
@Override
public final void addPropagatedAction(Action.PropagatedAction action) { public final void addPropagatedAction(Action.PropagatedAction action) {
if (isEnergyProvider()) { if (isEnergyProvider()) {
if (!completedActions.contains(action)) { if (!completedActions.contains(action)) {
@ -73,17 +41,14 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
} }
} }
@Override
public final boolean isNetwork(int network) { public final boolean isNetwork(int network) {
return isEnergyProvider() && EnergonRelics.NETWORK_CHIP_ITEM.getID(stack) == network; return isEnergyProvider() && EnergonRelics.NETWORK_CHIP_ITEM.getID(stack) == network;
} }
@Override
public final boolean isWithinDistance(Vec3d pos) { public final boolean isWithinDistance(Vec3d pos) {
return getPos().isWithinDistance(pos, HardcodedConfig.POWER_RANGE); return getPos().isWithinDistance(pos, HardcodedConfig.POWER_RANGE);
} }
@Override
public RegistryKey<World> getRegistryKey() { public RegistryKey<World> getRegistryKey() {
return Objects.requireNonNull(getWorld()).getRegistryKey(); return Objects.requireNonNull(getWorld()).getRegistryKey();
} }
@ -118,12 +83,13 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
protected void handlePropagatedAction(Action.PropagatedAction action) { protected void handlePropagatedAction(Action.PropagatedAction action) {
if (!isEnergyProvider()) { if (!isEnergyProvider()) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} else {
schedule();
} }
} }
private void tickPropagatedActions() { public void logicTick() {
}
public List<EnergyProviderBlockEntity> startTick() {
completedActions.clear(); completedActions.clear();
if (isEnergyProvider()) { if (isEnergyProvider()) {
NetworkComponent component = NetworkComponent.getInstance((ServerWorld) Objects.requireNonNull(getWorld())); NetworkComponent component = NetworkComponent.getInstance((ServerWorld) Objects.requireNonNull(getWorld()));
@ -132,16 +98,13 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
takeStack(getWorld()); takeStack(getWorld());
} }
} }
} return Collections.emptyList();
protected void serverTick() {
tickPropagatedActions();
} }
@Override @Override
public final void tick() { public final void tick() {
if (hasWorld() && !Objects.requireNonNull(getWorld()).isClient()) { if (hasWorld() && !Objects.requireNonNull(getWorld()).isClient()) {
schedule(); EnergyTicker.schedule(this);
} }
} }

View File

@ -2,7 +2,6 @@ package com.thebrokenrail.energonrelics.energy.core;
import com.thebrokenrail.energonrelics.component.NetworkComponent; import com.thebrokenrail.energonrelics.component.NetworkComponent;
import com.thebrokenrail.energonrelics.energy.core.util.Action; import com.thebrokenrail.energonrelics.energy.core.util.Action;
import com.thebrokenrail.energonrelics.energy.core.util.EnergyProvider;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -20,16 +19,22 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
super(type); super(type);
} }
private final List<Action.PropagatedAction> pendingPropagatedActions = new ArrayList<>(); private final List<EnergyProviderBlockEntity> providers = new ArrayList<>();
private final List<Action.PropagatedAction> pendingActions = new ArrayList<>();
private final List<EnergyProvider> providers = new ArrayList<>();
private final List<Integer> networks = new ArrayList<>(); private final List<Integer> networks = new ArrayList<>();
private long totalCost = 0; private long totalCost = 0;
private long previousTotalCost = 0;
protected void propagateAction(Action.PropagatedAction action) { protected void propagateAction(Action.PropagatedAction action) {
totalCost = totalCost + action.amountOwed(); totalCost = totalCost + action.amountOwed();
pendingActions.add(action); if (providers.size() > 0) {
action.expandPayments(providers.size());
for (EnergyProviderBlockEntity provider : providers) {
provider.addPropagatedAction(action);
}
} else {
action.pay(0);
}
} }
protected void addAction(Action action) { protected void addAction(Action action) {
@ -37,15 +42,17 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
} }
@Override @Override
public void serverTick() { public List<EnergyProviderBlockEntity> startTick() {
List<EnergyProviderBlockEntity> list = new ArrayList<>(super.startTick());
ServerWorld world = (ServerWorld) getWorld(); ServerWorld world = (ServerWorld) getWorld();
assert world != null; assert world != null;
NetworkComponent component = NetworkComponent.getInstance(world); NetworkComponent component = NetworkComponent.getInstance(world);
providers.clear(); providers.clear();
for (int network : networks) { for (int network : networks) {
List<EnergyProvider> potentialProviders = component.getSource(world, network); List<EnergyProviderBlockEntity> potentialProviders = component.getSource(world, network);
for (EnergyProvider provider : potentialProviders) { for (EnergyProviderBlockEntity provider : potentialProviders) {
if (provider.getRegistryKey().equals(getWorld().getRegistryKey())) { if (provider.getRegistryKey().equals(getWorld().getRegistryKey())) {
Vec3d pos = new Vec3d(getPos().getX() + 0.5d, getPos().getY() + 0.5d, getPos().getZ() + 0.5d); Vec3d pos = new Vec3d(getPos().getX() + 0.5d, getPos().getY() + 0.5d, getPos().getZ() + 0.5d);
if (provider.isWithinDistance(pos)) { if (provider.isWithinDistance(pos)) {
@ -55,31 +62,22 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
} }
} }
previousTotalCost = totalCost;
totalCost = 0; totalCost = 0;
pendingActions.clear();
list.addAll(providers);
return list;
}
@Override
public void logicTick() {
super.logicTick();
tickEnergy(); tickEnergy();
super.serverTick();
for (Action.PropagatedAction action : pendingPropagatedActions) {
propagateAction(action);
}
pendingPropagatedActions.clear();
for (Action.PropagatedAction action : pendingActions) {
if (providers.size() > 0) {
action.expandPayments(providers.size());
for (EnergyProvider provider : providers) {
provider.addPropagatedAction(action);
}
} else {
action.pay(0);
}
}
} }
public long getTotalCost() { public long getTotalCost() {
return totalCost; return previousTotalCost;
} }
@Override @Override
@ -87,7 +85,7 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
super.handlePropagatedAction(action); super.handlePropagatedAction(action);
// Propagate Action To Energy Providers // Propagate Action To Energy Providers
if (isEnergyProviderActive()) { if (isEnergyProviderActive()) {
pendingPropagatedActions.add(action); propagateAction(action);
} else { } else {
action.pay(0); action.pay(0);
} }

View File

@ -1,12 +0,0 @@
package com.thebrokenrail.energonrelics.energy.core.util;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
public interface EnergyProvider {
void addPropagatedAction(Action.PropagatedAction action);
boolean isNetwork(int network);
boolean isWithinDistance(Vec3d pos);
RegistryKey<World> getRegistryKey();
}

View File

@ -0,0 +1,38 @@
package com.thebrokenrail.energonrelics.energy.core.util;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class EnergyTicker {
private static final List<EnergyProviderBlockEntity> scheduled = new ArrayList<>();
public static void schedule(EnergyProviderBlockEntity provider) {
scheduled.add(provider);
}
public static void tick() {
List<EnergyProviderBlockEntity> started = new ArrayList<>();
List<EnergyProviderBlockEntity> temp = new ArrayList<>(scheduled);
List<EnergyProviderBlockEntity> temp2 = new ArrayList<>();
while (!temp.isEmpty()) {
for (EnergyProviderBlockEntity provider : temp) {
if (!started.contains(provider)) {
temp2.addAll(provider.startTick());
started.add(provider);
}
}
temp.clear();
temp.addAll(temp2);
temp2.clear();
}
Collections.shuffle(started);
for (EnergyProviderBlockEntity provider : started) {
provider.logicTick();
}
}
}

View File

@ -1,6 +1,6 @@
package com.thebrokenrail.energonrelics.mixin; package com.thebrokenrail.energonrelics.mixin;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity; import com.thebrokenrail.energonrelics.energy.core.util.EnergyTicker;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -16,7 +16,7 @@ public abstract class MixinWorld {
@Inject(at = @At("TAIL"), method = "tickBlockEntities") @Inject(at = @At("TAIL"), method = "tickBlockEntities")
public void tickBlockEntities(CallbackInfo info) { public void tickBlockEntities(CallbackInfo info) {
if (!isClient()) { if (!isClient()) {
EnergyProviderBlockEntity.tickScheduled(); EnergyTicker.tick();
} }
} }
} }