import java.lang.*; import java.io.*; import java.awt.*; // This class is immutable. Do not implement Cloneable class Ship { public final static int SCOUT = 0; public final static int DESTROYER = 1; public final static int CRUISER = 2; public final static int BATTLESHIP = 3; public final static int ASSAULT = 4; public final static int STARBASE = 5; final static int defaults[][] = { { 0, 16, 75, 12, 5000, 2, 75, 75, 1000, 1000, 20, 20 }, { 1, 14, 85, 10, 7000, 5, 85, 85, 1000, 1000, 20, 20 }, { 2, 12, 100, 9, 10000, 10, 100, 100, 1000, 1000, 20, 20 }, { 3, 12, 105, 8, 14000, 6, 130, 130, 1000, 1000, 20, 20 }, { 4, 16, 80, 8, 6000, 20, 80, 200, 1000, 1200, 20, 20 }, { 5, 14, 120, 2, 60000, 25, 500, 600, 1300, 1000, 20, 20 } }; public int s_phaserdamage; public int s_maxspeed; public int s_maxfuel; public int s_maxshield; public int s_maxdamage; public int s_maxegntemp; public int s_maxwpntemp; public int s_maxarmies; public int s_width; public int s_height; public int s_type; public int s_torpspeed; public Ship(int type) { int t = 3; for (int i = 0; i < defaults.length; i++) if (type == defaults[i][0]) { t = i; break; } s_type = type; s_torpspeed = defaults[t][1]; s_phaserdamage = defaults[t][2]; s_maxspeed = defaults[t][3]; s_maxfuel = defaults[t][4]; s_maxarmies = defaults[t][5]; s_maxshield = defaults[t][6]; s_maxdamage = defaults[t][7]; s_maxwpntemp = defaults[t][8]; s_maxegntemp = defaults[t][9]; s_width = defaults[t][10]; s_height = defaults[t][11]; } }; // This class is mutable -- implement Cloneable class PlayerStats implements Cloneable { public double st_maxkills; /* max kills ever */ public int st_kills; /* how many kills */ public int st_losses; /* times killed */ public int st_armsbomb; /* armies bombed */ public int st_planets; /* planets conquered */ public int st_ticks; /* Ticks I've been in game */ public int st_tkills; /* Kills in tournament play */ public int st_tlosses; /* Losses in tournament play */ public int st_tarmsbomb; /* Tournament armies bombed */ public int st_tplanets; /* Tournament planets conquered */ public int st_tticks; /* Tournament ticks */ /* SB stats are entirely separate */ public int st_sbkills; /* Kills as starbase */ public int st_sblosses; /* Losses as starbase */ public int st_sbticks; /* Time as starbase */ public double st_sbmaxkills; /* Max kills as starbase */ public int st_lastlogin; /* Last time this player was played */ public int st_flags; /* Misc option flags */ //char st_keymap[480]; /* keymap for this player */ public byte st_keymap[]; /* keymap for this player */ public int st_rank; /* Ranking of the player */ public PlayerStats() { st_keymap = new byte[96]; } public PlayerStats copy() { try { return (PlayerStats) clone(); } catch(CloneNotSupportedException ex) { return null; } } } class Player implements Cloneable { 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 PFREE = 0; public final static byte POUTFIT = 1; public final static byte PALIVE = 2; public final static byte PEXPLODE = 3; public final static byte PDEAD = 4; public final static int PFSHIELD = 0x0001; public final static int PFREPAIR = 0x0002; public final static int PFBOMB = 0x0004; public final static int PFORBIT = 0x0008; public final static int PFCLOAK = 0x0010; public final static int PFWEP = 0x0020; public final static int PFENG = 0x0040; public final static int PFROBOT = 0x0080; public final static int PFBEAMUP = 0x0100; public final static int PFBEAMDOWN = 0x0200; public final static int PFSELFDEST = 0x0400; public final static int PFGREEN = 0x0800; public final static int PFYELLOW = 0x1000; public final static int PFRED = 0x2000; public final static int PFPLOCK = 0x4000; /* Locked on a player */ public final static int PFPLLOCK = 0x8000; /* Locked on a planet */ public final static int PFCOPILOT = 0x10000;/* Allow copilots */ public final static int PFWAR = 0x20000;/* computer reprogramming for war */ public final static int PFPRACTR = 0x40000;/* practice type robot (no kills) */ public final static int PFDOCK = 0x80000;/* true if docked to a starbase */ public final static int PFREFIT = 0x100000;/* true if about to refit */ public final static int PFREFITTING= 0x200000;/* true if currently refitting */ public final static int PFTRACT = 0x400000;/* tractor beam activated */ public final static int PFPRESS = 0x800000;/* pressor beam activated */ public final static int PFDOCKOK = 0x1000000;/* docking permission */ public final static int PRREDRAW = 0x01; public final static int PRCLEAR = 0x02; public final static int KQUIT = 0x01; /* Player quit */ public final static int KTORP = 0x02; /* killed by torp */ public final static int KPHASER = 0x03; /* killed by phaser */ public final static int KPLANET = 0x04; /* killed by planet */ public final static int KSHIP = 0x05; /* killed by other ship */ public final static int KDAEMON = 0x06; /* killed by dying daemon */ public final static int KWINNER = 0x07; /* killed by a winner */ public final static int KGHOST = 0x08; /* killed because a ghost */ public final static int KGENOCIDE = 0x09; /* killed by genocide */ public final static int KPROVIDENCE= 0x0a; /* killed by a hacker */ public final static int KPLASMA = 0x0b; /* killed by a plasma torpedo */ public final static int TOURNEND = 0x0c; /* tournament game ended */ public final static int KOVER = 0x0d; /* game over */ public final static int TOURNSTART = 0x0e; /* tournament game starting */ public final static int KBINARY = 0x0f; /* bad binary */ public final static int ST_MAPMODE = 1; public final static int ST_NAMEMODE = 2; public final static int ST_SHOWSHIELDS = 4; public final static int ST_KEEPPEACE = 8; public final static int ST_SHOWLOCAL = 16; /* two bits for these two */ public final static int ST_SHOWGLOBAL = 64; public final static String shipnos = "0123456789abcdefghijklmnopqrstuvwxyz"; public final static char teamlet[] = {'I', 'F', 'R', 'X', 'K', 'X', 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'A'}; public final static int CLOAK_PHASES = 7; public final static int VIEWS = 16; public final static int EXPVIEWS = 5; public final static int SBEXPVIEWS = 7; final static String families[] = { "STDFED", "STDROM", "STDKLI", "STDORI" }; final static String classes[] = { "SC", "DD", "CA", "BB", "AS", "SB" }; public int p_no; //public int p_updates; /* Number of updates ship has survived */ public int p_status; /* Player status */ public int p_flags; /* Player flags */ public int p_fredraw; /* Redraw flags */ public String p_name; public String p_login; public String p_monitor; /* Monitor being played on */ public char p_mapchars[]; /* Cache for map window image */ public Ship p_ship; /* Personal ship statistics */ public int p_x; public int p_y; public byte p_dir; /* Real direction */ //public byte p_desdir; /* desired direction */ //public int p_subdir; /* fraction direction change */ public int p_speed; /* Real speed */ //public short p_desspeed; /* Desired speed */ //public int p_subspeed; /* Fractional speed */ public short p_team; /* Team I'm on */ public int p_damage; /* Current damage */ //public int p_subdamage; /* Fractional damage repair */ public int p_shield; /* Current shield power */ //public int p_subshield; /* Fractional shield recharge */ public short p_cloakphase; /* Drawing stage of cloaking * engage/disengage. */ public short p_ntorp; /* Number of torps flying */ public short p_nplasmatorp; /* Number of plasma torps active */ public byte p_hostile; /* Who my torps will hurt */ public byte p_swar; /* Who am I at sticky war with */ public float p_kills; /* Enemies killed */ //public short p_planet; /* Planet orbiting or locked onto */ //public short p_playerl; /* Player locked onto */ public int p_armies; /* XXX: for stats */ public int p_fuel; public short p_explode; /* Keeps track of final explosion */ public int p_etemp; public short p_etime; public int p_wtemp; public short p_wtime; public short p_whydead; /* Tells you why you died */ public short p_whodead; /* Tells you who killed you */ public PlayerStats p_stats; /* player statistics */ //public short p_genoplanets; /* planets taken since last genocide */ //public short p_genoarmsbomb; /* armies bombed since last genocide */ //public short p_planets; /* planets taken this game */ //public short p_armsbomb; /* armies bombed this game */ //public int p_ghostbuster; //public int p_docked; /* If starbase, # docked to, else base // * port */ //public Player p_port[]; /* If starbase, pno of ship docked to that // * port, else p_port[0] = base # docked to on // * host. */ public Player p_tractor; /* What player is in tractor lock */ //public int p_pos; /* My position in the player file */ public boolean p_self; public int redraw_cnt; int s_race; int s_color; int s_type; Image ship_cache[]; Image exp_cache[]; Image cloak_cache; Image shield_cache; Image gcache; Image gcloaked; int g_height; int gcolor; boolean newmapchars; Rectangle erase_area; Point erase_origin; public Player(int num) { p_status = PFREE; p_ship = new Ship(0); p_stats = new PlayerStats(); p_mapchars = new char[2]; p_name = new String(); p_login = new String(); p_monitor = new String(); p_no = num; p_mapchars[1] = shipnos.charAt(num); p_cloakphase = 0; p_ntorp = 0; p_explode = 1; p_stats.st_tticks = 1; p_self = false; p_hostile = (byte) (RACE_FED | RACE_ROM | RACE_KLI | RACE_ORI); p_fredraw = 0; SetClear(); redraw_cnt = 0; ship_cache = null; exp_cache = null; shield_cache = null; gcache = null; gcloaked = null; erase_area = new Rectangle(-10000, -10000, 0, 0); erase_origin = new Point(0, 0); } public Player copy() { Player ret = null; try { ret = (Player) clone(); } catch(CloneNotSupportedException ex) { } ret.p_stats = p_stats.copy(); ret.p_mapchars = new char[2]; ret.p_mapchars[0] = p_mapchars[0]; ret.p_mapchars[1] = p_mapchars[1]; ret.p_name = new String(p_name); ret.p_login = new String(p_login); ret.p_monitor = new String(p_monitor); ret.p_tractor = null; ret.ship_cache = null; ret.exp_cache = null; ret.shield_cache = null; ret.gcache = null; ret.gcloaked = null; ret.erase_area = new Rectangle(-10000, -10000, 0, 0); ret.erase_origin = new Point(0, 0); return ret; } public void SetSelf(boolean self) { p_self = self; } public boolean IsSelf() { return p_self; } public void SetRedraw() { p_fredraw |= PRREDRAW; } public void SetClear() { p_fredraw |= (PRREDRAW|PRCLEAR); } public void SetPos(int x, int y) { if (x != p_x || y != p_y) { SetClear(); redraw_cnt = 10; } p_x = x; p_y = y; } public void SetStatus(byte status) { if (p_status == status) return; if (status == PALIVE) p_kills = (float) 0; if (status == PEXPLODE) p_explode = 0; if (status == PDEAD) status = PEXPLODE; p_status = status; } public void SetLogin(String name, String display, String login, byte rank) { p_name = name; p_monitor = display; p_login = login; p_stats.st_rank = rank; } public void SetFlags(int flags) { if (p_flags == flags) return; p_flags = flags; p_tractor = null; } public void SetTeam(byte team) { if (p_team != team) newmapchars = true; p_team = team; p_mapchars[0] = teamlet[team]; } public byte GetRace() { short team = p_team; for (byte n = 0; team != 0; n++) { if ((team & 1) != 0) return n; team >>= 1; } return 4; //RACE_IND; } public byte GetColorNum() { if (IsSelf()) return 5; //RACE_ME; return GetRace(); } public void SetHostile(byte war, byte hostile) { if (p_swar == war && p_hostile == hostile) return; p_swar = war; p_hostile = hostile; } public void SetKills(int kills) { float r_kills = (float) (kills / 100.0); if (p_kills == r_kills) return; p_kills = r_kills; } public void SetShip(Ship ship) { p_ship = ship; } public int GetAlert() { return (p_flags & (PFRED | PFYELLOW | PFGREEN)); } public void Step() { if (--redraw_cnt < 0) { SetClear(); redraw_cnt = 10; } if (p_status != PALIVE && p_status != PEXPLODE) return; if (p_status == PALIVE) { if ((p_flags & PFCLOAK) != 0) { if (p_cloakphase < (CLOAK_PHASES-1)) p_cloakphase++; } else { if (p_cloakphase > 0) p_cloakphase--; } } else { if (p_ship.s_type != p_ship.STARBASE) { if (p_explode < EXPVIEWS) p_explode++; } else { if (p_explode < SBEXPVIEWS) p_explode++; } } } public void drawTractor(NetrekImageLib lib, Graphics g, ServerState state, Eraser eraser) { if (p_status != PALIVE) return; if ((p_flags & (PFTRACT | PFPRESS)) == 0 || p_tractor == null) return; if ((p_tractor.p_flags & PFCLOAK) != 0 && p_tractor.p_cloakphase == CLOAK_PHASES-1) return; int x = state.RealToRelativeXCoordinate(p_x); int y = state.RealToRelativeYCoordinate(p_y); int race = GetRace(); int color = GetColorNum(); int px = state.RealToRelativeXCoordinate(p_tractor.p_x); int py = state.RealToRelativeYCoordinate(p_tractor.p_y); if (px == x && py == y) return; int w = p_ship.s_width; int h = p_ship.s_height; int dx = px - x; int dy = py - y; double r = Math.sqrt(dx*dx + dy*dy); //double theta = atan2(dx, dy) + Math.PI/2.0; double costheta = -dy/r; double sintheta = dx/r; int ldx = (int) (costheta * w / 2.0); int ldy = (int) (sintheta * w / 2.0); if ((p_flags & PFPRESS) != 0) g.setColor(new Color(110, 100, 0)); else g.setColor(new Color(0, 110, 0)); g.drawLine(x, y, px + ldx, py + ldy); g.drawLine(x, y, px - ldx, py - ldy); } public void FlushCache() { ship_cache = null; exp_cache = null; } int rosette(int dir) { if (dir < 0) dir += 256; return(((dir + 8) / 16) & 0x0F); } synchronized void UpdateCache(NetrekImageLib lib, int race, int color) { if (ship_cache == null || s_race != race || s_color != color || s_type != p_ship.s_type) { s_race = race; s_color = color; s_type = p_ship.s_type; ship_cache = new Image[VIEWS]; for (int i = 0; i < VIEWS; i++) { ship_cache[i] = lib.GetImage(families[race], classes[s_type], color, i); if (ship_cache[i] == null) System.err.println(families[race] + ", " + classes[p_ship.s_type] + ", " + color + ", " + i); } if (s_type == Ship.STARBASE) { exp_cache = new Image[SBEXPVIEWS]; for (int i = 0; i < SBEXPVIEWS; i++) exp_cache[i] = lib.GetImage("STDALL", "SBEXP", color, i); } else { exp_cache = new Image[EXPVIEWS]; for (int i = 0; i < EXPVIEWS; i++) exp_cache[i] = lib.GetImage("STDALL", "EXP", color, i); } cloak_cache = lib.GetImage("STDALL", "CLOAK", color, 0); shield_cache = lib.GetImage("STDALL", "SHIELD", color, 0); } } public void paintLocal(NetrekImageLib lib, Graphics g, ServerState state, Eraser eraser) { Image img; if (p_status != PALIVE && p_status != PEXPLODE) return; int x = state.RealToRelativeXCoordinate(p_x); int y = state.RealToRelativeYCoordinate(p_y); if (!state.IsVisible(x, y)) return; int race = GetRace(); int color = GetColorNum(); UpdateCache(lib, race, color); if (p_status == PALIVE) { if (state.observer && IsSelf()) { img = cloak_cache; if ((p_flags & PFCLOAK) != 0 || p_cloakphase == (CLOAK_PHASES-1)) { if (img != null) g.drawImage(img, x - img.getWidth(null)/2, y - img.getHeight(null)/2, null); int w = p_ship.s_width; int h = p_ship.s_height; g.setColor(lib.GetRaceColor(color)); img = shield_cache; if ((p_flags & PFSHIELD) != 0 && img != null) g.drawOval(x - w/2, y - h/2, w-1, h-1); } return; } if ((p_flags & PFCLOAK) != 0 && p_cloakphase == (CLOAK_PHASES-1)) { if (!IsSelf()) return; } else { int idx = rosette(p_dir); img = ship_cache[idx]; if (img == null) System.err.println("ShipImg is null for rot " + idx + ", player " + p_no + ", race " + families[race] + ", ship " + classes[p_ship.s_type] + ", color " + color + ", pos (" + x + ", " + y + ")"); else g.drawImage(img, x - img.getWidth(null)/2, y - img.getHeight(null)/2, null); } img = cloak_cache; if ((p_flags & PFCLOAK) != 0 || p_cloakphase > 0) if (img != null) g.drawImage(img, x - img.getWidth(null)/2, y - img.getHeight(null)/2, null); int w = p_ship.s_width; int h = p_ship.s_height; g.setColor(lib.GetRaceColor(color)); img = shield_cache; if ((p_flags & PFSHIELD) != 0 && img != null) g.drawOval(x - w/2, y - h/2, w-1, h-1); /* g.drawImage(img, x - img.getWidth(null)/2, y - img.getHeight(null)/2, null); */ //eraser.AddArea(x - w/2, y - h/2, w, h); g.drawChars(p_mapchars, 1, 1, x + w/2, y - h/2); //eraser.AddArea(x + w/2, y - h/2 - 10, 10, 15); } else { if (p_explode >= 0 && p_explode < exp_cache.length) { img = exp_cache[p_explode]; if (img != null) { int w = img.getWidth(null); int h = img.getHeight(null); g.drawImage(img, x - w/2, y - h/2, null); //eraser.AddArea(x - w/2, y - h/2, w, h); } } } } public void PrepareToErase(Eraser eraser, Planets planets, ServerState state) { if ((p_fredraw & PRCLEAR) == 0) return; eraser.AddArea(erase_area.x, erase_area.y, erase_area.width, erase_area.height); planets.RedrawPosition(state, erase_origin.x, erase_origin.y); p_fredraw &= ~PRCLEAR; } void DrawGalacticImage(Graphics g, char[] chars, int x, int y, Color col) { FontMetrics fm = g.getFontMetrics(); int g_tw = fm.charsWidth(chars, 0, 2); g_height = fm.getMaxAscent(); int g_thd = fm.getMaxDescent(); g.clearRect(x - g_tw/2, y - g_height/2, g_tw, g_height); g.setColor(col); g.drawChars(chars, 0, 2, x - g_tw/2, y + g_height/2); erase_area.x = x - g_tw/2; erase_area.y = y - g_height/2; erase_area.width = g_tw; erase_area.height = g_height+g_thd; } /* Image CreateGalacticImage(Graphics g, char[] chars, Color col) { Image ret; FontMetrics fm = g.getFontMetrics(); int g_tw = fm.charsWidth(chars, 0, 2); g_height = fm.getMaxAscent(); int g_thd = fm.getMaxDescent(); ret = createImage(g_tw, g_height + g_thd); Graphics gtmp = ret.getGraphics(); gtmp.setFont(g.getFont()); gtmp.setColor(Color.black); gtmp.fillRect(0, 0, ret.getWidth(null), ret.getHeight(null)); gtmp.setColor(col); gtmp.drawChars(chars, 0, 2, 0, g_height); gtmp.finalize(); return ret; } void UpdateGalacticCache(NetrekImageLib lib, Graphics g) { int newcolor = GetColorNum(); if (gcache == null || newmapchars || newcolor != gcolor) { newmapchars = false; gcolor = newcolor; gcache = CreateGalacticImage(g, p_mapchars, lib.GetRaceColor(gcolor)); } if (gcloaked == null) { char[] cloakchars = { '?', '?' }; gcloaked = CreateGalacticImage(g, cloakchars, lib.GetRaceColor(4)); // RACE_IND } } */ public void paintGalactic(NetrekImageLib lib, Graphics g, ServerState state) { Image img; if ((p_fredraw & PRREDRAW) == 0) return; p_fredraw &= ~PRREDRAW; if (p_status != PALIVE) return; if (state.observer && IsSelf()) return; int x = state.RealToGalacticCoordinate(p_x); int y = state.RealToGalacticCoordinate(p_y); //UpdateGalacticCache(lib, g); char chars[] = { '?', '?' }; int colornum = 4; // RACE_IND if ((p_flags & PFCLOAK) == 0) { chars = p_mapchars; colornum = GetColorNum(); } erase_origin.x = p_x; erase_origin.y = p_y; DrawGalacticImage(g, chars, x, y, lib.GetRaceColor(colornum)); } } class Players implements Cloneable { ServerState state; Player players[]; byte buf[]; public Players(int num, ServerState state) { this.state = state; players = new Player[num]; for (int i = 0; i < num; i++) players[i] = new Player(i); buf = new byte[128]; } public Players copy(ServerState newstate) { Players ret = null; try { ret = (Players) clone(); } catch(CloneNotSupportedException ex) { } ret.state = newstate; ret.players = new Player[players.length]; //ret.buf = new byte[128]; for (int i = 0; i < players.length; i++) { ret.players[i] = players[i].copy(); if (players[i].p_tractor != null) ret.players[i].p_tractor = ret.players[players[i].p_tractor.p_no]; if (ret.players[i].IsSelf()) ret.state.me = ret.players[i]; } return ret; } public int Number() { return players.length; } public Player GetPlayer(int index) { return players[index]; } public Player GetSelf() { return state.me; } public void PrepareToErase(Eraser eraser, Planets planets, ServerState state) { for (int i = 0; i < players.length; i++) players[i].PrepareToErase(eraser, planets, state); } public void GalacticRedraw(NetrekImageLib lib, Graphics g, ServerState state, boolean redraw) { if (redraw) { for (int i = 0; i < players.length; i++) players[i].SetRedraw(); } for (int i = 0; i < players.length; i++) if (!players[i].IsSelf()) players[i].paintGalactic(lib, g, state); state.me.paintGalactic(lib, g, state); } public void DumpStateInit(DataOutput data) throws IOException { for(byte i = 0; i < players.length; i++) if (players[i].IsSelf()) sendYou(data, i); } public void DumpState(DataOutput data) throws IOException { for(byte i = 0; i < players.length; i++) { sendPlayerLogin(data, i); sendHostile(data, i); sendPlayerInfo(data, i); sendKills(data, i); sendPlayerStatus(data, i); sendFlags(data, i); sendPlayer(data, i); if (players[i].IsSelf()) sendYou(data, i); } } int CalcInt(byte data[], int off) { return ((((int) data[off]) << 24) + (((int) data[off+1] & 0xFF) << 16) + (((int) data[off+2] & 0xFF) << 8) + ((int) data[off+3] & 0xFF)); } short CalcShort(byte data[], int off) { return (short) ((((short) data[off]) << 8) + ((short) data[off+1] & (short)0xFF)); } // struct plyr_info_spacket { // char type; /* SP_PLAYER_INFO */ // char pnum; // char shiptype; // char team; // }; public void handlePlayerInfo(DataInput data) throws IOException { byte pnum = data.readByte(); byte shiptype = data.readByte(); byte team = data.readByte(); Player pl = players[pnum]; if (pl.p_ship.s_type != shiptype) pl.SetShip(new Ship(shiptype)); pl.SetTeam(team); } public void sendPlayerInfo(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_PLAYER_INFO); data.writeByte(pnum); data.writeByte((byte)players[pnum].p_ship.s_type); data.writeByte(players[pnum].p_team); } // struct kills_spacket { // char type; /* SP_KILLS */ // char pnum; // char pad1; // char pad2; // unsigned kills; /* where 1234=12.34 kills and 0=0.00 kills */ // }; public void handleKills(DataInput data) throws IOException { data.readFully(buf, 1, 7); byte pnum = buf[1]; int kills = CalcInt(buf, 4); Player pl = players[pnum]; pl.SetKills(kills); } public void sendKills(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_KILLS); data.writeByte(pnum); data.writeByte(0); data.writeByte(0); data.writeInt((int)(players[pnum].p_kills*100.0)); } // struct player_spacket { // char type; /* SP_PLAYER */ // char pnum; // unsigned char dir; // char speed; // LONG x, y; // }; public void handlePlayer(DataInput data) throws IOException { data.readFully(buf, 1, 11); byte pnum = buf[1]; byte dir = buf[2]; byte speed = buf[3]; int x = CalcInt(buf, 4); int y = CalcInt(buf, 8); Player player = players[pnum]; player.p_dir = dir; player.p_speed = speed; player.SetPos(x, y); if (player.p_dir < 0) player.p_dir += 256; } public void sendPlayer(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_PLAYER); data.writeByte(pnum); data.writeByte((byte)players[pnum].p_dir); data.writeByte((byte)players[pnum].p_speed); data.writeInt(players[pnum].p_x); data.writeInt(players[pnum].p_y); } // struct you_spacket { // char type; /* SP_YOU */ // char pnum; /* Guy needs to know this... */ // char hostile; // char swar; // char armies; // char pad1; // char pad2; // char pad3; // unsigned flags; // LONG damage; // LONG shield; // LONG fuel; // short etemp; // short wtemp; // short whydead; // short whodead; // }; void handleYou(DataInput data, ServerState state) throws IOException { byte pnum = data.readByte(); byte hostile = data.readByte(); byte swar = data.readByte(); byte armies = data.readByte(); byte pad1 = data.readByte(); byte pad2 = data.readByte(); byte pad3 = data.readByte(); int flags = data.readInt(); int damage = data.readInt(); int shield = data.readInt(); int fuel = data.readInt(); short etemp = data.readShort(); short wtemp = data.readShort(); short whydead = data.readShort();short whodead = data.readShort(); state.me = players[pnum]; state.me.SetSelf(true); state.me.p_hostile = hostile; state.me.p_swar = swar; state.me.p_armies = armies; state.me.p_flags = flags; state.me.p_damage = damage; state.me.p_shield = shield; state.me.p_fuel = fuel; state.me.p_etemp = etemp; state.me.p_wtemp = wtemp; state.me.p_whydead = whydead; state.me.p_whodead = whodead; } void sendYou(DataOutput data, int pnum) throws IOException { Player me = players[pnum]; data.writeByte(NetrekState.SP_YOU); data.writeByte(pnum); data.writeByte(me.p_hostile); data.writeByte(me.p_swar); data.writeByte(me.p_armies); data.writeByte(0); data.writeByte(0); data.writeByte(0); data.writeInt(me.p_flags); data.writeInt(me.p_damage); data.writeInt(me.p_shield); data.writeInt(me.p_fuel); data.writeShort(me.p_etemp); data.writeShort(me.p_wtemp); data.writeShort(me.p_whydead); data.writeShort(me.p_whodead); } // struct pstatus_spacket { // char type; /* SP_PSTATUS */ // char pnum; // char status; // char pad1; // }; public void handlePlayerStatus(DataInput data) throws IOException { data.readFully(buf, 1, 3); byte pnum = buf[1]; byte status = buf[2]; byte pad1 = buf[3]; Player pl = players[pnum]; pl.SetStatus(status); } public void sendPlayerStatus(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_PSTATUS); data.writeByte(pnum); data.writeByte(players[pnum].p_status); data.writeByte(0); } // struct flags_spacket { // char type; /* SP_FLAGS */ // char pnum; /* whose flags are they? */ // char pad1; // char pad2; // unsigned flags; // }; public void handleFlags(DataInput data) throws IOException { data.readFully(buf, 1, 7); byte pnum = buf[1]; int flags = CalcInt(buf, 4); Player pl = players[pnum]; pl.SetFlags(flags); } public void sendFlags(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_FLAGS); data.writeByte(pnum); data.writeByte(0); data.writeByte(0); data.writeInt(players[pnum].p_flags); } // struct hostile_spacket { // char type; /* SP_HOSTILE */ // char pnum; // char war; // char hostile; // }; public void handleHostile(DataInput data) throws IOException { data.readFully(buf, 1, 3); byte pnum = buf[1]; byte war = buf[2]; byte hostile = buf[3]; Player pl = players[pnum]; pl.SetHostile(war, hostile); } public void sendHostile(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_HOSTILE); data.writeByte(pnum); data.writeByte(players[pnum].p_swar); data.writeByte(players[pnum].p_hostile); } // struct stats_spacket { // char type; /* SP_STATS */ // char pnum; // char pad1; // char pad2; // LONG tkills; /* Tournament kills */ // LONG tlosses; /* Tournament losses */ // LONG kills; /* overall */ // LONG losses; /* overall */ // LONG tticks; /* ticks of tournament play time */ // LONG tplanets; /* Tournament planets */ // LONG tarmies; /* Tournament armies */ // LONG sbkills; /* Starbase kills */ // LONG sblosses; /* Starbase losses */ // LONG armies; /* non-tourn armies */ // LONG planets; /* non-tourn planets */ // LONG maxkills; /* max kills as player * 100 */ // LONG sbmaxkills; /* max kills as sb * 100 */ // }; public void handleStats(DataInput data) throws IOException { data.readFully(buf, 1, 55); byte pnum = buf[1]; byte pad1 = buf[2]; byte pad2 = buf[3]; int tkills = CalcInt(buf, 4); int tlosses = CalcInt(buf, 8); int kills = CalcInt(buf, 12); int losses = CalcInt(buf, 16); int tticks = CalcInt(buf, 20); int tplanets = CalcInt(buf, 24); int tarmies = CalcInt(buf, 28); int sbkills = CalcInt(buf, 32); int sblosses = CalcInt(buf, 36); int armies = CalcInt(buf, 40); int planets = CalcInt(buf, 44); int maxkills = CalcInt(buf, 48); int sbmaxkills = CalcInt(buf, 52); Player pl = players[pnum]; PlayerStats st = pl.p_stats; st.st_tkills = tkills; st.st_tlosses = tlosses; st.st_kills = kills; st.st_losses = losses; st.st_tticks = tticks; st.st_tplanets = tplanets; st.st_tarmsbomb = tarmies; st.st_sbkills = sbkills; st.st_sblosses = sblosses; st.st_armsbomb = armies; st.st_planets = planets; st.st_maxkills = maxkills / 100.0; st.st_sbmaxkills = sbmaxkills / 100.0; } public void sendStats(DataOutput data, byte pnum) throws IOException { data.writeByte(NetrekState.SP_STATS); data.writeByte(pnum); data.writeByte(0); data.writeByte(0); PlayerStats st = players[pnum].p_stats; data.writeInt(st.st_tkills); data.writeInt(st.st_tlosses); data.writeInt(st.st_kills); data.writeInt(st.st_losses); data.writeInt(st.st_tticks); data.writeInt(st.st_tplanets); data.writeInt(st.st_tarmsbomb); data.writeInt(st.st_sbkills); data.writeInt(st.st_sblosses); data.writeInt(st.st_armsbomb); data.writeInt(st.st_planets); data.writeInt((int)(st.st_maxkills*100.0)); data.writeInt((int)(st.st_sbmaxkills*100.0)); } // struct plyr_login_spacket { // char type; /* SP_PL_LOGIN */ // char pnum; // char rank; // char pad1; // char name[16]; // char monitor[16]; // char login[16]; // }; public void handlePlayerLogin(DataInput data) throws IOException { byte pnum = data.readByte(); byte rank = data.readByte(); byte pad1 = data.readByte(); data.readFully(buf, 0, 16); buf[15] = 0; String sname = new String(buf, 0, 0, 16); sname = sname.substring(0, sname.indexOf(0)); data.readFully(buf, 0, 16); buf[15] = 0; String smonitor = new String(buf, 0, 0, 16); smonitor = smonitor.substring(0, smonitor.indexOf(0)); data.readFully(buf, 0, 16); buf[15] = 0; String slogin = new String(buf, 0, 0, 16); slogin = slogin.substring(0, slogin.indexOf(0)); Player pl = players[pnum]; pl.SetLogin(sname, smonitor, slogin, rank); } public void sendPlayerLogin(DataOutput data, byte pnum) throws IOException { Player pl = players[pnum]; data.writeByte(NetrekState.SP_PL_LOGIN); data.writeByte(pnum); data.writeByte(pl.p_stats.st_rank); data.writeByte(0); pl.p_name.getBytes(0, pl.p_name.length(), buf, 0); buf[pl.p_name.length()] = 0; data.write(buf, 0, 16); pl.p_monitor.getBytes(0, pl.p_monitor.length(), buf, 0); buf[pl.p_monitor.length()] = 0; data.write(buf, 0, 16); pl.p_login.getBytes(0, pl.p_login.length(), buf, 0); buf[pl.p_login.length()] = 0; data.write(buf, 0, 16); } // struct youshort_spacket { /* SP_S_YOU */ // char type; // char pnum; // char hostile; // char swar; // char armies; // char whydead; // char whodead; // char pad1; // unsigned flags; // }; public void handleSYou(DataInput data, ServerState state) throws IOException { data.readFully(buf, 1, 11); byte pnum = buf[1]; byte hostile = buf[2]; byte swar = buf[3]; byte armies = buf[4]; byte whydead = buf[5]; byte whodead = buf[6]; byte pad1 = buf[7]; int flags = CalcInt(buf, 8); state.me = players[pnum]; state.me.SetSelf(true); state.me.p_hostile = hostile; state.me.p_swar = swar; state.me.p_armies = armies; state.me.p_flags = flags; state.me.p_whydead = whydead; state.me.p_whodead = whodead; } // struct youss_spacket { /* SP_S_YOU_SS */ // char type; // unsigned char flags8; // unsigned short damage; // unsigned short shield; // unsigned short fuel; // unsigned short etemp; // unsigned short wtemp; // }; public void handleSYouSS(DataInput data, ServerState state) throws IOException { data.readFully(buf, 1, 11); int flags = buf[1]; short damage = CalcShort(buf, 2); short shield = CalcShort(buf, 4); int fuel = CalcShort(buf, 6); short etemp = CalcShort(buf, 8); short wtemp = CalcShort(buf, 10); if (state.me == null) return; if (fuel < 0) fuel += 0x10000; state.me.p_fuel = fuel; state.me.p_damage = damage; state.me.p_shield = shield; state.me.p_etemp = etemp; state.me.p_wtemp = wtemp; if (flags < 0) flags = 256 + flags; state.me.p_flags = (state.me.p_flags & 0xFFFFFF00) | flags; } // struct player_s_spacket { // char type; /* SP_S_PLAYER Header */ // char packets; /* How many player-packets are in this packet // * ( only the first 6 bits are relevant ) */ // unsigned char dir; // char speed; // LONG x, y; /* To get the absolute Position */ // }; /* * The format of the body: struct player_s_body_spacket { Body of new Player * Packet unsigned char pnum; 0-4 = pnum, 5 local or galactic, 6 = 9. * x-bit, 7 9. y-bit unsigned char speeddir; 0-3 = speed , 4-7 direction of * ship unsigned char x; low 8 bits from X-Pixelcoordinate unsigned * char y; low 8 bits from Y-Pixelcoordinate }; */ public void handleSPlayer(DataInput data, ServerState state) throws IOException { byte dir, speed; int x, y; short pad; byte packets = data.readByte(); int player_num = packets & 0x3F; int dsize = player_num * 4; if ((packets & 0x80) != 0) pad = data.readShort(); else if ((packets & 0x40) != 0) pad = data.readShort(); else { byte info[] = buf; data.readFully(info, 0, 10); dir = info[0]; speed = info[1]; x = CalcInt(info, 2); y = CalcInt(info, 6); state.me.p_dir = dir; state.me.p_speed = speed; state.me.SetPos(x, y); } if (dsize == 0) return; byte info[] = buf; data.readFully(info, 0, dsize); for (int i = 0; i < dsize; i += 4) { int pnum = info[i] & 0x1F; if (pnum >= Number()) continue; Player pl = players[pnum]; pl.p_speed = info[i+1] & 0x0F; pl.p_dir = (byte) (info[i+1] & 0xF0); x = info[i+2]; if (x < 0) x += 256; if ((info[i] & 0x40) != 0) x += 256; y = info[i+3]; if (y < 0) y += 256; if ((info[i] & 0x80) != 0) y += 256; int p_x, p_y; if ((info[i] & 0x20) != 0) { // galactic p_x = state.GalacticToRealCoordinate(x); p_y = state.GalacticToRealCoordinate(y); } else { // local p_x = state.RelativeToRealXCoordinate(x); p_y = state.RelativeToRealYCoordinate(y); } pl.SetPos(p_x, p_y); } } public void Step() { for (int i = 0; i < Number(); i++) players[i].Step(); } public void paintLocal(NetrekImageLib lib, Graphics g, ServerState state, Eraser eraser) { state.me.drawTractor(lib, g, state, eraser); for (int i = 0; i < Number(); i++) if (!players[i].IsSelf()) players[i].paintLocal(lib, g, state, eraser); state.me.paintLocal(lib, g, state, eraser); } } // end of players