package space.celestials;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import space.models.Faction;
import space.models.Ship;
import space.physics.Entity;
import space.physics.Sandbox;
import sql.SQL;
public class StarSystem implements Runnable {
private static SQL sql = SQL.getInstance();
private static PreparedStatement select = sql.prepareStatement("SELECT * FROM `systems`");
public static ArrayList<StarSystem> load() throws SQLException {
try(ResultSet r = select.executeQuery()) {
ArrayList<StarSystem> system = new ArrayList<>();
while(r.next()) {
system.add(new StarSystem(r));
}
return system;
}
}
private int _id = -1;
public int nextID() { return _id--; }
private Thread _thread;
private boolean _running;
private int _tps = 60;
private long _celestialTimer;
private Sandbox _sandbox = new Sandbox();
public final int id;
private String _name;
private double _size;
public String getName() { return _name; }
public double getSize() { return _size; }
public Celestial star;
private ArrayList<Faction> _faction = new ArrayList<>();
private ArrayList<Ship> _ship = new ArrayList<>();
public Faction getFaction(int id) {
for(Faction faction : _faction) {
if(faction.id == id) {
return faction;
}
}
return null;
}
private StarSystem(ResultSet r) throws SQLException {
id = r.getInt("id");
_name = r.getString("name");
_size = r.getInt("size");
_faction = Faction.load(this);
_ship = Ship.load(this);
for(Ship ship : _ship) {
_sandbox.addToSandbox(ship);
}
System.out.println("Generating System[" + _name + "]");
// 290759680 x 32m/coordinate ~= 1/1000 scale our Solar system
System.out.println("System Size[" + (long)_size * 32 + "m][" + _size + "px]");
star = Celestial.load(this).get(0);
star.addToSandbox(_sandbox);
_running = true;
_thread = new Thread(this);
_thread.start();
_sandbox.startSandbox();
}
public void stop() {
_sandbox.stopSandbox();
while(_sandbox.isAlive()) {
try {
_sandbox.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
_running = false;
}
public void join() throws InterruptedException {
_thread.join();
}
public boolean isAlive() {
return _thread != null && _thread.isAlive();
}
public void sendEntities(Ship ship, Entity.Request request) {
for(int i = 0; i < request.i.length; i++) {
Entity e = _sandbox.getEntity(request.i[i]);
if(e != null) {
ship.sendEntity(e.serializeAdd());
}
}
}
public void sendCelestials(Ship ship, Entity.Request request) {
for(int i = 0; i < request.i.length; i++) {
Entity e = _sandbox.getEntity(request.i[i]);
if(e != null) {
ship.sendCelestial(e.serializeAdd());
}
}
}
public Ship findShip(int id) {
for(Ship ship : _ship) {
if(ship.id == id) {
return ship;
}
}
return null;
}
public void run() {
int interval = 1000000000 / 60;
_running = true;
long time, timeDelta = interval;
int ticks = 0;
long tickTime = System.nanoTime() + 1000000000l;
while(_running) {
time = System.nanoTime();
tick(timeDelta / interval);
// Track FPS
if(tickTime <= System.nanoTime()) {
_tps = ticks;
ticks = 0;
tickTime = System.nanoTime() + 1000000000l;
//System.out.println(_tps + " ticks per second");
}
ticks++;
// Sleep each loop if we have extra time
timeDelta = System.nanoTime() - time;
long timeSleep = interval - timeDelta;
long timeDeltaMS = timeSleep / 1000000l;
int timeDeltaNS = (int)(timeSleep - timeDeltaMS * 1000000);
if(timeSleep > 0) {
try { Thread.sleep(timeDeltaMS, timeDeltaNS); } catch(InterruptedException e) { }
}
}
}
private void tick(double deltaT) {
for(Ship ship : _ship) {
if(ship.user() != null) {
ship.updateList.clear();
for(Entity e : _sandbox) {
if(!(e instanceof Celestial)) {
if(ship.isNear(e)) {
ship.updateList.add(e.serializeUpdate());
}
}
}
ship.sendUpdate(ship.updateList.toArray(new Entity.Update[0]));
}
}
if(_celestialTimer <= System.nanoTime()) {
for(Ship ship : _ship) {
if(ship.user() != null) {
ship.celestList.clear();
for(Entity e : _sandbox) {
if(e instanceof Celestial) {
if(ship.isNear(e)) {
ship.celestList.add(e.serializeUpdate());
}
}
}
ship.sendCelestials(ship.celestList.toArray(new Entity.Update[0]));
}
}
_celestialTimer = System.nanoTime() + 1000000000l;
}
}
}