def handle(client, room, message): player = client.get_player(message['aiclientnum']) shot_id = message['shot_id'] gun = message['gun'] from_pos = vec(*dictget(message, 'fx', 'fy', 'fz')) to_pos = vec(*dictget(message, 'tx', 'ty', 'tz')) hits = message['hits'] room.handle_player_event('shoot', player, shot_id, gun, from_pos, to_pos, hits)
def on_shoot(self, client: Client, room: Room, message: Dict[str, int]) -> None: player = client.get_player(message['aiclientnum']) shot_id = message['shot_id'] gun = message['gun'] from_pos = vec(*dictget(message, 'fx', 'fy', 'fz')) # type: ignore to_pos = vec(*dictget(message, 'tx', 'ty', 'tz')) # type: ignore hits = message['hits'] room.handle_player_event('shoot', player, shot_id, gun, from_pos, to_pos, hits)
def __init__(self, sel_ox, sel_oy, sel_oz, sel_sx, sel_sy, sel_sz, sel_grid, sel_orient, sel_cx, sel_cxs, sel_cy, sel_cys, sel_corner): self.origin = vec(sel_ox, sel_oy, sel_oz) self.source = vec(sel_sx, sel_sy, sel_sz) self.grid_size = sel_grid self.orientation = sel_orient self.cx = sel_cx self.cxs = sel_cxs self.cy = sel_cy self.cys = sel_cys self.corner = sel_corner
def __init__(self): self.physstate = 0 self.lifesequence = 0 self.move = 0 self.yaw = 0 self.roll = 0 self.pitch = 0 self.strafe = 0 self.o = vec(0, 0, 0) self.falling = vec(0, 0, 0) self.eyeheight = 14 self.vel = vec(0, 0, 0)
def _on_player_damaged(self, target, player, damage, gun, dx, dy, dz): v = vec(dx, dy, dz).div(DMF).rescale(DNF) target.state.receive_damage(damage) with self.room.broadcastbuffer(1, True) as cds: swh.put_damage(cds, target, player, damage) if target == player: pass elif not v.iszero(): if target.state.health <= 0: swh.put_hitpush(cds, target, gun, damage, v) else: with target.sendbuffer(1, True) as cds: swh.put_hitpush(cds, target, gun, damage, v) if target.state.health < 1: target.state.state = client_states.CS_DEAD target.state.deaths += 1 if player == target: player.state.suicides += 1 swh.put_died(cds, target, target) self.on_player_death(target, player)
def __init__(self) -> None: self.game_clock: Optional[GameClock] = None self.messages = CubeDataStream() self.state: int = -1 self.lifesequence = 0 self.frags = 0 self.deaths = 0 self.suicides = 0 self.teamkills = 0 self.damage_dealt = 0 self.damage_spent = 0 self.flags = 0 self.flag_returns = 0 self.health = 100 self.maxhealth = 100 self.armour = 0 self.armourtype = armor_types.A_BLUE self.gunselect = weapon_types.GUN_PISTOL self.ammo = [0] * weapon_types.NUMGUNS self.death_timer = None self.pos = vec(0, 0, 0) self._quadexpiry: Optional[Expiry] = None self.shotwait: Optional[Expiry] = None self.spawnwait: Optional[Expiry] = None self._pending_spawn = False self.rockets: Dict = {} self.grenades: Dict = {} self.position = b'' self.reset()
def on_player_damaged(self, target, player, damage, gun, dx, dy, dz): v = vec(dx, dy, dz).div(DMF).rescale(DNF) target.state.receive_damage(damage) with self.room.broadcastbuffer(1, True) as cds: swh.put_damage(cds, target, player, damage) if target == player: pass elif not v.iszero(): if target.state.health <= 0: swh.put_hitpush(cds, target, gun, damage, v) else: with target.sendbuffer(1, True) as cds: swh.put_hitpush(cds, target, gun, damage, v) if target.state.health < 1: target.state.state = client_states.CS_DEAD target.state.deaths += 1 if player == target: player.state.suicides += 1 if self.hasteams and player.team == target.team: player.state.teamkills += 1 if player == target or self.hasteams and player.team == target.team: mod = -1 else: mod = 1 player.state.frags += mod if self.hasteams: player.team.frags += mod swh.put_died(cds, target, player) self.on_player_death(target, player)
def load_vslot(f, index, changed): vs = VSlot(index) numparams = readushort(f) for i in xrange(numparams): nlen = readushort(f) name = f.read(nlen) p = ShaderParam(name, shader_param_types.SHPARAM_LOOKUP) p.val = struct.unpack("4i", f.read(12)) vs.params.append(p) if changed & (1<<vslot_types.VSLOT_SCALE): vs.scale = readfloat(f) if changed & (1<<vslot_types.VLOT_ROTATION): vs.rotation = readint(f) if changed & (1<<vslot_types.VSLOT_OFFSET): vs.xoffset = readint(f) vs.yoffset = readint(f) if changed & (1<<vslot_types.VSLOT_SCROLL): vs.scrollS = readfloat(f) vs.scrollT = readfloat(f) if changed & (1<<vslot_types.VSLOT_LAYER): vs.layer = readint(f) if changed & (1<<vslot_types.VSLOT_ALPHA): vs.alphafront = readfloat(f) vs.alphaback = readfloat(f) if changed & (1<<vslot_types.VSLOT_COLOR): vs.colorscale = vec(*struct.unpack("3f", f.read(12))) return vs
def toplane(self, *args): if len(args) == 2: n, p = args self.x = n.x self.y = n.y self.z = n.z self.offset = -self.dot(p) elif len(args) == 3: a, b, c = args self.cross(vec(b).sub(a), vec(c).sub(a)) mag = self.magnitude() if mag == 0.0: return False self.div(mag) self.offset = -self.dot(a) return True
def load_vslot(f, index, changed): vs = VSlot(index) numparams = readushort(f) for i in range(numparams): nlen = readushort(f) name = f.read(nlen) p = ShaderParam(name, shader_param_types.SHPARAM_LOOKUP) p.val = struct.unpack("4i", f.read(12)) vs.params.append(p) if changed & (1 << vslot_types.VSLOT_SCALE): vs.scale = readfloat(f) if changed & (1 << vslot_types.VLOT_ROTATION): vs.rotation = readint(f) if changed & (1 << vslot_types.VSLOT_OFFSET): vs.xoffset = readint(f) vs.yoffset = readint(f) if changed & (1 << vslot_types.VSLOT_SCROLL): vs.scrollS = readfloat(f) vs.scrollT = readfloat(f) if changed & (1 << vslot_types.VSLOT_LAYER): vs.layer = readint(f) if changed & (1 << vslot_types.VSLOT_ALPHA): vs.alphafront = readfloat(f) vs.alphaback = readfloat(f) if changed & (1 << vslot_types.VSLOT_COLOR): vs.colorscale = vec(*struct.unpack("3f", f.read(12))) return vs
def _load_flag_list(self, flag_list): fid = 0 self.flags = [] for flag_dict in flag_list: team = self.teams[flag_dict['team']-1] spawn_loc = vec(flag_dict['x'], flag_dict['y'], flag_dict['z']) flag = Flag(game_clock=self.room._game_clock, fid=fid, spawn_loc=spawn_loc, team=team) fid += 1 self.flags.append(flag)
def _load_flag_list(self, flag_list): fid = 0 self.flags = [] for flag_dict in flag_list: team = list(self.teams.values())[flag_dict['team']-1] spawn_loc = vec(flag_dict['x'], flag_dict['y'], flag_dict['z']) flag = Flag(game_clock=self.room._game_clock, fid=fid, spawn_loc=spawn_loc, team=team) fid += 1 self.flags.append(flag)
def __init__(self, index): self.next = None self.index = index self.changed = 0 self.skipped = 0 self.params = [] self.linked = False self.scale = 1; self.rotation = 0 self.xoffset = 0 self.yoffset = 0 self.scrollS = 0 self.scrollT = 0 self.layer = 0 self.alphafront = 0.5 self.alphaback = 0 self.colorscale = vec(1, 1, 1) self.glowcolor = vec(1, 1, 1) self.pulseglowcolor = vec(0, 0, 0) self.pulseglowspeed = 0 self.envscale = vec(0, 0, 0)
def __init__(self, index): self.next = None self.index = index self.changed = 0 self.skipped = 0 self.params = [] self.linked = False self.scale = 1 self.rotation = 0 self.xoffset = 0 self.yoffset = 0 self.scrollS = 0 self.scrollT = 0 self.layer = 0 self.alphafront = 0.5 self.alphaback = 0 self.colorscale = vec(1, 1, 1) self.glowcolor = vec(1, 1, 1) self.pulseglowcolor = vec(0, 0, 0) self.pulseglowspeed = 0 self.envscale = vec(0, 0, 0)
def threeplaneintersect(pl1, pl2, pl3, dest): t1, t2, t3, t4 = dest, vec(), vec(), vec() t1.cross(pl1, pl2) t4 = t1 t1.mul(pl3.offset) t2.cross(pl3, pl1) t2.mul(pl2.offset) t3.cross(pl2, pl3) t3.mul(pl1.offset) t1.add(t2); t1.add(t3); t1.mul(-1); d = t4.dot(pl3) if d==0: return False t1.div(d) return True
def edgespan2vectorcube(self): if self.isentirelysolid() or self.isempty(): return for x in xrange(2): for y in xrange(2): for z in xrange(2): p = ivec(8 * x, 8 * y, 8 * z) v = vec(0, 0, 0) o = self.copy() genedgespanvert(p, o, v) self.setcubeedge(0, y, z, edgeval(self.getcubeedge(0, y, z), x, int(v.x + 0.49))) self.setcubeedge(1, z, x, edgeval(self.getcubeedge(1, z, x), y, int(v.y + 0.49))) self.setcubeedge(2, x, y, edgeval(self.getcubeedge(2, x, y), z, int(v.z + 0.49)))
def edgespan2vectorcube(self): if self.isentirelysolid() or self.isempty(): return for x in range(2): for y in range(2): for z in range(2): p = ivec(8 * x, 8 * y, 8 * z) v = vec(0, 0, 0) o = self.copy() genedgespanvert(p, o, v) self.setcubeedge(0, y, z, edgeval(self.getcubeedge(0, y, z), x, int(v.x + 0.49))) self.setcubeedge(1, z, x, edgeval(self.getcubeedge(1, z, x), y, int(v.y + 0.49))) self.setcubeedge(2, x, y, edgeval(self.getcubeedge(2, x, y), z, int(v.z + 0.49)))
def vecfromyawpitch(yaw, pitch, move, strafe): m = vec(0, 0, 0) if move: m.x = move * -math.sin(RAD * yaw) m.y = move * math.cos(RAD * yaw) else: m.x = m.y = 0 if pitch: m.x *= math.cos(RAD * pitch) m.y *= math.cos(RAD * pitch) m.z = move * math.sin(RAD * pitch) else: m.z = 0 if strafe: m.x += strafe * math.cos(RAD * yaw) m.y += strafe * math.sin(RAD * yaw) return m
def map_change_reset(self): if self.state != client_states.CS_SPECTATOR: self.state = client_states.CS_DEAD self.frags = 0 self.deaths = 0 self.suicides = 0 self.teamkills = 0 self.damage_dealt = 0 self.damage_spent = 0 self.flags = 0 self.flag_returns = 0 self.health = 100 self.maxhealth = 100 self.armour = 0 self.armourtype = armor_types.A_BLUE self.gunselect = weapon_types.GUN_PISTOL self.ammo = [0] * weapon_types.NUMGUNS if self.game_clock is not None: self.playing_timer = Timer(self.game_clock) else: self.playing_timer = None self.death_timer = None self.pos = vec(0, 0, 0) self._quadexpiry = None self.shotwait = None self.spawnwait = None self._pending_spawn = False self.rockets = {} self.grenades = {} self.messages.clear() self.position = None
def read_physics_state(cds): d = PhysicsState() physstate = cds.getbyte() flags = cds.getuint() for k in range(3): n = cds.getbyte() n |= cds.getbyte() << 8 if flags & (1 << k): n |= cds.getbyte() << 16 if n & 0x800000: n |= -1 << 24 d.o[k] = n dir = cds.getbyte() dir |= cds.getbyte() << 8 yaw = dir % 360 pitch = clamp(dir / 360, 0, 180) - 90 roll = clamp(int(cds.getbyte()), 0, 180) - 90 mag = cds.getbyte() if flags & (1 << 3): mag |= cds.getbyte() << 8 dir = cds.getbyte() dir |= cds.getbyte() << 8 d.vel = vecfromyawpitch(dir % 360, clamp(dir / 360, 0, 180) - 90, 1, 0) if flags & (1 << 4): mag = cds.getbyte() if flags & (1 << 5): mag |= cds.getbyte() << 8 if flags & (1 << 6): dir = cds.getbyte() dir |= cds.getbyte() << 8 falling = vecfromyawpitch(dir % 360, clamp(dir / 360, 0, 180) - 90, 1, 0) else: falling = vec(0, 0, -1) else: falling = vec(0, 0, 0) d.falling = falling seqcolor = (physstate >> 3) & 1 d.yaw = yaw d.pitch = pitch d.roll = roll if (physstate >> 4) & 2: d.move = -1 else: d.move = (physstate >> 4) & 1 if (physstate >> 6) & 2: d.strafe = -1 else: d.strafe = (physstate >> 6) & 1 d.physstate = physstate & 7 return d
def read_map_data(map_filename): meta_data = {'vars': {}, 'ents': []} with gzip.open(map_filename) as f: magic, version, headersize, worldsize, numents, numpvs, lightmaps = struct.unpack("4s6i", f.read(28)) meta_data['version'] = version meta_data['headersize'] = headersize meta_data['worldsize'] = worldsize meta_data['numents'] = numents meta_data['numpvs'] = numpvs meta_data['lightmaps'] = lightmaps if version <= 28: lightprecision, lighterror, lightlod = struct.unpack("3i", f.read(12)) ambient = struct.unpack("B", f.read(1)) watercolor = struct.unpack("3B", f.read(3)) blendmap = struct.unpack("B", f.read(1)) lerpangle = struct.unpack("B", f.read(1)) lerpsubdiv = struct.unpack("B", f.read(1)) lerpsubdivsize = struct.unpack("B", f.read(1)) bumperror = struct.unpack("B", f.read(1)) skylight = struct.unpack("3B", f.read(3)) lavacolor = struct.unpack("3B", f.read(3)) waterfallcolor = struct.unpack("3B", f.read(3)) reserved = struct.unpack("10B", f.read(10)) maptitle = struct.unpack("128s", f.read(128)) meta_data['vars']['maptitle'] = maptitle else: if version <= 29: blendmap, numvars = struct.unpack("2i", f.read(8)) else: blendmap, numvars, numvslots = struct.unpack("3i", f.read(12)) if version <= 28: numvars = 0 if version <= 29: numvslots = 0 meta_data['blendmap'] = blendmap meta_data['numvars'] = numvars meta_data['numvslots'] = numvslots for i in xrange(numvars): var_type = struct.unpack("b", f.read(1))[0] ilen = struct.unpack("<H", f.read(2))[0] var_name = f.read(ilen) if var_type == cs_id_types.ID_VAR: var_value = struct.unpack("i", f.read(4))[0] elif var_type == cs_id_types.ID_FVAR: var_value = struct.unpack("f", f.read(4))[0] elif var_type == cs_id_types.ID_SVAR: slen = struct.unpack("H", f.read(2))[0] var_value = f.read(slen) #print "{:.8}: {:.32s} = {}".format(cs_id_types.by_value(var_type), var_name, var_value) meta_data['vars'][var_name] = var_value if version >= 16: gt_len = struct.unpack("b", f.read(1))[0] game_type = f.read(gt_len+1) else: game_type = 'fps' meta_data['gametype'] = game_type if version >= 16: eif = struct.unpack("H", f.read(2))[0] extra_size = struct.unpack("H", f.read(2))[0] edata = f.read(extra_size) print eif, extra_size, edata if version < 14: f.read(256) else: nummru = struct.unpack("H", f.read(2))[0] f.read(nummru*2) for i in range(min(numents, MAXENTS)): x, y, z = struct.unpack("3f", f.read(12)) attrs = struct.unpack('5h', f.read(10)) ent_type, reserved = struct.unpack('2B', f.read(2)) ent = {'id': i, 'type': ent_type, 'x': x, 'y': y, 'z': z, 'attrs': attrs, 'reserved': reserved} meta_data['ents'].append(ent) vslots = load_vslots(f, numvslots) worldroot = loadchildren(version, f, vec(0, 0, 0), worldsize>>1) try: with gzip.open(map_filename) as f: meta_data['crc'] = zlib.crc32(f.read()) & 0xffffffff except IOError: meta_data['crc'] = 0 cube_map = CubeMap() cube_map.vslots = vslots cube_map.octants = worldroot cube_map.meta_data = meta_data return cube_map
def copy(self): return vec(self.x, self.y, self.z)
def read_map_data(map_filename): meta_data = {'vars': {}, 'ents': []} with gzip.open(map_filename) as f: magic, version, headersize, worldsize, numents, numpvs, lightmaps = struct.unpack( "4s6i", f.read(28)) meta_data['version'] = version meta_data['headersize'] = headersize meta_data['worldsize'] = worldsize meta_data['numents'] = numents meta_data['numpvs'] = numpvs meta_data['lightmaps'] = lightmaps if version <= 28: lightprecision, lighterror, lightlod = struct.unpack( "3i", f.read(12)) ambient = struct.unpack("B", f.read(1)) watercolor = struct.unpack("3B", f.read(3)) blendmap = struct.unpack("B", f.read(1)) lerpangle = struct.unpack("B", f.read(1)) lerpsubdiv = struct.unpack("B", f.read(1)) lerpsubdivsize = struct.unpack("B", f.read(1)) bumperror = struct.unpack("B", f.read(1)) skylight = struct.unpack("3B", f.read(3)) lavacolor = struct.unpack("3B", f.read(3)) waterfallcolor = struct.unpack("3B", f.read(3)) reserved = struct.unpack("10B", f.read(10)) maptitle = struct.unpack("128s", f.read(128)) meta_data['vars']['maptitle'] = maptitle else: if version <= 29: blendmap, numvars = struct.unpack("2i", f.read(8)) else: blendmap, numvars, numvslots = struct.unpack("3i", f.read(12)) if version <= 28: numvars = 0 if version <= 29: numvslots = 0 meta_data['blendmap'] = blendmap meta_data['numvars'] = numvars meta_data['numvslots'] = numvslots for i in range(numvars): var_type = struct.unpack("b", f.read(1))[0] ilen = struct.unpack("<H", f.read(2))[0] var_name = f.read(ilen) if var_type == cs_id_types.ID_VAR: var_value = struct.unpack("i", f.read(4))[0] elif var_type == cs_id_types.ID_FVAR: var_value = struct.unpack("f", f.read(4))[0] elif var_type == cs_id_types.ID_SVAR: slen = struct.unpack("H", f.read(2))[0] var_value = f.read(slen) #print "{:.8}: {:.32s} = {}".format(cs_id_types.by_value(var_type), var_name, var_value) meta_data['vars'][var_name] = var_value if version >= 16: gt_len = struct.unpack("b", f.read(1))[0] game_type = f.read(gt_len + 1) else: game_type = 'fps' meta_data['gametype'] = game_type if version >= 16: eif = struct.unpack("H", f.read(2))[0] extra_size = struct.unpack("H", f.read(2))[0] edata = f.read(extra_size) print(eif, extra_size, edata) if version < 14: f.read(256) else: nummru = struct.unpack("H", f.read(2))[0] f.read(nummru * 2) for i in range(min(numents, MAXENTS)): x, y, z = struct.unpack("3f", f.read(12)) attrs = struct.unpack('5h', f.read(10)) ent_type, reserved = struct.unpack('2B', f.read(2)) ent = { 'id': i, 'type': ent_type, 'x': x, 'y': y, 'z': z, 'attrs': attrs, 'reserved': reserved } meta_data['ents'].append(ent) vslots = load_vslots(f, numvslots) worldroot = loadchildren(version, f, vec(0, 0, 0), worldsize >> 1) try: with gzip.open(map_filename) as f: meta_data['crc'] = zlib.crc32(f.read()) & 0xffffffff except IOError: meta_data['crc'] = 0 cube_map = CubeMap() cube_map.vslots = vslots cube_map.octants = worldroot cube_map.meta_data = meta_data return cube_map
def read_physics_state(cds): d = PhysicsState() physstate = cds.getbyte() flags = cds.getuint() for k in range(3): n = cds.getbyte() n |= cds.getbyte() << 8 if flags & (1 << k): n |= cds.getbyte() << 16 if n & 0x800000: n |= -1 << 24 d.o[k] = n dir = cds.getbyte() dir |= cds.getbyte() << 8 yaw = dir % 360 pitch = clamp(dir / 360, 0, 180) - 90 roll = clamp(int(cds.getbyte()), 0, 180) - 90 mag = cds.getbyte() if flags & (1 << 3): mag |= cds.getbyte() << 8 dir = cds.getbyte() dir |= cds.getbyte() << 8 d.vel = vecfromyawpitch(dir % 360, clamp(dir / 360, 0, 180) - 90, 1, 0); if flags & (1 << 4): mag = cds.getbyte() if flags & (1 << 5): mag |= cds.getbyte() << 8 if flags & (1 << 6): dir = cds.getbyte() dir |= cds.getbyte() << 8 falling = vecfromyawpitch(dir % 360, clamp(dir / 360, 0, 180) - 90, 1, 0) else: falling = vec(0, 0, -1) else: falling = vec(0, 0, 0) d.falling = falling seqcolor = (physstate >> 3) & 1 d.yaw = yaw d.pitch = pitch d.roll = roll if (physstate >> 4) & 2: d.move = -1 else: d.move = (physstate >> 4) & 1 if (physstate >> 6) & 2: d.strafe = -1 else: d.strafe = (physstate >> 6) & 1 d.physstate = physstate & 7 return d
def feetpos(self): return vec(0, 0, -self.eyeheight).add(self.o)
def write_physics_state(cds, physics_state): d = physics_state # TODO: replace this with an actual lookup for which material is at a particular position lookupmaterial = dummy_air_material_lookup # 3 bits phys state, 1 bit life sequence, 2 bits move, 2 bits strafe physstate = d.physstate | ((d.lifesequence & 1) << 3) | ((d.move & 3) << 4) | ((d.strafe & 3) << 6) cds.putbyte(physstate) o = ivec(vec(d.o.x, d.o.y, d.o.z - d.eyeheight)) vel = min(int(d.vel.magnitude() * DVELF), 0xFFFF) fall = min(int(d.falling.magnitude() * DVELF), 0xFFFF) # 3 bits position, 1 bit velocity, 3 bits falling, 1 bit material flags = 0; if (o.x < 0 or o.x > 0xFFFF): flags |= 1 << 0 if (o.y < 0 or o.y > 0xFFFF): flags |= 1 << 1 if (o.z < 0 or o.z > 0xFFFF): flags |= 1 << 2 if (vel > 0xFF): flags |= 1 << 3 if fall > 0: flags |= 1 << 4 if fall > 0xFF: flags |= 1 << 5 if d.falling.x or d.falling.y or d.falling.z > 0: flags |= 1 << 6 if lookupmaterial(d.feetpos()) & material_types.MATF_CLIP == empty_material_types.MAT_GAMECLIP: flags |= 1 << 7 cds.putuint(flags) for k in range(3): cds.putbyte(o[k] & 0xFF) cds.putbyte((o[k] >> 8) & 0xFF) if o[k] < 0 or o[k] > 0xFFFF: cds.putbyte((o[k] >> 16) & 0xFF) if d.yaw < 0: dir = 360 + int(d.yaw) % 360 else: dir = int(d.yaw) % 360 dir += clamp(int(d.pitch + 90), 0, 180) * 360 cds.putbyte(dir & 0xFF) cds.putbyte((dir >> 8) & 0xFF) cds.putbyte(clamp(int(d.roll + 90), 0, 180)) cds.putbyte(vel & 0xFF) if vel > 0xFF: cds.putbyte((vel >> 8) & 0xFF) velyaw, velpitch = vectoyawpitch(d.vel) if velyaw < 0: veldir = 360 + int(velyaw) % 360 else: veldir = int(velyaw) % 360 veldir += clamp(int(velpitch + 90), 0, 180) * 360 cds.putbyte(veldir & 0xFF) cds.putbyte((veldir >> 8) & 0xFF) if fall > 0: cds.putbyte(fall & 0xFF) if fall > 0xFF: cds.putbyte((fall >> 8) & 0xFF) if d.falling.x or d.falling.y or d.falling.z > 0: fallyaw, fallpitch = vectoyawpitch(d.falling) if fallyaw < 0: falldir = 360 + int(fallyaw) % 360 else: falldir = int(fallyaw) % 360 falldir += clamp(int(fallpitch + 90), 0, 180) * 360 cds.putbyte(falldir & 0xFF) cds.putbyte((falldir >> 8) & 0xFF)
def write_physics_state(cds, physics_state): d = physics_state # TODO: replace this with an actual lookup for which material is at a particular position lookupmaterial = dummy_air_material_lookup # 3 bits phys state, 1 bit life sequence, 2 bits move, 2 bits strafe physstate = d.physstate | ((d.lifesequence & 1) << 3) | ((d.move & 3) << 4) | ((d.strafe & 3) << 6) cds.putbyte(physstate) o = ivec(vec(d.o.x, d.o.y, d.o.z - d.eyeheight)) vel = min(int(d.vel.magnitude() * DVELF), 0xFFFF) fall = min(int(d.falling.magnitude() * DVELF), 0xFFFF) # 3 bits position, 1 bit velocity, 3 bits falling, 1 bit material flags = 0; if (o.x < 0 or o.x > 0xFFFF): flags |= 1 << 0 if (o.y < 0 or o.y > 0xFFFF): flags |= 1 << 1 if (o.z < 0 or o.z > 0xFFFF): flags |= 1 << 2 if (vel > 0xFF): flags |= 1 << 3 if fall > 0: flags |= 1 << 4 if fall > 0xFF: flags |= 1 << 5 if d.falling.x or d.falling.y or d.falling.z > 0: flags |= 1 << 6 if lookupmaterial(d.feetpos()) & material_types.MATF_CLIP == empty_material_types.MAT_GAMECLIP: flags |= 1 << 7 cds.putuint(flags) for k in xrange(3): cds.putbyte(o[k] & 0xFF) cds.putbyte((o[k] >> 8) & 0xFF) if o[k] < 0 or o[k] > 0xFFFF: cds.putbyte((o[k] >> 16) & 0xFF) if d.yaw < 0: dir = 360 + int(d.yaw) % 360 else: dir = int(d.yaw) % 360 dir += clamp(int(d.pitch + 90), 0, 180) * 360 cds.putbyte(dir & 0xFF) cds.putbyte((dir >> 8) & 0xFF) cds.putbyte(clamp(int(d.roll + 90), 0, 180)) cds.putbyte(vel & 0xFF) if vel > 0xFF: cds.putbyte((vel >> 8) & 0xFF) velyaw, velpitch = vectoyawpitch(d.vel) if velyaw < 0: veldir = 360 + int(velyaw) % 360 else: veldir = int(velyaw) % 360 veldir += clamp(int(velpitch + 90), 0, 180) * 360 cds.putbyte(veldir & 0xFF) cds.putbyte((veldir >> 8) & 0xFF) if fall > 0: cds.putbyte(fall & 0xFF) if fall > 0xFF: cds.putbyte((fall >> 8) & 0xFF) if d.falling.x or d.falling.y or d.falling.z > 0: fallyaw, fallpitch = vectoyawpitch(d.falling) if fallyaw < 0: falldir = 360 + int(fallyaw) % 360 else: falldir = int(fallyaw) % 360 falldir += clamp(int(fallpitch + 90), 0, 180) * 360 cds.putbyte(falldir & 0xFF) cds.putbyte((falldir >> 8) & 0xFF)