From b79d7d1968b1ceec6a6ad2b297eed1af9c7caaf1 Mon Sep 17 00:00:00 2001 From: Ben Allison Date: Sat, 20 Apr 2019 05:45:22 -0700 Subject: [PATCH] Send returning players their saved position on connect, rather than 0,0 Refactor out send_sector() --- client.py | 2 +- savingsystem.py | 4 ++-- server.py | 54 ++++++++++++++++++++++++++++++------------------- utils.py | 12 +++++------ 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/client.py b/client.py index ec52cf01..ca642d54 100644 --- a/client.py +++ b/client.py @@ -149,7 +149,7 @@ def dequeue_packet(self): elif packetid == 10: # Update Tile Entity self.world[struct.unpack("iii", packet[:12])].update_tile_entity(packet[12:]) elif packetid == 255: # Spawn Position - self.controller.player.position = struct.unpack("iii", packet[:12]) + self.controller.player.position = struct.unpack("fff", packet[:12]) packet = packet[12:] packet, seed = extract_string_packet(packet) self.world.biome_generator = BiomeGenerator(seed) diff --git a/savingsystem.py b/savingsystem.py index acc046d6..0039cbdc 100644 --- a/savingsystem.py +++ b/savingsystem.py @@ -102,7 +102,7 @@ def save_blocks(blocks: custom_types.WorldServer, world: str): #blocks and sectors (window.world and window.world.sectors) #Saves individual sectors in region files (4x4x4 sectors) - for secpos in blocks.sectors: #TODO: only save dirty sectors + for secpos in blocks.sectors.keys(): #TODO: only save dirty sectors if not blocks.sectors[secpos]: continue #Skip writing empty sectors file = os.path.join(G.game_dir, world, sector_to_filename(secpos)) @@ -182,7 +182,7 @@ def load_region(world: custom_types.WorldServer, world_name: str = "world", regi print("load_region: Invalid Block", e) sectors[(x//SECTOR_SIZE, y//SECTOR_SIZE, z//SECTOR_SIZE)].append(position) -def load_player(player, world: str): +def load_player(player: custom_types.ServerPlayer, world: str): db = connect_db(world) cur = db.cursor() cur.execute("select * from players where name='%s'" % player.username) diff --git a/server.py b/server.py index 7a999a26..d9d23c8c 100644 --- a/server.py +++ b/server.py @@ -9,6 +9,7 @@ import threading import globals as G +from custom_types import fVector, iVector from savingsystem import save_sector_to_bytes, save_blocks, save_world, load_player, save_player from world_server import WorldServer import blocks @@ -18,14 +19,33 @@ #This class is effectively a serverside "Player" object class ServerPlayer(socketserver.BaseRequestHandler): + id: int + position: fVector + momentum: fVector + username: str inventory = b"\0"*(4*40) # Currently, is serialized to be 4 bytes * (27 inv + 9 quickbar + 4 armor) = 160 bytes command_parser = CommandParser() + server: 'Server' operator = False def sendpacket(self, size: int, packet: bytes): self.request.sendall(struct.pack("i", 5 + size) + packet) + def send_sector(self, world: WorldServer, sector: iVector): + if sector not in world.sectors: + with world.server_lock: + world.open_sector(sector) + + if not world.sectors[sector]: + # Empty sector, send packet 2 + self.sendpacket(12, b"\2" + struct.pack("iii", *sector)) + else: + packet = struct.pack("iii", *sector) \ + + save_sector_to_bytes(world, sector) \ + + world.get_exposed_sector(sector) + self.sendpacket(len(packet), b"\1" + packet) + def sendchat(self, txt: str, color=(255,255,255,255)): txt_bytes = txt.encode('utf-8') self.sendpacket(len(txt_bytes) + 4, b"\5" + txt_bytes + struct.pack("BBBB", *color)) @@ -70,17 +90,7 @@ def loop(self): packettype = struct.unpack("B", byte)[0] # Client Packet Type if packettype == 1: # Sector request sector = struct.unpack("iii", self.request.recv(4*3)) - - if sector not in world.sectors: - with world.server_lock: - world.open_sector(sector) - - if not world.sectors[sector]: - #Empty sector, send packet 2 - self.sendpacket(12, b"\2" + struct.pack("iii",*sector)) - else: - msg = struct.pack("iii",*sector) + save_sector_to_bytes(world, sector) + world.get_exposed_sector(sector) - self.sendpacket(len(msg), b"\1" + msg) + self.send_sector(world, sector) elif packettype == 3: # Add block positionbytes = self.request.recv(4*3) blockbytes = self.request.recv(2) @@ -141,15 +151,18 @@ def loop(self): elif packettype == 255: # Initial Login txtlen = struct.unpack("i", self.request.recv(4))[0] self.username = self.request.recv(txtlen).decode('utf-8') - self.position = None load_player(self, "world") for player in self.server.players.values(): player.sendchat("$$y%s has connected." % self.username) print("%s's username is %s" % (self.client_address, self.username)) - position = (0,self.server.world.terraingen.get_height(0,0)+2,0) - if self.position is None: self.position = position # New player, set initial position + if self.position is None: + # New player, set initial position + self.position = (0.0, world.terraingen.get_height(0, 0) + 2.0, 0.0) + elif self.position[1] < 0: + # Somehow fell below the world, reset their height + self.position = (self.position[0], world.terraingen.get_height(0, 0) + 2.0, self.position[2]) # Send list of current players to the newcomer for player in self.server.players.values(): @@ -163,16 +176,15 @@ def loop(self): player.sendpacket(2 + len(name), b'\7' + struct.pack("H", self.id) + name) #Send them the sector under their feet first so they don't fall - sector = sectorize(position) - if sector not in world.sectors: - with world.server_lock: - world.open_sector(sector) - msg = struct.pack("iii",*sector) + save_sector_to_bytes(world, sector) + world.get_exposed_sector(sector) - self.sendpacket(len(msg), b"\1" + msg) + sector = sectorize(self.position) + self.send_sector(world, sector) + if sector[1] > 0: + sector_below = (sector[0], sector[1] - 1, sector[2]) + self.send_sector(world, sector_below) #Send them their spawn position and world seed(for client side biome generator) seed_packet = make_string_packet(G.SEED) - self.sendpacket(12 + len(seed_packet), struct.pack("B",255) + struct.pack("iii", *position) + seed_packet) + self.sendpacket(12 + len(seed_packet), struct.pack("B",255) + struct.pack("fff", *self.position) + seed_packet) self.sendpacket(4*40, b"\6" + self.inventory) else: print("Received unknown packettype", packettype) diff --git a/utils.py b/utils.py index 0bd59196..ecfa3756 100644 --- a/utils.py +++ b/utils.py @@ -3,7 +3,7 @@ # Python packages import os import struct -from typing import Tuple, List +from typing import Tuple, List, Union from ctypes import byref # Third-party packages @@ -204,12 +204,10 @@ def normalize(position: fVector) -> fVector: return normalize_float(x), normalize_float(y), normalize_float(z) -def sectorize(position: iVector) -> iVector: - x, y, z = normalize(position) - x, y, z = (x // G.SECTOR_SIZE, - y // G.SECTOR_SIZE, - z // G.SECTOR_SIZE) - return x, y, z +def sectorize(position: Union[iVector, fVector]) -> iVector: + return (normalize_float(float(position[0])) // G.SECTOR_SIZE, + normalize_float(float(position[1])) // G.SECTOR_SIZE, + normalize_float(float(position[2])) // G.SECTOR_SIZE) class TextureGroup(pyglet.graphics.Group):