Skip to content

Commit

Permalink
Send returning players their saved position on connect, rather than 0,0
Browse files Browse the repository at this point in the history
Refactor out send_sector()
  • Loading branch information
Nebual committed Apr 21, 2019
1 parent bbfd2a5 commit 543a4c8
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 32 deletions.
2 changes: 1 addition & 1 deletion client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions savingsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def save_sector_to_bytes(blocks: custom_types.WorldServer, secpos: iVector) -> b
for y in range(cy, cy+8):
for z in range(cz, cz+8):
blk = blocks.get((x,y,z), air).id
if blk is not air:
if blk != air:
#if isinstance(blk, int): # When does this occur? Its expensive and I don't see it triggering
# blk = BlockID(blk)
fstr += structuchar2.pack(blk.main, blk.sub)
Expand All @@ -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))
Expand Down Expand Up @@ -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)
Expand Down
54 changes: 33 additions & 21 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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():
Expand All @@ -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)
Expand Down
12 changes: 5 additions & 7 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Python packages
import os
import struct
from typing import Tuple, List
from typing import Tuple, List, Union

# Third-party packages
import pyglet
Expand Down Expand Up @@ -140,12 +140,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):
Expand Down

0 comments on commit 543a4c8

Please sign in to comment.