2019-03-19 17:21:06 +01:00
|
|
|
package de.ellpeck.naturesaura.blocks.tiles;
|
|
|
|
|
2021-01-11 23:39:19 +01:00
|
|
|
import de.ellpeck.naturesaura.ModConfig;
|
2019-03-19 17:21:06 +01:00
|
|
|
import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk;
|
2021-12-06 14:38:12 +01:00
|
|
|
import net.minecraft.core.BlockPos;
|
2021-12-04 15:40:09 +01:00
|
|
|
import net.minecraft.nbt.CompoundTag;
|
2021-12-06 14:38:12 +01:00
|
|
|
import net.minecraft.server.level.ServerLevel;
|
|
|
|
import net.minecraft.util.Mth;
|
|
|
|
import net.minecraft.world.level.ChunkPos;
|
|
|
|
import net.minecraft.world.level.block.state.BlockState;
|
2020-01-24 20:49:09 +01:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.stream.Collectors;
|
2019-03-19 17:21:06 +01:00
|
|
|
|
2021-12-04 15:40:09 +01:00
|
|
|
public class BlockEntityChunkLoader extends BlockEntityImpl implements ITickableBlockEntity {
|
2020-01-24 20:49:09 +01:00
|
|
|
|
|
|
|
private final List<ChunkPos> forcedChunks = new ArrayList<>();
|
2021-01-11 23:39:19 +01:00
|
|
|
private boolean firstTick = true;
|
2023-02-16 19:03:26 +01:00
|
|
|
private boolean canUseRightNow = true;
|
2020-01-24 20:49:09 +01:00
|
|
|
|
2021-12-06 14:38:12 +01:00
|
|
|
public BlockEntityChunkLoader(BlockPos pos, BlockState state) {
|
2021-12-19 15:32:45 +01:00
|
|
|
super(ModBlockEntities.CHUNK_LOADER, pos, state);
|
2020-01-21 21:04:44 +01:00
|
|
|
}
|
2019-03-19 17:21:06 +01:00
|
|
|
|
|
|
|
@Override
|
2021-12-06 14:38:12 +01:00
|
|
|
public void setRemoved() {
|
|
|
|
super.setRemoved();
|
2020-01-24 20:49:09 +01:00
|
|
|
this.loadChunks(true);
|
2019-03-19 17:21:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRedstonePowerChange(int newPower) {
|
|
|
|
super.onRedstonePowerChange(newPower);
|
2021-12-04 15:40:09 +01:00
|
|
|
if (!this.level.isClientSide) {
|
2020-01-24 20:49:09 +01:00
|
|
|
this.loadChunks(false);
|
2019-03-19 17:21:06 +01:00
|
|
|
this.sendToClients();
|
|
|
|
}
|
2020-01-24 20:49:09 +01:00
|
|
|
}
|
2019-03-19 17:21:06 +01:00
|
|
|
|
|
|
|
public int range() {
|
|
|
|
return this.redstonePower * 2;
|
|
|
|
}
|
|
|
|
|
2023-02-16 19:03:26 +01:00
|
|
|
public int getAuraUsed() {
|
|
|
|
return Mth.ceil(this.range() / 2F);
|
|
|
|
}
|
|
|
|
|
2020-01-24 20:49:09 +01:00
|
|
|
private void loadChunks(boolean unload) {
|
2021-12-04 15:40:09 +01:00
|
|
|
if (this.level.isClientSide || !ModConfig.instance.chunkLoader.get())
|
2019-03-19 17:21:06 +01:00
|
|
|
return;
|
2021-12-15 16:30:22 +01:00
|
|
|
var level = (ServerLevel) this.level;
|
2020-01-24 20:49:09 +01:00
|
|
|
|
|
|
|
List<ChunkPos> shouldBeForced = new ArrayList<>();
|
|
|
|
if (!unload) {
|
2021-12-15 16:30:22 +01:00
|
|
|
var range = this.range();
|
2023-02-16 19:03:26 +01:00
|
|
|
if (range > 0 && this.canUseRightNow) {
|
2022-06-27 15:24:04 +02:00
|
|
|
for (var x = this.worldPosition.getX() - range >> 4; x <= this.worldPosition.getX() + range >> 4; x++) {
|
|
|
|
for (var z = this.worldPosition.getZ() - range >> 4; z <= this.worldPosition.getZ() + range >> 4; z++) {
|
2021-12-15 16:30:22 +01:00
|
|
|
var pos = new ChunkPos(x, z);
|
2020-01-24 20:49:09 +01:00
|
|
|
// Only force chunks that we're already forcing or that nobody else is forcing
|
2021-12-06 14:38:12 +01:00
|
|
|
if (this.forcedChunks.contains(pos) || !level.getForcedChunks().contains(pos.toLong()))
|
2020-01-24 20:49:09 +01:00
|
|
|
shouldBeForced.add(pos);
|
|
|
|
}
|
2019-03-19 17:21:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-24 20:49:09 +01:00
|
|
|
|
2021-12-06 14:38:12 +01:00
|
|
|
// Unforce all the chunks that shouldn't be forced anymore
|
2021-12-15 16:30:22 +01:00
|
|
|
for (var pos : this.forcedChunks) {
|
2020-01-24 20:49:09 +01:00
|
|
|
if (!shouldBeForced.contains(pos))
|
2021-12-06 14:38:12 +01:00
|
|
|
level.setChunkForced(pos.x, pos.z, false);
|
2020-01-24 20:49:09 +01:00
|
|
|
}
|
|
|
|
this.forcedChunks.clear();
|
|
|
|
|
|
|
|
// Force all chunks that should be forced
|
2021-12-15 16:30:22 +01:00
|
|
|
for (var pos : shouldBeForced) {
|
2021-12-06 14:38:12 +01:00
|
|
|
level.setChunkForced(pos.x, pos.z, true);
|
2020-01-24 20:49:09 +01:00
|
|
|
this.forcedChunks.add(pos);
|
|
|
|
}
|
|
|
|
}
|
2019-03-19 17:21:06 +01:00
|
|
|
|
|
|
|
@Override
|
2020-01-21 21:04:44 +01:00
|
|
|
public void tick() {
|
2021-12-04 15:40:09 +01:00
|
|
|
if (!this.level.isClientSide && ModConfig.instance.chunkLoader.get()) {
|
2021-01-11 23:39:19 +01:00
|
|
|
// defer loading chunks on load to here since, otherwise, deadlocks happen oof
|
|
|
|
// since forced chunks are saved to disk by the game, this is only necessary for when the chunk loader config changes
|
|
|
|
if (this.firstTick) {
|
|
|
|
this.loadChunks(false);
|
|
|
|
this.firstTick = false;
|
|
|
|
}
|
|
|
|
|
2023-02-16 19:03:26 +01:00
|
|
|
var toUse = this.getAuraUsed();
|
|
|
|
var canUse = this.canUseRightNow(toUse);
|
|
|
|
if (this.canUseRightNow != canUse) {
|
|
|
|
this.canUseRightNow = canUse;
|
|
|
|
this.loadChunks(false);
|
|
|
|
}
|
|
|
|
|
2021-12-04 15:40:09 +01:00
|
|
|
if (this.level.getGameTime() % 20 != 0)
|
2019-03-19 17:21:06 +01:00
|
|
|
return;
|
2023-02-16 19:03:26 +01:00
|
|
|
if (toUse > 0 && this.canUseRightNow) {
|
2021-12-15 16:30:22 +01:00
|
|
|
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
|
2021-12-04 15:40:09 +01:00
|
|
|
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, toUse);
|
2019-03-19 17:21:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-24 20:49:09 +01:00
|
|
|
|
|
|
|
@Override
|
2021-12-04 15:40:09 +01:00
|
|
|
public void writeNBT(CompoundTag compound, SaveType type) {
|
2020-01-24 20:49:09 +01:00
|
|
|
super.writeNBT(compound, type);
|
|
|
|
if (type == SaveType.TILE)
|
2021-12-06 14:38:12 +01:00
|
|
|
compound.putLongArray("forced_chunks", this.forcedChunks.stream().map(ChunkPos::toLong).collect(Collectors.toList()));
|
2020-01-24 20:49:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-12-04 15:40:09 +01:00
|
|
|
public void readNBT(CompoundTag compound, SaveType type) {
|
2020-01-24 20:49:09 +01:00
|
|
|
super.readNBT(compound, type);
|
|
|
|
|
|
|
|
if (type == SaveType.TILE) {
|
|
|
|
this.forcedChunks.clear();
|
|
|
|
Arrays.stream(compound.getLongArray("forced_chunks")).mapToObj(ChunkPos::new).forEach(this.forcedChunks::add);
|
|
|
|
}
|
|
|
|
}
|
2023-02-16 19:03:26 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean allowsLowerLimiter() {
|
|
|
|
return true;
|
|
|
|
}
|
2019-03-19 17:21:06 +01:00
|
|
|
}
|