Skip to content

Commit

Permalink
implemented missile simulation WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
GHXX committed Jul 29, 2018
1 parent 858a575 commit 77bacfb
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 3 deletions.
16 changes: 16 additions & 0 deletions src/main/java/icbm/classic/ICBMClassic.java
Expand Up @@ -5,6 +5,7 @@
import icbm.classic.content.blocks.*;
import icbm.classic.content.entity.*;
import icbm.classic.content.entity.missile.EntityMissile;
import icbm.classic.content.entity.missile.MissileSimulationHandler;
import icbm.classic.content.explosive.Explosives;
import icbm.classic.content.explosive.tile.BlockExplosive;
import icbm.classic.content.explosive.tile.ItemBlockExplosive;
Expand Down Expand Up @@ -67,6 +68,7 @@
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.*;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
Expand Down Expand Up @@ -181,6 +183,8 @@ public final class ICBMClassic
public static final ContagiousPoison contagios_potion = new ContagiousPoison("Contagious", 1, true);

public static final ICBMCreativeTab CREATIVE_TAB = new ICBMCreativeTab(DOMAIN);
public static MissileSimulationHandler missileSimulationHandler;


@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event)
Expand Down Expand Up @@ -409,6 +413,18 @@ else if (event.getName().equals(LootTableList.ENTITIES_CREEPER))
}
}


@SubscribeEvent
public static void onWorldLoad(WorldEvent.Load event)
{
if (!event.getWorld().isRemote) // if server
{
missileSimulationHandler = new MissileSimulationHandler(event.getWorld().getWorldInfo().getWorldName());
missileSimulationHandler.handlerThread.start();
ICBMClassic.logger().info("Missile Simulation Handler Started");
}
}

@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event)
{
Expand Down
@@ -1,6 +1,7 @@
package icbm.classic.content.entity.missile;

import com.builtbroken.jlib.data.vector.IPos3D;
import com.sun.media.jfxmedia.logging.Logger;
import icbm.classic.ICBMClassic;
import icbm.classic.api.caps.IEMPReceiver;
import icbm.classic.api.explosion.IExplosiveContainer;
Expand All @@ -26,11 +27,14 @@
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import scala.Console;

import javax.annotation.Nullable;
import java.util.HashSet;
Expand Down Expand Up @@ -78,7 +82,9 @@ public class EntityMissile extends EntityProjectile implements IEntityAdditional

public Pos motionVector = new Pos();

private double lockHeight = 3;
public double lockHeight = 3;

public boolean wasSimulated = false;

// Used for the rocket launcher preventing the players from killing themselves.
private final HashSet<Entity> ignoreEntity = new HashSet<Entity>();
Expand All @@ -87,6 +93,10 @@ public class EntityMissile extends EntityProjectile implements IEntityAdditional

public IEMPReceiver capabilityEMP;

private ForgeChunkManager.Ticket chunkLoadTicket;
private ChunkPos currentLoadedChunk;
private ChunkPos oldloadedChunk;

public EntityMissile(World w)
{
super(w);
Expand Down Expand Up @@ -253,6 +263,7 @@ public void recalculatePath()
this.missileFlightTime = (float) Math.max(100, 2 * this.flatDistance) - this.ticksInAir;
// Acceleration
this.acceleration = (float) this.maxHeight * 2 / (this.missileFlightTime * this.missileFlightTime);

}
else if (missileType.movesDirectly)
{
Expand All @@ -266,6 +277,19 @@ public void entityInit()
{
//this.dataWatcher.addObject(16, -1);
//this.dataWatcher.addObject(17, 0);
/*ForgeChunkManager.setForcedChunkLoadingCallback(ICBMClassic.INSTANCE,null);
chunkLoadTicket = ForgeChunkManager.requestTicket(ICBMClassic.INSTANCE,this.world, ForgeChunkManager.Type.NORMAL);
if (chunkLoadTicket != null) // if we are allowed to load chunks
{
currentLoadedChunk = new ChunkPos((int)this.posX>>4,(int)this.posZ>>4);
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);
ICBMClassic.logger().warn("(Init) Forced chunk at: "+currentLoadedChunk.toString());
}
else
{
ICBMClassic.logger().warn("Unable to receive chunkloading ticket. You could try to increase the maximum loaded chunks for ICBM.");
}*/
}

@Override
Expand All @@ -281,9 +305,33 @@ protected void updateMotion()
{
if (this.ticksInAir >= 0)
{
if (this.missileType == MissileFlightType.PAD_LAUNCHER)
{
if (this.missileType == MissileFlightType.PAD_LAUNCHER) {

/* if (chunkLoadTicket != null) // if we are allowed to load chunks
{
// if (oldloadedChunk != null && (oldloadedChunk.getXStart() > this.x() || oldloadedChunk.getXEnd() < this.x())
// && (oldloadedChunk.getZStart() > this.z() || oldloadedChunk.getZEnd() < this.z()))
// {
// ForgeChunkManager.unforceChunk(chunkLoadTicket, oldloadedChunk);
// ICBMClassic.logger().warn("Unforced chunk at: "+oldloadedChunk.toString());
// oldloadedChunk = null;
// }
// load chunks
ChunkPos nextChunk = new ChunkPos((int) (this.posX + this.motionX)>>4, (int) (this.posZ + this.motionZ)>>4);
//ICBMClassic.logger().warn("Speed: X:"+this.motionX+" Z:" +this.motionZ);
if (nextChunk.x != currentLoadedChunk.x || nextChunk.z != currentLoadedChunk.z) { // next chunk is a different one. lets load a new chunk and mark the current one for unloading
oldloadedChunk = currentLoadedChunk;
currentLoadedChunk = nextChunk;
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);
ICBMClassic.logger().warn("Forced chunk at: "+currentLoadedChunk.toString());
}
}
ICBMClassic.logger().warn("Speed: y" +this.motionY + "Pos y" +this.y() + "Est next y" +(this.y() + this.motionY));*/
// Start the launch


if (this.lockHeight > 0)
{
this.motionY = ConfigMissile.LAUNCH_SPEED * this.ticksInAir * (this.ticksInAir / 2);
Expand All @@ -304,7 +352,19 @@ protected void updateMotion()
// Look at the next point
this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180 / Math.PI);
}



if (targetPos.distance(launcherPos)>50 && !wasSimulated && this.ticksInAir > 20*5) // 5 seconds
{
ICBMClassic.logger().info("Simulating missile.");
ICBMClassic.missileSimulationHandler.AddMissile(this);
this.setDead();
}

}

ICBMClassic.logger().info("x/y/z: "+this.posX+"/"+this.posY+"/"+this.posZ);
}
else
{
Expand Down
@@ -0,0 +1,209 @@
package icbm.classic.content.entity.missile;

import com.builtbroken.jlib.data.vector.Pos3D;
import com.google.common.util.concurrent.UncheckedExecutionException;
import icbm.classic.ICBMClassic;
import icbm.classic.content.explosive.Explosives;
import icbm.classic.content.explosive.handlers.missiles.Missile;
import icbm.classic.lib.transform.vector.Pos;
import javafx.util.Pair;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.storage.WorldSavedData;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import scala.unchecked;

import java.io.InvalidObjectException;
import java.util.*;


public class MissileSimulationHandler extends WorldSavedData{

public Thread handlerThread = null;
private Stack<EntityMissile> missileBuffer;
private ForgeChunkManager.Ticket chunkLoadTicket;
private Stack<Pair<ChunkPos, Integer>> currentLoadedChunks;

public MissileSimulationHandler(String mapName)
{
super(mapName);
missileBuffer = new Stack<EntityMissile>();
handlerThread = new Thread(new Runnable() {
@Override
public void run() {
SimulationLoop();
}
}, "ICBM-MissileSimThread");
currentLoadedChunks = new Stack<>();
ForgeChunkManager.setForcedChunkLoadingCallback(ICBMClassic.INSTANCE,null);
}

protected void AddMissile(EntityMissile missile)
{
if(missile.world.isRemote)
{
throw new UncheckedExecutionException(new InvalidObjectException("Missile handler cannot be constructed Clientside!"));
}

// create copy
EntityMissile newMissile = new EntityMissile(missile.world());

// copy data
newMissile.explosiveID = missile.explosiveID;
newMissile.launcherPos = missile.launcherPos;
newMissile.setPosition(missile.posX,missile.posY,missile.posZ);
newMissile.lockHeight = missile.lockHeight;
newMissile.targetPos = missile.targetPos;
newMissile.world = missile.world;
newMissile.ticksInAir = (int)missile.missileFlightTime - 20;
newMissile.wasSimulated = true;
newMissile.motionX = speedPerSec*Math.signum(missile.targetPos.x() - missile.posX);
newMissile.motionZ = speedPerSec*Math.signum(missile.targetPos.z() - missile.posZ);

missileBuffer.add(newMissile);
}

private final int speedPerSec = 100;
private final int unloadChunkCooldown = 60;

private void SimulationLoop()
{
boolean doRun = true;
while (doRun)
{
for (int i = 0; i<missileBuffer.size();i++)
{
EntityMissile missile = missileBuffer.get(i);
if (missile.posX == missile.targetPos.x() && missile.posZ == missile.targetPos.z()) // if missile is at the target location
{
missile.missileType = MissileFlightType.DEAD_AIM;
ICBMClassic.logger().info("["+i+"] Reached target location");
try {
if (chunkLoadTicket == null) {
chunkLoadTicket = ForgeChunkManager.requestTicket(ICBMClassic.INSTANCE, missile.world, ForgeChunkManager.Type.NORMAL);
}
if (chunkLoadTicket != null) // if we are allowed to load chunks
{
ChunkPos currentLoadedChunk = new ChunkPos((int) missile.posX >> 4, (int) missile.posZ >> 4);
currentLoadedChunks.add(new Pair(currentLoadedChunk, unloadChunkCooldown));
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);
ICBMClassic.logger().warn("(Init) Forced chunk at: " + currentLoadedChunk.toString());
currentLoadedChunk = new ChunkPos(1+((int) missile.posX >> 4), (int) missile.posZ >> 4);
currentLoadedChunks.add(new Pair(currentLoadedChunk, unloadChunkCooldown));
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);
ICBMClassic.logger().warn("(Init) Forced chunk at: " + currentLoadedChunk.toString());
currentLoadedChunk = new ChunkPos(-1+((int) missile.posX >> 4), (int) missile.posZ >> 4);
currentLoadedChunks.add(new Pair(currentLoadedChunk, unloadChunkCooldown));
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);
ICBMClassic.logger().warn("(Init) Forced chunk at: " + currentLoadedChunk.toString());
currentLoadedChunk = new ChunkPos((int) missile.posX >> 4, 1+((int) missile.posZ >> 4));
currentLoadedChunks.add(new Pair(currentLoadedChunk, unloadChunkCooldown));
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);
ICBMClassic.logger().warn("(Init) Forced chunk at: " + currentLoadedChunk.toString());
currentLoadedChunk = new ChunkPos((int) missile.posX >> 4 , -1+((int) missile.posZ >> 4));
currentLoadedChunks.add(new Pair(currentLoadedChunk, unloadChunkCooldown));
ForgeChunkManager.forceChunk(chunkLoadTicket, currentLoadedChunk);

ICBMClassic.logger().warn("(Init) Forced chunk at: " + currentLoadedChunk.toString());
} else {
ICBMClassic.logger().warn("Unable to receive chunkloading ticket. You could try to increase the maximum loaded chunks for ICBM.");
}
}
catch (Exception e)
{
ICBMClassic.logger().warn("Exception!");
}

missile.posY = 125;
missile.motionY = -10;
missile.motionZ = 0;
missile.motionX = 0;

missile.lockHeight = 0;
missile.acceleration = 40;
Launch(missile);
missileBuffer.remove(i);
}
else
{
ICBMClassic.logger().info("["+i+"] Adjusting target x, z. Current Delta: "+(missile.targetPos.x() - missile.posX)+", "+(missile.targetPos.z() - missile.posZ));
double currDeltaX = Math.abs(missile.targetPos.x() - missile.posX);
double nextDeltaX = Math.abs(currDeltaX - missile.motionX);
double currDeltaZ = Math.abs(missile.targetPos.z() - missile.posZ);
double nextDeltaZ = Math.abs(currDeltaZ - missile.motionZ);


if (nextDeltaX < currDeltaX) // lets tro to move the missile closer. if we cant then we are at the target pos.
{
missile.posX += missile.motionX;
}
else
{
missile.posX = missile.targetPos.x();
ICBMClassic.logger().info("["+i+"] Reached target x");
}
if (nextDeltaZ < currDeltaZ)
{
missile.posZ += missile.motionZ;
}
else
{
missile.posZ = missile.targetPos.z();
ICBMClassic.logger().info("["+i+"] Reached target z");
}
}
}

for (int i = 0; i<currentLoadedChunks.size();i++) {
ChunkPos chunkPos = currentLoadedChunks.elementAt(i).getKey();
int waitTime = currentLoadedChunks.elementAt(i).getValue() - 1;
if (waitTime <= 0)
{
ForgeChunkManager.unforceChunk(chunkLoadTicket,chunkPos);
currentLoadedChunks.removeElementAt(i);
ICBMClassic.logger().info("Unforced chunk");
}
else
{
currentLoadedChunks.setElementAt(new Pair(chunkPos,waitTime),i);
}

}

try {
Thread.sleep(1000);
}
catch (InterruptedException e)
{
doRun = false;
}
}
}

private void Launch(EntityMissile missile)
{
//Trigger launch event
missile.launch(missile.targetPos, (int)missile.lockHeight);
try {
Thread.sleep(1000);
}
catch (Exception e){}
//Spawn entity
missile.world().spawnEntity(missile);
}

@Override
public void readFromNBT(NBTTagCompound nbt) {
}

@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
handlerThread.interrupt();
missileBuffer.clear();
return null;
}

}

0 comments on commit 77bacfb

Please sign in to comment.