package joshie.harvest.gathering;
import com.google.common.cache.Cache;
import joshie.harvest.api.HFApi;
import joshie.harvest.api.calendar.CalendarDate;
import joshie.harvest.api.calendar.Season;
import joshie.harvest.town.data.TownBuilding;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import static joshie.harvest.gathering.HFGathering.*;
public class GatheringData {
private final Random random = new Random();
private Set<GatheringLocation> locations = new HashSet<>();
public void newDay(World world, BlockPos townCentre, Collection<TownBuilding> buildings, Cache<BlockPos, Boolean> isFar) {
Set<GatheringLocation> previous = new HashSet<>(locations);
locations = new HashSet<>();
//Remove all previous locations
for (GatheringLocation location : previous) {
if (world.isBlockLoaded(location.pos)) {
IBlockState state = world.getBlockState(location.pos);
if (state.getBlock() == location.block && state.getBlock().getMetaFromState(state) == location.meta) {
world.setBlockToAir(location.pos);
}
} else locations.add(location); //Add them back
}
//Create some new spawn spots based on where we have buildings
CalendarDate date = HFApi.calendar.getDate(world);
Season season = date.getSeason();
random.setSeed(date.hashCode());
int placed = 0;
for (int i = 0; i < 2048 && placed < GATHERING_ATTEMPTS; i++) {
BlockPos original = townCentre.add(GATHERING_MAX_HALF - random.nextInt(GATHERING_MAXIMUM), 64, GATHERING_MAX_HALF - random.nextInt(GATHERING_MAXIMUM));
if (world.isBlockLoaded(original)) {
BlockPos pos = world.getTopSolidOrLiquidBlock(original);
if (GatheringRegistry.INSTANCE.isValidGatheringSpawn(world.getBlockState(pos.down()).getBlock())
&& world.isAirBlock(pos) && world.canBlockSeeSky(pos) && isNotTooFar(isFar, buildings, pos)) {
IBlockState random = HFApi.gathering.getRandomStateForSeason(season);
if (random != null && world.setBlockState(pos, random, 2)) {
locations.add(new GatheringLocation(random, pos));
placed++;
}
}
}
}
}
private boolean isNotTooFar(Cache<BlockPos, Boolean> isFar, Collection<TownBuilding> buildings, BlockPos pos) {
try {
return isFar.get(pos, () -> {
for (TownBuilding building: buildings) {
if (building.pos.getDistance(pos.getX(), pos.getY(), pos.getZ()) < GATHERING_MINIMUM) return false;
}
return true;
});
} catch (ExecutionException ex) { return false; }
}
public void readFromNBT(NBTTagCompound nbt) {
NBTTagList list = nbt.getTagList("GatheringLocations", 10);
for (int i = 0; i < list.tagCount(); i++) {
NBTTagCompound tag = list.getCompoundTagAt(i);
GatheringLocation location = new GatheringLocation();
location.readFromNBT(tag);
locations.add(location);
}
}
public void writeToNBT(NBTTagCompound nbt) {
NBTTagList list = new NBTTagList();
for (GatheringLocation location : locations) {
NBTTagCompound tag = new NBTTagCompound();
location.writeToNBT(tag);
list.appendTag(tag);
}
nbt.setTag("GatheringLocations", list);
}
}