package equipment;
import static dcpu.DcpuConstants.REG_A;
import static dcpu.DcpuConstants.REG_B;
import static dcpu.DcpuConstants.REG_C;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import physics.Body;
import physics.BodyForce;
import physics.ForceSource;
import render.BodyRenderNode;
import render.RTTRenderNode;
import render.RenderNode;
import render.RenderPreferences;
import ships.Equipment;
import ships.Ship;
import dcpu.CpuWatcher;
import dcpu.Dcpu;
import dcpu.Hardware;
public class Engine implements Equipment, ForceSource, CpuWatcher, Hardware {
private float max;
private float t2;
private float t1;
private float r;
private long onRate;
private long onMax;
private char setpoint;
private float renderOnness;
private char[] commands;
private char[] setpoints;
private Ship ship;
private int fullCost;
private char hwid;
public Engine(float r, float t1, float t2, float max, int fullCost, char hwid) {
this.r = r;
this.t1 = t1;
this.t2 = t2;
this.max = max;
commands = new char[4];
setpoints = new char[4];
this.fullCost = fullCost;
this.hwid = hwid;
}
public static RenderNode makeIndependantPart(Body base) {
return new BodyRenderNode(base) {
public void draw(Graphics2D g, RenderPreferences prefs) {
Engine.draw(g, prefs, 1f);
}
};
}
public static void draw(Graphics2D g, RenderPreferences prefs, float renderOnness) {
int t = prefs.borderThickness();
g.translate(14, 0);
g.setStroke(new BasicStroke(t));
g.setColor(prefs.borderColor());
g.drawRect(-25, -15, 20, 30);
g.drawRect(-5, -10, 5, 20);
g.setColor(prefs.body1());
g.fillRect(-25, -15, 20, 30);
g.setColor(prefs.highlight1());
g.fillRect(-5, -10, 5, 20);
g.setColor(prefs.borderColor());
g.fillPolygon(new int[]{0,0,(int)(16*Math.sqrt(renderOnness)+t*2)}, new int[]{-8-t*2,8+t*2,0}, 3);
g.fillPolygon(new int[]{0,0,(int)(22*Math.sqrt(renderOnness)+t*2)}, new int[]{-4-t*2,4+t*2,0}, 3);
g.setColor(new Color(180,180,255));
g.fillPolygon(new int[]{0,0,(int)(16*Math.sqrt(renderOnness))}, new int[]{-8,8,0}, 3);
g.setColor(new Color(220,220,255));
g.fillPolygon(new int[]{0,0,(int)(22*Math.sqrt(renderOnness))}, new int[]{-4,4,0}, 3);
}
public void addedTo(Ship s) {
s.addBodyForce(new BodyForce(this));
s.addRenderNode(new RTTRenderNode(this) {
public void draw(Graphics2D g, RenderPreferences prefs) {
Engine.draw(g, prefs, renderOnness);
}
});
s.cpu.addWatcher(this);
s.cpu.addHardware(hwid, this);
ship = s;
}
public void reset() {
onRate = 0;
onMax = 0;
setpoint = 0;
}
public void physicsTickPreForce() {
if (onMax == 0) {
renderOnness = 0f;
} else {
float mix = (float)onRate / onMax;
int mixportion = 2;
renderOnness = (renderOnness * (mixportion) + mix)/(mixportion+1);
}
if (onMax > 0) {
ship.power.sink(fullCost*onRate/onMax);
}
}
public void physicsTickPostForce() {
this.onMax = 0;
this.onRate = 0;
}
public void triggerSynchronizedEvent(char id, int cyclesAgo) {
for (int i=0;i<commands.length;i++) {
if (id == commands[i]) {
setpoint = setpoints[i];
}
}
}
public float position_radius() {
return r;
}
public float position_theta() {
return t1;
}
public float alignment_theta() {
return t2;
}
public float force_magnitude() {
if (onMax == 0) {
return 0;
}
return max * onRate / onMax;
}
public void cpu_changed(Dcpu cpu, long cyclesAdvanved, boolean idle) {
onRate += cyclesAdvanved * setpoint;
onMax += cyclesAdvanved * 0xFFFF;
}
public void plugged_in(Dcpu parent, char id) {
}
public void query(Dcpu parent) {
}
public void interrupted(Dcpu parent) {
parent.cyclecnt+=1;
if (parent.regs.gp[REG_A]==0) {
setpoint = parent.regs.gp[REG_B];
} else if (parent.regs.gp[REG_A]-1 < commands.length) {
commands[parent.regs.gp[REG_A]-1] = parent.regs.gp[REG_C];
setpoints[parent.regs.gp[REG_A]-1] = parent.regs.gp[REG_B];
System.out.printf("Engine %d cmd %d setpoint %d\n", (int)hwid, (int) parent.regs.gp[REG_C], (int)parent.regs.gp[REG_B]);
}
}
}