Fix Energy System Bugs

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.world.LightType;
import java.util.List;
import java.util.Objects;
import java.util.Random;
@ -49,7 +50,7 @@ public class LightningRodBlockEntity extends EnergyProviderBlockEntity implement
}
@Override
protected void serverTick() {
public List<EnergyProviderBlockEntity> startTick() {
if (cooldown <= 0) {
energy = 0;
@ -68,7 +69,7 @@ public class LightningRodBlockEntity extends EnergyProviderBlockEntity implement
} else {
cooldown--;
}
super.serverTick();
return super.startTick();
}
@Override

View File

@ -1,11 +1,13 @@
package com.thebrokenrail.energonrelics.block.entity;
import com.thebrokenrail.energonrelics.config.HardcodedConfig;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import com.thebrokenrail.energonrelics.energy.helper.EnergyGeneratorBlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.math.Direction;
import net.minecraft.world.LightType;
import java.util.List;
import java.util.Objects;
public class SolarPanelBlockEntity extends EnergyGeneratorBlockEntity {
@ -37,8 +39,8 @@ public class SolarPanelBlockEntity extends EnergyGeneratorBlockEntity {
}
@Override
protected void serverTick() {
public List<EnergyProviderBlockEntity> startTick() {
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.entity.battery.PassiveBatteryControllerBlockEntity;
import com.thebrokenrail.energonrelics.block.reactor.ReactorControllerBlock;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import com.thebrokenrail.energonrelics.energy.helper.EnergyGeneratorBlockEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
@ -32,7 +33,7 @@ public class ReactorControllerBlockEntity extends EnergyGeneratorBlockEntity {
}
@Override
protected void serverTick() {
public List<EnergyProviderBlockEntity> startTick() {
if (getCachedState().get(ReactorControllerBlock.POWERED)) {
Reactor reactor = getReactor();
if (reactor != null && !reactor.core.isReacting()) {
@ -62,7 +63,7 @@ public class ReactorControllerBlockEntity extends EnergyGeneratorBlockEntity {
}
}
setEnergy(getDisplayEnergy());
super.serverTick();
return super.startTick();
}
@Override

View File

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

View File

@ -4,7 +4,7 @@ import com.thebrokenrail.energonrelics.config.HardcodedConfig;
import com.thebrokenrail.energonrelics.EnergonRelics;
import com.thebrokenrail.energonrelics.component.NetworkComponent;
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 net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.minecraft.block.BlockState;
@ -25,43 +25,11 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProvider, 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 class EnergyProviderBlockEntity extends BlockEntity implements BlockEntityClientSerializable, Tickable {
public EnergyProviderBlockEntity(BlockEntityType<?> type) {
super(type);
}
@Override
public final void addPropagatedAction(Action.PropagatedAction action) {
if (isEnergyProvider()) {
if (!completedActions.contains(action)) {
@ -73,17 +41,14 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
}
}
@Override
public final boolean isNetwork(int network) {
return isEnergyProvider() && EnergonRelics.NETWORK_CHIP_ITEM.getID(stack) == network;
}
@Override
public final boolean isWithinDistance(Vec3d pos) {
return getPos().isWithinDistance(pos, HardcodedConfig.POWER_RANGE);
}
@Override
public RegistryKey<World> getRegistryKey() {
return Objects.requireNonNull(getWorld()).getRegistryKey();
}
@ -118,12 +83,13 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
protected void handlePropagatedAction(Action.PropagatedAction action) {
if (!isEnergyProvider()) {
throw new UnsupportedOperationException();
} else {
schedule();
}
}
private void tickPropagatedActions() {
public void logicTick() {
}
public List<EnergyProviderBlockEntity> startTick() {
completedActions.clear();
if (isEnergyProvider()) {
NetworkComponent component = NetworkComponent.getInstance((ServerWorld) Objects.requireNonNull(getWorld()));
@ -132,16 +98,13 @@ public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProv
takeStack(getWorld());
}
}
}
protected void serverTick() {
tickPropagatedActions();
return Collections.emptyList();
}
@Override
public final void tick() {
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.energy.core.util.Action;
import com.thebrokenrail.energonrelics.energy.core.util.EnergyProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.nbt.CompoundTag;
@ -20,16 +19,22 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
super(type);
}
private final List<Action.PropagatedAction> pendingPropagatedActions = new ArrayList<>();
private final List<Action.PropagatedAction> pendingActions = new ArrayList<>();
private final List<EnergyProvider> providers = new ArrayList<>();
private final List<EnergyProviderBlockEntity> providers = new ArrayList<>();
private final List<Integer> networks = new ArrayList<>();
private long totalCost = 0;
private long previousTotalCost = 0;
protected void propagateAction(Action.PropagatedAction action) {
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) {
@ -37,15 +42,17 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
}
@Override
public void serverTick() {
public List<EnergyProviderBlockEntity> startTick() {
List<EnergyProviderBlockEntity> list = new ArrayList<>(super.startTick());
ServerWorld world = (ServerWorld) getWorld();
assert world != null;
NetworkComponent component = NetworkComponent.getInstance(world);
providers.clear();
for (int network : networks) {
List<EnergyProvider> potentialProviders = component.getSource(world, network);
for (EnergyProvider provider : potentialProviders) {
List<EnergyProviderBlockEntity> potentialProviders = component.getSource(world, network);
for (EnergyProviderBlockEntity provider : potentialProviders) {
if (provider.getRegistryKey().equals(getWorld().getRegistryKey())) {
Vec3d pos = new Vec3d(getPos().getX() + 0.5d, getPos().getY() + 0.5d, getPos().getZ() + 0.5d);
if (provider.isWithinDistance(pos)) {
@ -55,31 +62,22 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
}
}
previousTotalCost = totalCost;
totalCost = 0;
pendingActions.clear();
list.addAll(providers);
return list;
}
@Override
public void logicTick() {
super.logicTick();
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() {
return totalCost;
return previousTotalCost;
}
@Override
@ -87,7 +85,7 @@ public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntit
super.handlePropagatedAction(action);
// Propagate Action To Energy Providers
if (isEnergyProviderActive()) {
pendingPropagatedActions.add(action);
propagateAction(action);
} else {
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;
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
import com.thebrokenrail.energonrelics.energy.core.util.EnergyTicker;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -16,7 +16,7 @@ public abstract class MixinWorld {
@Inject(at = @At("TAIL"), method = "tickBlockEntities")
public void tickBlockEntities(CallbackInfo info) {
if (!isClient()) {
EnergyProviderBlockEntity.tickScheduled();
EnergyTicker.tick();
}
}
}