import java.lang.*; import java.io.*; import java.awt.*; /* * An important note concerning planets: The game assumes that the planets * are in a 'known' order. Ten planets per team, the first being the home * planet. */ /* the lower bits represent the original owning team */ class Planet implements Cloneable { public final static byte NOBODY = 0x00; public final static byte IND = 0x00; public final static byte FED = 0x01; public final static byte ROM = 0x02; public final static byte KLI = 0x04; public final static byte ORI = 0x08; public final static byte RACE_FED = 0x01; public final static byte RACE_ROM = 0x02; public final static byte RACE_KLI = 0x04; public final static byte RACE_ORI = 0x08; public final static byte RACE_IND = 0x10; public final static byte RACE_ME = 0x20; public final static byte NRACE_FED = 0x00; public final static byte NRACE_ROM = 0x01; public final static byte NRACE_KLI = 0x02; public final static byte NRACE_ORI = 0x03; public final static byte NRACE_IND = 0x04; public final static byte NRACE_ME = 0x05; public final static int PLREPAIR = 0x010; public final static int PLFUEL = 0x020; public final static int PLAGRI = 0x040; public final static int PLREDRAW = 0x080;/* Player close for redraw */ public final static int PLHOME = 0x100;/* home planet for a given team */ public final static int PLCOUP = 0x200;/* Coup has occured */ public final static int PLCHEAP = 0x400;/* Planet was taken from undefended team */ /* NEW */ public final static int PLCLEAR = 0x800;/* should the planet area be erased before redraw */ final int pl_width = 30; final int pl_height = 30; final int pl_mwidth = 16; final int pl_mheight = 16; public int pl_no; public int pl_flags; /* State information */ public int pl_owner; public int pl_x; public int pl_y; public String pl_name; public int pl_namelen; /* Cuts back on strlen's */ public int pl_armies; public int pl_info; /* Teams which have info on planets */ public int pl_deadtime; /* Time before planet will support life */ public int pl_couptime; /* Time before coup may take place */ boolean c_armies, c_known; int c_race; int c_flags; Image c_image, c_mimage; Rectangle erase_area; public Planet(int num) { pl_no = num; pl_name = new String(); pl_namelen = 0; pl_flags = 0; c_image = null; erase_area = new Rectangle(-10000, -10000, 0, 0); } public Planet copy() { Planet ret = null; try { ret = (Planet) clone(); } catch(CloneNotSupportedException ex) { } ret.pl_name = new String(pl_name); c_image = null; erase_area = new Rectangle(-10000, -10000, 0, 0); return ret; } public void SetRedraw() { pl_flags |= PLREDRAW; } public void SetClear() { pl_flags |= (PLREDRAW|PLCLEAR); } public int GetRace() { int team = pl_owner; for (byte n = 0; team != 0; n++) { if ((team & 1) != 0) return n; team >>= 1; } return 4; //RACE_IND; } public void SetData(int owner, int info, int armies, int flags) { boolean redraw; redraw = (pl_owner != owner || pl_info != info || pl_flags != flags || ((pl_armies > 4) ^ (armies > 4))); pl_owner = owner; pl_info = info; pl_flags = flags | (pl_flags & (PLREDRAW|PLCLEAR)); pl_armies = armies; if (pl_owner < FED || pl_owner > ORI || pl_info == 0) pl_owner = NOBODY; if (redraw) SetClear(); } public void SetLoc(String name, int x, int y) { pl_x = x; pl_y = y; pl_name = name; pl_namelen = name.length(); SetClear(); } void UpdateCache(NetrekImageLib lib, int race, int flags, boolean armies, boolean known) { if (c_image == null || c_race != race || c_armies != armies || (c_flags & (PLFUEL|PLREPAIR)) != (flags & (PLFUEL|PLREPAIR)) || known != c_known) { c_flags = flags; c_race = race; c_armies = armies; c_known = known; int type = 0; if (c_known) { if ((c_flags & PLFUEL) != 0) type += 1; if ((c_flags & PLREPAIR) != 0) type += 2; if (c_armies) type += 4; } else { type = 8; race = NRACE_IND; } c_image = lib.GetImage("STDALL", "PLANET", race, type); c_mimage = lib.GetImage("STDALL", "MPLANET", race, type); } } public void paintLocal(NetrekImageLib lib, Graphics g, ServerState state, Eraser eraser) { Image img; int x = state.RealToRelativeXCoordinate(pl_x); int y = state.RealToRelativeYCoordinate(pl_y); if (!state.IsVisible(x, y)) return; int race = GetRace(); UpdateCache(lib, race, pl_flags, pl_armies > 4, (pl_info & state.me.p_team) != 0); img = c_image; if (img != null) { g.drawImage(img, x - img.getWidth(null)/2, y - img.getHeight(null)/2, null); g.setColor(lib.GetRaceColor(race)); FontMetrics fm = g.getFontMetrics(); g.drawString(pl_name, x - fm.stringWidth(pl_name)/2, y + pl_height/2 + fm.getMaxAscent()); } } public void PrepareToErase(Eraser eraser) { if ((pl_flags & PLCLEAR) == 0) return; eraser.AddArea(erase_area.x, erase_area.y, erase_area.width, erase_area.height); pl_flags &= ~PLCLEAR; } public void paintGalactic(NetrekImageLib lib, Graphics g, ServerState state) { Image img; if ((pl_flags & PLREDRAW) == 0) return; int x = state.RealToGalacticCoordinate(pl_x); int y = state.RealToGalacticCoordinate(pl_y); int race = GetRace(); UpdateCache(lib, race, pl_flags, pl_armies > 4, (pl_info & state.me.p_team) != 0); img = c_mimage; if (img != null) { int w = img.getWidth(null); int h = img.getHeight(null); g.drawImage(img, x - w/2, y - h/2, null); g.setColor(lib.GetRaceColor(race)); FontMetrics fm = g.getFontMetrics(); String name = pl_name.substring(0, 3); int tw = fm.stringWidth(name); int tha = fm.getMaxAscent(); int thd = fm.getMaxDescent(); g.drawString(name, x - tw/2, y + pl_mheight/2 + tha); if (tw > w) w = tw; erase_area.x = x - w/2; erase_area.y = y - h/2; erase_area.width = w; erase_area.height = pl_mheight + tha + thd; } pl_flags &= ~PLREDRAW; } } class Planets implements Cloneable { final static int REGIONS = 40; final static int PDIST = 4500; Planet planets[]; byte buf[]; Planet redraws[][]; public Planets(int num) { planets = new Planet[num]; for (int i = 0; i < num; i++) planets[i] = new Planet(i); buf = new byte[2048]; redraws = new Planet[REGIONS][REGIONS]; for (int i = 0; i < REGIONS; i++) for (int j = 0; j < REGIONS; j++) redraws[i][j] = null; } public Planets copy() { Planets ret = null; try { ret = (Planets) clone(); } catch(CloneNotSupportedException ex) { } ret.planets = new Planet[planets.length]; for (int i = 0; i < planets.length; i++) ret.planets[i] = planets[i].copy(); ret.redraws = new Planet[REGIONS][REGIONS]; for (int i = 0; i < REGIONS; i++) for (int j = 0; j < REGIONS; j++) if (redraws[i][j] == null) ret.redraws[i][j] = null; else ret.redraws[i][j] = ret.planets[redraws[i][j].pl_no]; return ret; } public int Number() { return planets.length; } public Planet GetPlanet(int idx) { return planets[idx]; } public void PrepareToErase(Eraser eraser) { for (int i = 0; i < planets.length; i++) planets[i].PrepareToErase(eraser); } public void GalacticRedraw(NetrekImageLib lib, Graphics g, ServerState state, boolean redraw) { if (redraw) { for (int i = 0; i < planets.length; i++) planets[i].SetRedraw(); } for (int i = 0; i < planets.length; i++) planets[i].paintGalactic(lib, g, state); } public void RedrawPosition(ServerState state, int x, int y) { if (x < 0 || x >= state.gwidth || y < 0 || y >= state.gwidth) return; int size = state.gwidth/REGIONS; Planet pl = redraws[x/size][y/size]; if (pl != null) pl.SetRedraw(); } public void DumpStateInit(DataOutput data) throws IOException { for (byte i = 0; i < planets.length; i++) sendPlLoc(data, i); } public void DumpState(DataOutput data) throws IOException { for (byte i = 0; i < planets.length; i++) sendPlanet(data, i); } // struct planet_loc_spacket { // char type; /* SP_PLANET_LOC */ // char pnum; // char pad2; // char pad3; // LONG x; // LONG y; // char name[16]; // }; void handlePlLoc(ServerState state, DataInput data) throws IOException { byte pnum = data.readByte(); byte pad2 = data.readByte(); byte pad3 = data.readByte(); int x = data.readInt(); int y = data.readInt(); byte name[] = buf; data.readFully(name, 0, 16); name[15] = 0; String sname = new String(name, 0, 0, 16); sname = sname.substring(0, sname.indexOf(0)); Planet pl = planets[pnum]; pl.SetLoc(sname, x, y); MarkNet(state, x, y, pl); } void sendPlLoc(DataOutput data, byte pnum) throws IOException { Planet pl = planets[pnum]; data.writeByte(NetrekState.SP_PLANET_LOC); data.writeByte(pnum); data.writeByte(0); data.writeByte(0); data.writeInt(pl.pl_x); data.writeInt(pl.pl_y); pl.pl_name.getBytes(0, pl.pl_name.length(), buf, 0); buf[pl.pl_name.length()] = 0; data.write(buf, 0, 16); } // struct planet_spacket { // char type; /* SP_PLANET */ // char pnum; // char owner; // char info; // short flags; // short pad2; // LONG armies; // }; public void handlePlanet(DataInput data) throws IOException { byte pnum = data.readByte(); byte owner = data.readByte(); byte info = data.readByte(); short flags = data.readShort(); short pad2 = data.readShort(); int armies = data.readInt(); Planet pl = planets[pnum]; pl.SetData(owner, info, armies, flags); } void sendPlanet(DataOutput data, byte pnum) throws IOException { Planet pl = planets[pnum]; data.writeByte(NetrekState.SP_PLANET); data.writeByte(pnum); data.writeByte(pl.pl_owner); data.writeByte(pl.pl_info); data.writeShort((short)pl.pl_flags); data.writeShort(0); data.writeInt(pl.pl_armies); } // struct planet_s_spacket { /* body of SP_S_PLANET */ // char pnum; // char owner; // char info; // unsigned char armies; /* more than 255 Armies ? ... */ // short flags; // }; public void handleSPlanet(DataInput data) throws IOException { byte num = data.readByte(); int size = num * 6 + 2; int padsize = (4 - (size % 4)) % 4; for (int i = 0; i < num; i++) { byte pnum = data.readByte(); byte owner = data.readByte(); byte info = data.readByte(); int armies = data.readByte(); if (armies < 0) armies += 256; int flags = data.readShort(); Planet pl = planets[pnum]; pl.SetData(owner, info, armies, flags); } for (int i = 0; i < padsize; i++) byte pad = data.readByte(); } public void paintLocal(NetrekImageLib lib, Graphics g, ServerState state, Eraser eraser) { for (int i = 0; i < Number(); i++) planets[i].paintLocal(lib, g, state, eraser); } void MarkNet(ServerState state, int x, int y, Planet pl) { int size = state.gwidth/REGIONS; int offset = PDIST / size + 1; int fromx = x / size - offset; if (fromx < 0) fromx = 0; int tox = x / size + offset; if (tox >= REGIONS) tox = REGIONS; int fromy = y / size - offset; if (fromy < 0) fromy = 0; int toy = y / size + offset; if (toy >= REGIONS) toy = REGIONS; for (int i = fromx; i <= tox; i++) for (int j = fromy; j <= toy; j++) redraws[i][j] = pl; } }