2018-10-21 12:51:13 +02:00
|
|
|
package de.ellpeck.naturesaura.aura.chunk;
|
|
|
|
|
2018-10-30 18:18:56 +01:00
|
|
|
import de.ellpeck.naturesaura.Helper;
|
2018-10-26 20:25:21 +02:00
|
|
|
import de.ellpeck.naturesaura.NaturesAura;
|
2018-11-07 23:42:13 +01:00
|
|
|
import de.ellpeck.naturesaura.aura.AuraType;
|
2018-10-21 12:51:13 +02:00
|
|
|
import de.ellpeck.naturesaura.aura.Capabilities;
|
2018-10-25 18:49:42 +02:00
|
|
|
import de.ellpeck.naturesaura.aura.chunk.effect.GrassDieEffect;
|
|
|
|
import de.ellpeck.naturesaura.aura.chunk.effect.IDrainSpotEffect;
|
2018-10-30 18:18:56 +01:00
|
|
|
import de.ellpeck.naturesaura.aura.chunk.effect.PlantBoostEffect;
|
2018-10-25 18:49:42 +02:00
|
|
|
import de.ellpeck.naturesaura.aura.chunk.effect.ReplenishingEffect;
|
2018-10-21 12:51:13 +02:00
|
|
|
import de.ellpeck.naturesaura.packet.PacketAuraChunk;
|
|
|
|
import de.ellpeck.naturesaura.packet.PacketHandler;
|
|
|
|
import net.minecraft.nbt.NBTBase;
|
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
import net.minecraft.nbt.NBTTagList;
|
|
|
|
import net.minecraft.util.EnumFacing;
|
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.world.World;
|
|
|
|
import net.minecraft.world.chunk.Chunk;
|
|
|
|
import net.minecraftforge.common.capabilities.Capability;
|
|
|
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
|
|
|
import net.minecraftforge.common.util.INBTSerializable;
|
2018-10-21 13:12:03 +02:00
|
|
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
2018-10-21 12:51:13 +02:00
|
|
|
import org.apache.commons.lang3.mutable.MutableInt;
|
|
|
|
import org.apache.commons.lang3.mutable.MutableObject;
|
|
|
|
|
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.function.BiConsumer;
|
|
|
|
|
|
|
|
public class AuraChunk implements ICapabilityProvider, INBTSerializable<NBTTagCompound> {
|
|
|
|
|
|
|
|
public static final int DEFAULT_AURA = 10000;
|
|
|
|
|
|
|
|
private final Chunk chunk;
|
2018-11-07 23:42:13 +01:00
|
|
|
private final AuraType type;
|
2018-10-24 13:06:24 +02:00
|
|
|
private final Map<BlockPos, MutableInt> drainSpots = new HashMap<>();
|
2018-10-25 18:49:42 +02:00
|
|
|
private final List<IDrainSpotEffect> effects = new ArrayList<>();
|
2018-10-21 12:51:13 +02:00
|
|
|
private boolean needsSync;
|
|
|
|
|
2018-11-07 23:42:13 +01:00
|
|
|
public AuraChunk(Chunk chunk, AuraType type) {
|
2018-10-21 12:51:13 +02:00
|
|
|
this.chunk = chunk;
|
2018-11-07 23:42:13 +01:00
|
|
|
this.type = type;
|
|
|
|
|
|
|
|
this.addEffect(new ReplenishingEffect());
|
|
|
|
this.addEffect(new GrassDieEffect());
|
|
|
|
this.addEffect(new PlantBoostEffect());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addEffect(IDrainSpotEffect effect) {
|
|
|
|
if (effect.appliesToType(this.type))
|
|
|
|
this.effects.add(effect);
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
|
2018-10-24 13:06:24 +02:00
|
|
|
public static void getSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) {
|
2018-10-26 20:25:21 +02:00
|
|
|
world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getSpotsInArea");
|
2018-10-21 12:51:13 +02:00
|
|
|
for (int x = (pos.getX() - radius) >> 4; x <= (pos.getX() + radius) >> 4; x++) {
|
|
|
|
for (int z = (pos.getZ() - radius) >> 4; z <= (pos.getZ() + radius) >> 4; z++) {
|
2018-10-30 18:18:56 +01:00
|
|
|
if (Helper.isChunkLoaded(world, x, z)) {
|
|
|
|
Chunk chunk = world.getChunk(x, z);
|
|
|
|
if (chunk.hasCapability(Capabilities.auraChunk, null)) {
|
|
|
|
AuraChunk auraChunk = chunk.getCapability(Capabilities.auraChunk, null);
|
|
|
|
auraChunk.getSpotsInArea(pos, radius, consumer);
|
|
|
|
}
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-10-26 20:25:21 +02:00
|
|
|
world.profiler.endSection();
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static int getAuraInArea(World world, BlockPos pos, int radius) {
|
|
|
|
MutableInt result = new MutableInt(DEFAULT_AURA);
|
2018-10-24 13:06:24 +02:00
|
|
|
getSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> result.add(drainSpot.intValue()));
|
2018-10-21 12:51:13 +02:00
|
|
|
return result.intValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static AuraChunk getAuraChunk(World world, BlockPos pos) {
|
|
|
|
Chunk chunk = world.getChunk(pos);
|
|
|
|
if (chunk.hasCapability(Capabilities.auraChunk, null)) {
|
|
|
|
return chunk.getCapability(Capabilities.auraChunk, null);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-31 11:50:57 +01:00
|
|
|
public static BlockPos getLowestSpot(World world, BlockPos pos, int radius, BlockPos defaultSpot) {
|
|
|
|
MutableInt lowestAmount = new MutableInt(Integer.MAX_VALUE);
|
|
|
|
MutableObject<BlockPos> lowestSpot = new MutableObject<>();
|
2018-10-21 12:51:13 +02:00
|
|
|
getSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> {
|
2018-10-31 11:50:57 +01:00
|
|
|
int amount = drainSpot.intValue();
|
|
|
|
if (amount < lowestAmount.intValue()) {
|
|
|
|
lowestAmount.setValue(amount);
|
|
|
|
lowestSpot.setValue(blockPos);
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
});
|
2018-10-31 11:50:57 +01:00
|
|
|
BlockPos lowest = lowestSpot.getValue();
|
|
|
|
if (lowest == null)
|
|
|
|
lowest = defaultSpot;
|
|
|
|
return lowest;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static BlockPos getHighestSpot(World world, BlockPos pos, int radius, BlockPos defaultSpot) {
|
|
|
|
MutableInt highestAmount = new MutableInt(Integer.MIN_VALUE);
|
|
|
|
MutableObject<BlockPos> highestSpot = new MutableObject<>();
|
|
|
|
getSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> {
|
|
|
|
int amount = drainSpot.intValue();
|
|
|
|
if (amount > highestAmount.intValue()) {
|
|
|
|
highestAmount.setValue(amount);
|
|
|
|
highestSpot.setValue(blockPos);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
BlockPos highest = highestSpot.getValue();
|
|
|
|
if (highest == null)
|
|
|
|
highest = defaultSpot;
|
|
|
|
return highest;
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
|
2018-10-24 13:06:24 +02:00
|
|
|
public void getSpotsInArea(BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) {
|
|
|
|
for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) {
|
2018-10-21 12:51:13 +02:00
|
|
|
BlockPos drainPos = entry.getKey();
|
|
|
|
if (drainPos.distanceSq(pos) <= radius * radius) {
|
|
|
|
consumer.accept(drainPos, entry.getValue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void drainAura(BlockPos pos, int amount) {
|
2018-10-24 13:06:24 +02:00
|
|
|
MutableInt spot = this.getDrainSpot(pos);
|
|
|
|
spot.subtract(amount);
|
|
|
|
if (spot.intValue() == 0)
|
2018-10-21 12:51:13 +02:00
|
|
|
this.drainSpots.remove(pos);
|
|
|
|
this.markDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void storeAura(BlockPos pos, int amount) {
|
2018-10-24 13:06:24 +02:00
|
|
|
MutableInt spot = this.getDrainSpot(pos);
|
|
|
|
spot.add(amount);
|
|
|
|
if (spot.intValue() == 0)
|
2018-10-21 12:51:13 +02:00
|
|
|
this.drainSpots.remove(pos);
|
|
|
|
this.markDirty();
|
|
|
|
}
|
|
|
|
|
2018-10-24 13:06:24 +02:00
|
|
|
private MutableInt getDrainSpot(BlockPos pos) {
|
|
|
|
MutableInt spot = this.drainSpots.get(pos);
|
2018-10-21 12:51:13 +02:00
|
|
|
if (spot == null) {
|
2018-10-24 13:06:24 +02:00
|
|
|
spot = new MutableInt();
|
2018-10-21 12:51:13 +02:00
|
|
|
this.drainSpots.put(pos, spot);
|
|
|
|
}
|
|
|
|
return spot;
|
|
|
|
}
|
|
|
|
|
2018-10-24 13:06:24 +02:00
|
|
|
public void setSpots(Map<BlockPos, MutableInt> spots) {
|
2018-10-21 12:51:13 +02:00
|
|
|
this.drainSpots.clear();
|
|
|
|
this.drainSpots.putAll(spots);
|
|
|
|
}
|
|
|
|
|
2018-11-07 23:42:13 +01:00
|
|
|
public AuraType getType() {
|
|
|
|
return this.type;
|
|
|
|
}
|
|
|
|
|
2018-10-21 12:51:13 +02:00
|
|
|
public void markDirty() {
|
|
|
|
this.needsSync = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void update() {
|
|
|
|
World world = this.chunk.getWorld();
|
|
|
|
if (this.needsSync) {
|
|
|
|
PacketHandler.sendToAllLoaded(world,
|
|
|
|
new BlockPos(this.chunk.x * 16, 0, this.chunk.z * 16),
|
2018-10-21 13:12:03 +02:00
|
|
|
this.makePacket());
|
2018-10-21 12:51:13 +02:00
|
|
|
this.needsSync = false;
|
|
|
|
}
|
|
|
|
|
2018-10-25 18:49:42 +02:00
|
|
|
for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) {
|
|
|
|
for (IDrainSpotEffect effect : this.effects) {
|
2018-10-31 12:16:42 +01:00
|
|
|
world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":" + effect.getClass().getSimpleName());
|
2018-10-25 18:49:42 +02:00
|
|
|
effect.update(world, this.chunk, this, entry.getKey(), entry.getValue());
|
2018-10-31 12:16:42 +01:00
|
|
|
world.profiler.endSection();
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-21 13:12:03 +02:00
|
|
|
public IMessage makePacket() {
|
|
|
|
return new PacketAuraChunk(this.chunk.x, this.chunk.z, this.drainSpots);
|
|
|
|
}
|
|
|
|
|
2018-10-21 12:51:13 +02:00
|
|
|
@Override
|
|
|
|
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
|
|
|
|
return capability == Capabilities.auraChunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
@Override
|
|
|
|
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
|
|
|
|
return capability == Capabilities.auraChunk ? (T) this : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public NBTTagCompound serializeNBT() {
|
|
|
|
NBTTagList list = new NBTTagList();
|
2018-10-24 13:06:24 +02:00
|
|
|
for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) {
|
2018-10-21 12:51:13 +02:00
|
|
|
NBTTagCompound tag = new NBTTagCompound();
|
|
|
|
tag.setLong("pos", entry.getKey().toLong());
|
2018-10-24 13:06:24 +02:00
|
|
|
tag.setInteger("amount", entry.getValue().intValue());
|
2018-10-21 12:51:13 +02:00
|
|
|
list.appendTag(tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
NBTTagCompound compound = new NBTTagCompound();
|
|
|
|
compound.setTag("drain_spots", list);
|
|
|
|
return compound;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void deserializeNBT(NBTTagCompound compound) {
|
|
|
|
this.drainSpots.clear();
|
|
|
|
NBTTagList list = compound.getTagList("drain_spots", 10);
|
|
|
|
for (NBTBase base : list) {
|
|
|
|
NBTTagCompound tag = (NBTTagCompound) base;
|
|
|
|
this.drainSpots.put(
|
|
|
|
BlockPos.fromLong(tag.getLong("pos")),
|
2018-10-24 13:06:24 +02:00
|
|
|
new MutableInt(tag.getInteger("amount")));
|
2018-10-21 12:51:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|