Skip to content

Commit c250c78

Browse files
committed
Send returning players their saved position on connect, rather than 0,0
Refactor out send_sector()
1 parent 3312186 commit c250c78

File tree

4 files changed

+46
-31
lines changed

4 files changed

+46
-31
lines changed

client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def dequeue_packet(self):
149149
elif packetid == 10: # Update Tile Entity
150150
self.world[struct.unpack("iii", packet[:12])].update_tile_entity(packet[12:])
151151
elif packetid == 255: # Spawn Position
152-
self.controller.player.position = struct.unpack("iii", packet[:12])
152+
self.controller.player.position = struct.unpack("fff", packet[:12])
153153
packet = packet[12:]
154154
packet, seed = extract_string_packet(packet)
155155
self.world.biome_generator = BiomeGenerator(seed)

savingsystem.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def save_sector_to_bytes(blocks, secpos: iVector) -> bytes:
8383
for y in range(cy, cy+8):
8484
for z in range(cz, cz+8):
8585
blk = blocks.get((x,y,z), air).id
86-
if blk is not air:
86+
if blk != air:
8787
#if isinstance(blk, int): # When does this occur? Its expensive and I don't see it triggering
8888
# blk = BlockID(blk)
8989
fstr += structuchar2.pack(blk.main, blk.sub)
@@ -109,7 +109,7 @@ def save_blocks(blocks, world: str):
109109
#blocks and sectors (window.world and window.world.sectors)
110110
#Saves individual sectors in region files (4x4x4 sectors)
111111

112-
for secpos in blocks.sectors: #TODO: only save dirty sectors
112+
for secpos in blocks.sectors.keys(): #TODO: only save dirty sectors
113113
if not blocks.sectors[secpos]:
114114
continue #Skip writing empty sectors
115115
file = os.path.join(G.game_dir, world, sector_to_filename(secpos))
@@ -194,6 +194,9 @@ def load_region(world, world_name: str = "world", region: Optional[iVector] = No
194194
sectors[(x//SECTOR_SIZE, y//SECTOR_SIZE, z//SECTOR_SIZE)].append(position)
195195

196196
def load_player(player, world: str):
197+
"""
198+
:type player: server.ServerPlayer
199+
"""
197200
db = connect_db(world)
198201
cur = db.cursor()
199202
cur.execute("select * from players where name='%s'" % player.username)

server.py

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
import socket
55
import struct
66
import time
7+
from typing import Any, Tuple, Union
8+
79
import timer
810
import socketserver
911
import threading
1012

1113
import globals as G
14+
from custom_types import fVector, iVector
1215
from savingsystem import save_sector_to_bytes, save_blocks, save_world, load_player, save_player
1316
from world_server import WorldServer
1417
import blocks
@@ -18,14 +21,33 @@
1821

1922
#This class is effectively a serverside "Player" object
2023
class ServerPlayer(socketserver.BaseRequestHandler):
24+
id: int
25+
position: fVector
26+
momentum: fVector
27+
username: str
2128
inventory = b"\0"*(4*40) # Currently, is serialized to be 4 bytes * (27 inv + 9 quickbar + 4 armor) = 160 bytes
2229
command_parser = CommandParser()
30+
server: 'Server'
2331

2432
operator = False
2533

2634
def sendpacket(self, size: int, packet: bytes):
2735
self.request.sendall(struct.pack("i", 5 + size) + packet)
2836

37+
def send_sector(self, world: WorldServer, sector: iVector):
38+
if sector not in world.sectors:
39+
with world.server_lock:
40+
world.open_sector(sector)
41+
42+
if not world.sectors[sector]:
43+
# Empty sector, send packet 2
44+
self.sendpacket(12, b"\2" + struct.pack("iii", *sector))
45+
else:
46+
packet = struct.pack("iii", *sector) \
47+
+ save_sector_to_bytes(world, sector) \
48+
+ world.get_exposed_sector(sector)
49+
self.sendpacket(len(packet), b"\1" + packet)
50+
2951
def sendchat(self, txt: str, color=(255,255,255,255)):
3052
txt_bytes = txt.encode('utf-8')
3153
self.sendpacket(len(txt_bytes) + 4, b"\5" + txt_bytes + struct.pack("BBBB", *color))
@@ -70,17 +92,7 @@ def loop(self):
7092
packettype = struct.unpack("B", byte)[0] # Client Packet Type
7193
if packettype == 1: # Sector request
7294
sector = struct.unpack("iii", self.request.recv(4*3))
73-
74-
if sector not in world.sectors:
75-
with world.server_lock:
76-
world.open_sector(sector)
77-
78-
if not world.sectors[sector]:
79-
#Empty sector, send packet 2
80-
self.sendpacket(12, b"\2" + struct.pack("iii",*sector))
81-
else:
82-
msg = struct.pack("iii",*sector) + save_sector_to_bytes(world, sector) + world.get_exposed_sector(sector)
83-
self.sendpacket(len(msg), b"\1" + msg)
95+
self.send_sector(world, sector)
8496
elif packettype == 3: # Add block
8597
positionbytes = self.request.recv(4*3)
8698
blockbytes = self.request.recv(2)
@@ -141,15 +153,18 @@ def loop(self):
141153
elif packettype == 255: # Initial Login
142154
txtlen = struct.unpack("i", self.request.recv(4))[0]
143155
self.username = self.request.recv(txtlen).decode('utf-8')
144-
self.position = None
145156
load_player(self, "world")
146157

147158
for player in self.server.players.values():
148159
player.sendchat("$$y%s has connected." % self.username)
149160
print("%s's username is %s" % (self.client_address, self.username))
150161

151-
position = (0,self.server.world.terraingen.get_height(0,0)+2,0)
152-
if self.position is None: self.position = position # New player, set initial position
162+
if self.position is None:
163+
# New player, set initial position
164+
self.position = (0.0, world.terraingen.get_height(0, 0) + 2.0, 0.0)
165+
elif self.position[1] < 0:
166+
# Somehow fell below the world, reset their height
167+
self.position = (self.position[0], world.terraingen.get_height(0, 0) + 2.0, self.position[2])
153168

154169
# Send list of current players to the newcomer
155170
for player in self.server.players.values():
@@ -163,16 +178,15 @@ def loop(self):
163178
player.sendpacket(2 + len(name), b'\7' + struct.pack("H", self.id) + name)
164179

165180
#Send them the sector under their feet first so they don't fall
166-
sector = sectorize(position)
167-
if sector not in world.sectors:
168-
with world.server_lock:
169-
world.open_sector(sector)
170-
msg = struct.pack("iii",*sector) + save_sector_to_bytes(world, sector) + world.get_exposed_sector(sector)
171-
self.sendpacket(len(msg), b"\1" + msg)
181+
sector = sectorize(self.position)
182+
self.send_sector(world, sector)
183+
if sector[1] > 0:
184+
sector_below = (sector[0], sector[1] - 1, sector[2])
185+
self.send_sector(world, sector_below)
172186

173187
#Send them their spawn position and world seed(for client side biome generator)
174188
seed_packet = make_string_packet(G.SEED)
175-
self.sendpacket(12 + len(seed_packet), struct.pack("B",255) + struct.pack("iii", *position) + seed_packet)
189+
self.sendpacket(12 + len(seed_packet), struct.pack("B",255) + struct.pack("fff", *self.position) + seed_packet)
176190
self.sendpacket(4*40, b"\6" + self.inventory)
177191
else:
178192
print("Received unknown packettype", packettype)

utils.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Python packages
44
import os
55
import struct
6-
from typing import Tuple, List
6+
from typing import Tuple, List, Union
77

88
# Third-party packages
99
import pyglet
@@ -140,12 +140,10 @@ def normalize(position: fVector) -> fVector:
140140
return normalize_float(x), normalize_float(y), normalize_float(z)
141141

142142

143-
def sectorize(position: iVector) -> iVector:
144-
x, y, z = normalize(position)
145-
x, y, z = (x // G.SECTOR_SIZE,
146-
y // G.SECTOR_SIZE,
147-
z // G.SECTOR_SIZE)
148-
return x, y, z
143+
def sectorize(position: Union[iVector, fVector]) -> iVector:
144+
return (normalize_float(float(position[0])) // G.SECTOR_SIZE,
145+
normalize_float(float(position[1])) // G.SECTOR_SIZE,
146+
normalize_float(float(position[2])) // G.SECTOR_SIZE)
149147

150148

151149
class TextureGroup(pyglet.graphics.Group):

0 commit comments

Comments
 (0)