WEATHER 2 Vec3 issue when running the Forge run thing
Mungydungy opened this issue ยท 0 comments
package weather2.weathersystem;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.*;
import CoroUtil.util.CoroUtilPhysics;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.apache.commons.io.FileUtils;
import weather2.ServerTickHandler;
import weather2.Weather;
import weather2.config.ConfigStorm;
import weather2.weathersystem.storm.EnumWeatherObjectType;
import weather2.weathersystem.storm.StormObject;
import weather2.weathersystem.storm.WeatherObject;
import weather2.weathersystem.storm.WeatherObjectSandstorm;
import weather2.weathersystem.wind.WindManager;
import CoroUtil.util.CoroUtilFile;
import CoroUtil.util.Vec3;
public class WeatherManagerBase {
//shared stuff, stormfront list
public int dim;
//storms
private List<WeatherObject> listStormObjects = new ArrayList<>();
public HashMap<Long, WeatherObject> lookupStormObjectsByID = new HashMap<>();
public HashMap<Integer, ArrayList<StormObject>> lookupStormObjectsByLayer = new HashMap<>();
//private ArrayList<ArrayList<StormObject>> listStormObjectsByLayer = new ArrayList<ArrayList<StormObject>>();
//volcanos
/*private List<VolcanoObject> listVolcanoes = new ArrayList<>();
public HashMap<Long, VolcanoObject> lookupVolcanoes = new HashMap<>();*/
//wind
public WindManager windMan;
//for client only
public boolean isVanillaRainActiveOnServer = false;
public boolean isVanillaThunderActiveOnServer = false;
public int vanillaRainTimeOnServer = 0;
public long lastStormFormed = 0;
public long lastSandstormFormed = 0;
//0 = none, 1 = usual max overcast
public float cloudIntensity = 1F;
private HashSet<Long> listWeatherBlockDamageDeflector = new HashSet<>();
public WeatherManagerBase(int parDim) {
dim = parDim;
windMan = new WindManager(this);
lookupStormObjectsByLayer.put(0, new ArrayList<>());
lookupStormObjectsByLayer.put(1, new ArrayList<>());
lookupStormObjectsByLayer.put(2, new ArrayList<>());
}
public void reset() {
for (int i = 0; i < getStormObjects().size(); i++) {
WeatherObject so = getStormObjects().get(i);
so.reset();
}
getStormObjects().clear();
lookupStormObjectsByID.clear();
try {
for (int i = 0; i < lookupStormObjectsByLayer.size(); i++) {
lookupStormObjectsByLayer.get(i).clear();
}
} catch (Exception ex) {
ex.printStackTrace();
}
/*for (int i = 0; i < getVolcanoObjects().size(); i++) {
VolcanoObject vo = getVolcanoObjects().get(i);
vo.reset();
}
getVolcanoObjects().clear();
lookupVolcanoes.clear();*/
windMan.reset();
//do not reset this, its static (shared between client and server) and client side calls reset()
//WeatherObject.lastUsedStormID = 0;
}
public World getWorld() {
return null;
}
public void tick() {
World world = getWorld();
if (world != null) {
//tick storms
List<WeatherObject> list = getStormObjects();
for (int i = 0; i < list.size(); i++) {
WeatherObject so = list.get(i);
if (this instanceof WeatherManagerServer && so.isDead) {
removeStormObject(so.ID);
((WeatherManagerServer)this).syncStormRemove(so);
} else {
/*if (getWorld().isRemote && so.ticksSinceLastPacketReceived > 20*60) {
Weather.dbg("WARNING!!! - detected no packets received in last 60 seconds for storm ID: " + so.ID + " this is an ongoing bug, force removing storm on client side");
removeStormObject(so.ID);
//if it failed still
if (!so.isDead) {
for (int ii = 0; ii < listStormObjects.size(); ii++) {
StormObject so2 = listStormObjects.get(ii);
if (so2 == so) {
Weather.dbg("second attempt removal via list iteration");
so2.remove();
listStormObjects.remove(so2);
lookupStormObjectsByID.remove(so2.ID);
lookupStormObjectsByLayer.get(so2.layer).remove(so2);
}
}
}
} else {*/
if (!so.isDead) {
so.tick();
} else {
if (getWorld().isRemote) {
Weather.dbg("WARNING!!! - detected isDead storm object still in client side list, had to remove storm object with ID " + so.ID + " from client side, wasnt properly isDead via main channels");
removeStormObject(so.ID);
}
//Weather.dbg("client storm is dead and still in list, bug?");
}
//}
}
}
//tick volcanos
/*for (int i = 0; i < getVolcanoObjects().size(); i++) {
getVolcanoObjects().get(i).tick();
}*/
//tick wind
windMan.tick();
}
}
public void tickRender(float partialTick) {
World world = getWorld();
if (world != null) {
//tick storms
//There are scenarios where getStormObjects().get(i) returns a null storm, uncertain why, for now try to catch it and move on
try {
for (int i = 0; i < getStormObjects().size(); i++) {
WeatherObject obj = getStormObjects().get(i);
if (obj != null) {
obj.tickRender(partialTick);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public List<WeatherObject> getStormObjects() {
return listStormObjects;
}
public List<StormObject> getStormObjectsByLayer(int layer) {
return lookupStormObjectsByLayer.get(layer);
}
public StormObject getStormObjectByID(long ID) {
WeatherObject obj = lookupStormObjectsByID.get(ID);
if (obj instanceof StormObject) {
return (StormObject) obj;
} else {
return null;
}
}
public void addStormObject(WeatherObject so) {
if (!lookupStormObjectsByID.containsKey(so.ID)) {
listStormObjects.add(so);
lookupStormObjectsByID.put(so.ID, so);
if (so instanceof StormObject) {
StormObject so2 = (StormObject) so;
lookupStormObjectsByLayer.get(so2.layer).add(so2);
}
} else {
Weather.dbg("Weather2 WARNING!!! Received new storm create for an ID that is already active! design bug or edgecase with PlayerEvent.Clone, ID: " + so.ID);
Weather.dbgStackTrace();
}
}
public void removeStormObject(long ID) {
WeatherObject so = lookupStormObjectsByID.get(ID);
if (so != null) {
so.remove();
listStormObjects.remove(so);
lookupStormObjectsByID.remove(ID);
if (so instanceof StormObject) {
StormObject so2 = (StormObject) so;
lookupStormObjectsByLayer.get(so2.layer).remove(so2);
}
} else {
Weather.dbg("error looking up storm ID on server for removal: " + ID + " - lookup count: " + lookupStormObjectsByID.size() + " - last used ID: " + WeatherObject.lastUsedStormID);
}
}
/*public List<VolcanoObject> getVolcanoObjects() {
return listVolcanoes;
}
public void addVolcanoObject(VolcanoObject so) {
if (!lookupVolcanoes.containsKey(so.ID)) {
listVolcanoes.add(so);
lookupVolcanoes.put(so.ID, so);
} else {
Weather.dbg("Weather2 WARNING!!! Client received new volcano create for an ID that is already active! design bug");
}
}
public void removeVolcanoObject(long ID) {
VolcanoObject vo = lookupVolcanoes.get(ID);
if (vo != null) {
vo.remove();
listVolcanoes.remove(vo);
lookupVolcanoes.remove(ID);
Weather.dbg("removing volcano");
}
}*/
public StormObject getClosestStormAny(Vec3 parPos, double maxDist) {
return getClosestStorm(parPos, maxDist, -1, true);
}
public StormObject getClosestStorm(Vec3 parPos, double maxDist, int severityFlagMin) {
return getClosestStorm(parPos, maxDist, severityFlagMin, false);
}
public StormObject getClosestStorm(Vec3 parPos, double maxDist, int severityFlagMin, boolean orRain) {
/*StormObject closestStorm = null;
double closestDist = Double.MAX_VALUE;
List<WeatherObject> listStorms = getStormObjects();
for (int i = 0; i < listStorms.size(); i++) {
WeatherObject wo = listStorms.get(i);
if (wo instanceof StormObject) {
StormObject storm = (StormObject) wo;
if (storm == null || storm.isDead) continue;
double dist = storm.pos.distanceTo(parPos);
*//*if (getWorld().isRemote) {
System.out.println("close storm candidate: " + dist + " - " + storm.state + " - " + storm.attrib_rain);
}*//*
if (dist < closestDist && dist <= maxDist) {
if ((storm.attrib_precipitation && orRain) || (severityFlagMin == -1 || storm.levelCurIntensityStage >= severityFlagMin)) {
closestStorm = storm;
closestDist = dist;
}
}
}
}
return closestStorm;*/
//not sure i can avoid a double use of distance calculation adding to iteration cost, this method might not be stream worthy
return getStormObjects().stream()
.map(wo -> (StormObject)wo)
.filter(so -> !so.isDead)
.filter(so -> (so.attrib_precipitation && orRain) || (severityFlagMin == -1 || so.levelCurIntensityStage >= severityFlagMin))
.filter(so -> so.pos.distanceTo(parPos) < maxDist)
.min(Comparator.comparing(so -> so.pos.distanceTo(parPos))).orElse(null);
}
public boolean isPrecipitatingAt(BlockPos pos) {
return isPrecipitatingAt(new Vec3(pos));
}
/**
* TODO: Heavy on the processing, consider caching the result by location for 20 ticks
*
* @param parPos
* @return
*/
public boolean isPrecipitatingAt(Vec3 parPos) {
/*List<WeatherObject> listStorms = getStormObjects();
for (int i = 0; i < listStorms.size(); i++) {
WeatherObject wo = listStorms.get(i);
if (wo instanceof StormObject) {
StormObject storm = (StormObject) wo;
if (storm == null || storm.isDead) continue;
if (storm.attrib_precipitation) {
double dist = storm.pos.distanceTo(parPos);
if (dist < storm.size) {
return true;
}
}
}
}
return false;*/
return getStormObjects().stream()
.map(wo -> (StormObject)wo)
.anyMatch(so -> !so.isDead && so.attrib_precipitation && so.pos.distanceTo(parPos) < so.size);
}
/**
* Simply compares stormfront distances, doesnt factor in tail
*
* @param parPos
* @param maxDist
* @return
*/
public WeatherObjectSandstorm getClosestSandstorm(Vec3 parPos, double maxDist) {
WeatherObjectSandstorm closestStorm = null;
double closestDist = 9999999;
List<WeatherObject> listStorms = getStormObjects();
for (int i = 0; i < listStorms.size(); i++) {
WeatherObject wo = listStorms.get(i);
if (wo instanceof WeatherObjectSandstorm) {
WeatherObjectSandstorm storm = (WeatherObjectSandstorm) wo;
if (storm == null || storm.isDead) continue;
double dist = storm.pos.distanceTo(parPos);
/*if (getWorld().isRemote) {
System.out.println("close storm candidate: " + dist + " - " + storm.state + " - " + storm.attrib_rain);
}*/
if (dist < closestDist && dist <= maxDist) {
//if ((storm.attrib_precipitation && orRain) || (severityFlagMin == -1 || storm.levelCurIntensityStage >= severityFlagMin)) {
closestStorm = storm;
closestDist = dist;
//}
}
}
}
return closestStorm;
}
/**
* Gets the most intense sandstorm, used for effects and sounds
*
* @param parPos
* @return
*/
public WeatherObjectSandstorm getClosestSandstormByIntensity(Vec3 parPos/*, double maxDist*/) {
WeatherObjectSandstorm bestStorm = null;
double closestDist = 9999999;
double mostIntense = 0;
List<WeatherObject> listStorms = getStormObjects();
for (int i = 0; i < listStorms.size(); i++) {
WeatherObject wo = listStorms.get(i);
if (wo instanceof WeatherObjectSandstorm) {
WeatherObjectSandstorm sandstorm = (WeatherObjectSandstorm) wo;
if (sandstorm == null || sandstorm.isDead) continue;
List<Vec3> field_75884_a = sandstorm.getSandstormAsShape();
double scale = sandstorm.getSandstormScale();
boolean inStorm = CoroUtilPhysics.isInConvexShape(parPos, field_75884_a);
double dist = CoroUtilPhysics.getDistanceToShape(parPos, field_75884_a);
//if best is within storm, compare intensity
if (inStorm) {
//System.out.println("in storm");
closestDist = 0;
if (scale > mostIntense) {
mostIntense = scale;
bestStorm = sandstorm;
}
//if best is not within storm, compare distance to shape
} else if (closestDist > 0/* && dist < maxDist*/) {
if (dist < closestDist) {
closestDist = dist;
bestStorm = sandstorm;
}
}
}
}
return bestStorm;
}
public List<WeatherObject> getSandstormsAround(Vec3 parPos, double maxDist) {
List<WeatherObject> storms = new ArrayList<>();
for (int i = 0; i < getStormObjects().size(); i++) {
WeatherObject wo = getStormObjects().get(i);
if (wo instanceof WeatherObjectSandstorm) {
WeatherObjectSandstorm storm = (WeatherObjectSandstorm) wo;
if (storm.isDead) continue;
if (storm.pos.distanceTo(parPos) < maxDist) {
storms.add(storm);
}
}
}
return storms;
}
public List<WeatherObject> getStormsAroundForDeflector(Vec3 parPos, double maxDist) {
List<WeatherObject> storms = new ArrayList<>();
for (int i = 0; i < getStormObjects().size(); i++) {
WeatherObject wo = getStormObjects().get(i);
if (wo.isDead) continue;
if (wo instanceof StormObject) {
StormObject storm = (StormObject) wo;
if (storm.pos.distanceTo(parPos) < maxDist && ((storm.attrib_precipitation && ConfigStorm.Storm_Deflector_RemoveRainstorms) || storm.levelCurIntensityStage >= ConfigStorm.Storm_Deflector_MinStageRemove)) {
storms.add(storm);
}
} else if (wo instanceof WeatherObjectSandstorm && ConfigStorm.Storm_Deflector_RemoveSandstorms) {
WeatherObjectSandstorm sandstorm = (WeatherObjectSandstorm)wo;
List<Vec3> field_75884_a = sandstorm.getSandstormAsShape();
double distToStorm = CoroUtilPhysics.getDistanceToShape(parPos, field_75884_a);
if (distToStorm < maxDist) {
storms.add(wo);
}
}
}
return storms;
}
public List<WeatherObject> getStormsAround(Vec3 parPos, double maxDist) {
List<WeatherObject> storms = new ArrayList<>();
for (int i = 0; i < getStormObjects().size(); i++) {
WeatherObject wo = getStormObjects().get(i);
if (wo.isDead) continue;
if (wo instanceof StormObject) {
StormObject storm = (StormObject) wo;
if (storm.pos.distanceTo(parPos) < maxDist && (storm.attrib_precipitation || storm.levelCurIntensityStage > StormObject.STATE_NORMAL)) {
storms.add(storm);
}
} else if (wo instanceof WeatherObjectSandstorm) {
WeatherObjectSandstorm sandstorm = (WeatherObjectSandstorm)wo;
List<Vec3> field_75884_a = sandstorm.getSandstormAsShape();
double distToStorm = CoroUtilPhysics.getDistanceToShape(parPos, field_75884_a);
if (distToStorm < maxDist) {
storms.add(wo);
}
}
}
return storms;
}
public void writeToFile() {
CompoundNBT mainNBT = new CompoundNBT();
/*CompoundNBT listVolcanoesNBT = new CompoundNBT();
for (int i = 0; i < listVolcanoes.size(); i++) {
VolcanoObject td = listVolcanoes.get(i);
CompoundNBT teamNBT = new CompoundNBT();
td.write(teamNBT);
listVolcanoesNBT.put("volcano_" + td.ID, teamNBT);
}
mainNBT.put("volcanoData", listVolcanoesNBT);
mainNBT.putLong("lastUsedIDVolcano", VolcanoObject.lastUsedID);*/
CompoundNBT listStormsNBT = new CompoundNBT();
for (int i = 0; i < listStormObjects.size(); i++) {
WeatherObject obj = listStormObjects.get(i);
obj.getNbtCache().setUpdateForced(true);
obj.write();
obj.getNbtCache().setUpdateForced(false);
listStormsNBT.put("storm_" + obj.ID, obj.getNbtCache().getNewNBT());
}
mainNBT.put("stormData", listStormsNBT);
mainNBT.putLong("lastUsedIDStorm", WeatherObject.lastUsedStormID);
mainNBT.putLong("lastStormFormed", lastStormFormed);
mainNBT.putLong("lastSandstormFormed", lastSandstormFormed);
mainNBT.putFloat("cloudIntensity", this.cloudIntensity);
mainNBT.put("windMan", windMan.write(new CompoundNBT()));
String saveFolder = CoroUtilFile.getWorldSaveFolderPath() + CoroUtilFile.getWorldFolderName() + "weather2" + File.separator;
try {
//Write out to file
if (!(new File(saveFolder).exists())) (new File(saveFolder)).mkdirs();
FileOutputStream fos = new FileOutputStream(saveFolder + "WeatherData_" + dim + ".dat");
CompressedStreamTools.writeCompressed(mainNBT, fos);
fos.close();
} catch (Exception ex) { ex.printStackTrace(); }
}
public void readFromFile() {
CompoundNBT rtsNBT = new CompoundNBT();
String saveFolder = CoroUtilFile.getWorldSaveFolderPath() + CoroUtilFile.getWorldFolderName() + "weather2" + File.separator;
boolean readFail = false;
try {
if ((new File(saveFolder + "WeatherData_" + dim + ".dat")).exists()) {
rtsNBT = CompressedStreamTools.readCompressed(new FileInputStream(saveFolder + "WeatherData_" + dim + ".dat"));
} else {
//readFail = true; - first run, no point
}
} catch (Exception ex) {
ex.printStackTrace();
readFail = true;
}
//If reading file was ok, make a backup and shift names for second backup
if (!readFail) {
try {
File tmp = (new File(saveFolder + "WeatherData_" + dim + "_BACKUP0.dat"));
if (tmp.exists()) FileUtils.copyFile(tmp, (new File(saveFolder + "WeatherData_" + dim + "_BACKUP1.dat")));
if ((new File(saveFolder + "WeatherData_" + dim + ".dat").exists())) FileUtils.copyFile((new File(saveFolder + "WeatherData_" + dim + ".dat")), (new File(saveFolder + "WeatherData_" + dim + "_BACKUP0.dat")));
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
System.out.println("WARNING! Weather2 File: WeatherData.dat failed to load, automatically restoring to backup from previous game run");
try {
//auto restore from most recent backup
if ((new File(saveFolder + "WeatherData_" + dim + "_BACKUP0.dat")).exists()) {
rtsNBT = CompressedStreamTools.readCompressed(new FileInputStream(saveFolder + "WeatherData_" + dim + "_BACKUP0.dat"));
} else {
System.out.println("WARNING! Failed to find backup file WeatherData_BACKUP0.dat, nothing loaded");
}
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("WARNING! Error loading backup file WeatherData_BACKUP0.dat, nothing loaded");
}
}
lastStormFormed = rtsNBT.getLong("lastStormFormed");
lastSandstormFormed = rtsNBT.getLong("lastSandstormFormed");
//prevent setting to 0 for worlds updating to new weather version
if (rtsNBT.contains("cloudIntensity")) {
cloudIntensity = rtsNBT.getFloat("cloudIntensity");
}
/*VolcanoObject.lastUsedID = rtsNBT.getLong("lastUsedIDVolcano");*/
WeatherObject.lastUsedStormID = rtsNBT.getLong("lastUsedIDStorm");
windMan.read(rtsNBT.getCompound("windMan"));
/*CompoundNBT nbtVolcanoes = rtsNBT.getCompound("volcanoData");
Iterator it = nbtVolcanoes.keySet().iterator();
while (it.hasNext()) {
String tagName = (String) it.next();
CompoundNBT teamData = nbtVolcanoes.getCompound(tagName);
VolcanoObject to = new VolcanoObject(ServerTickHandler.lookupDimToWeatherMan.get(0));
try {
to.read(teamData);
} catch (Exception ex) {
ex.printStackTrace();
}
//to.initAITree();
//addVolcanoObject(to);
//THIS LINE NEEDS REFINING FOR PLAYERS WHO JOIN AFTER THE FACT!!!
//((WeatherManagerServer)(this)).syncVolcanoNew(to);
//listVolcanoes.add(to);
//lookupVolcanoes.put(to.ID, to);
to.initPost();
}*/
CompoundNBT nbtStorms = rtsNBT.getCompound("stormData");
Iterator it = nbtStorms.keySet().iterator();
while (it.hasNext()) {
String tagName = (String) it.next();
CompoundNBT data = nbtStorms.getCompound(tagName);
if (ServerTickHandler.lookupDimToWeatherMan.get(dim) != null) {
WeatherObject wo = null;
if (data.getInt("weatherObjectType") == EnumWeatherObjectType.CLOUD.ordinal()) {
wo = new StormObject(this/*-1, -1, null*/);
} else if (data.getInt("weatherObjectType") == EnumWeatherObjectType.SAND.ordinal()) {
wo = new WeatherObjectSandstorm(this);
//initStormNew???
}
try {
wo.getNbtCache().setNewNBT(data);
wo.read();
wo.getNbtCache().updateCacheFromNew();
} catch (Exception ex) {
ex.printStackTrace();
}
addStormObject(wo);
//TODO: possibly unneeded/redundant/bug inducing, packets will be sent upon request from client
((WeatherManagerServer)(this)).syncStormNew(wo);
} else {
System.out.println("WARNING: trying to load storm objects for missing dimension: " + dim);
}
//listVolcanoes.add(to);
//lookupVolcanoes.put(to.ID, to);
//to.initPost();
}
}
public WindManager getWindManager() {
return this.windMan;
}
public HashSet<Long> getListWeatherBlockDamageDeflector() {
return listWeatherBlockDamageDeflector;
}
public void setListWeatherBlockDamageDeflector(HashSet<Long> listWeatherBlockDamageDeflector) {
this.listWeatherBlockDamageDeflector = listWeatherBlockDamageDeflector;
}
}