From 3a6df05fb7d3ed2c3458a469fc3d71a01049b481 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Sun, 22 Dec 2024 00:59:32 +0300 Subject: [PATCH] server refactor --- server/__pycache__/block.cpython-311.pyc | Bin 0 -> 2548 bytes server/__pycache__/config.cpython-311.pyc | Bin 0 -> 577 bytes server/__pycache__/main.cpython-311.pyc | Bin 0 -> 3778 bytes server/__pycache__/network.cpython-311.pyc | Bin 0 -> 5040 bytes server/__pycache__/player.cpython-311.pyc | Bin 0 -> 14182 bytes server/block.py | 35 +++ server/config.py | 16 + server/main.py | 347 +-------------------- server/network.py | 61 ++++ server/player.py | 255 +++++++++++++++ server/src/block.py | 35 +++ server/src/config.py | 16 + server/src/main.py | 55 ++++ server/src/network.py | 61 ++++ server/src/player.py | 255 +++++++++++++++ server/start.sh | 6 + 16 files changed, 801 insertions(+), 341 deletions(-) create mode 100644 server/__pycache__/block.cpython-311.pyc create mode 100644 server/__pycache__/config.cpython-311.pyc create mode 100644 server/__pycache__/main.cpython-311.pyc create mode 100644 server/__pycache__/network.cpython-311.pyc create mode 100644 server/__pycache__/player.cpython-311.pyc create mode 100644 server/block.py create mode 100644 server/config.py create mode 100644 server/network.py create mode 100644 server/player.py create mode 100644 server/src/block.py create mode 100644 server/src/config.py create mode 100644 server/src/main.py create mode 100644 server/src/network.py create mode 100644 server/src/player.py create mode 100755 server/start.sh diff --git a/server/__pycache__/block.cpython-311.pyc b/server/__pycache__/block.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b4b878150fb756010a5f38c16c7f1ceae0f5a2d GIT binary patch literal 2548 zcmZ3^%ge>Uz`!7Bk)H0r!octt#DQTJDC4sZ0|Uc!h7^Vr#vF!R#wbQc1||k~h7_h2 zh7{&yObiUGnV>2eqL@-xf*CYfUxEZQ8E>%$2RMfNC4+b{3{(4A4{T~GLlk2QNFQSh zLliT}%qW%=<`#x1))bZ&hA6fajuf^Q#whj__Fx80&ReWbIr+)i$!svw7#J8p1~M}+ zFnsm_8(70w!w?Ubu3@TSh-ZXxYnW>o;z8=c0yQi(4DleH5FTp{Lp;pO3@Hr33@aJ^ zG+A#kR@`E&yv0&dS&({*H90>gzvvc6a(+%uW=d+YCfhBR;?$h9A`S)yh9XV|28LT) zNgxNtgOnF>gG6~47#NB{?o|MTUncq)`MIh3rNya5`o;OBMail9xv8lY#hE3k`sL;2 z`pKn9naTRasYPX}MfzaF^a?6(am2@G=4F<|$5-)zLqHG42f4UdlYxPuf#HUrPzOs7 z8;lZ>>tN~Oydf&p!P3KZLqeg0rH8kJw}baH$h*n#FkxU|0I{1vAqYwf-VBW3$PQ*G zVrO7rSjn)Gv4|Js2aqa-B7Tr3SxPdKv#YouE&;JYKK%?LUNF1>xrBqKgQZB2fq{W& zdy0fXfhB@w5nEAeUP@|F6%WKJ2#*h>QVc|ZZ2*M;$V(s$icPRjzA-W|Kzvfel){(| z5@#q9uVKgnsRH8~rYZ&oh8jkMNEH`|kDOXibRyCXGgK#B1gaBk3&?PUoyBZ5%y3iI z)i7kiU7Ny`4c1>|RKvJ{6{HItr!X&LWMEhg3U{y+BSQ`20#Hf<^N@)Y7Ic**5!5mU28PveE~*|-ZiQh@PQM~hz~17@D$Om3Ps-0P zE=h;z`(pnR6wo0rLGn4R7Ef_%iC1ZE0ffhypBJBAlwX>c0=2mqtca~RwIm?FxCoRsZt)hU z=B0$>2jnDHrWO@zvVb$zEw%zMA8b3=+G0>50hJbz+{T%o=L{)us`w%K04@N^0L40t z3=GhG$IUZ=vCFK(Y=O!WwH1a7wN{j^sko?QKEZ5?%?&(q4`6Z=0%s^r3Y!pigI~C( za)!?(evJ$K8aD*Qt_!GL5>Q)Ea#29%ih#}q0UfZI@+AS~1&$X5)UF7qT@X;ap{zcE z?TUcH1p$Q{g5p;Ml@=sk5>&q+s18;PHlX;Tfc6yu?F$0hU@2B&KyyOy`Oi$Wa%-PQxTWh%<=EObGiR#2}!0 zfnNn&Foh(85&z&Oomn%;&g&DtXb3xTAi{C9KC&OQiI=7gd3^dsg3Fa1aW?o4V zsHOoYRdB_l$plGV%!w%}#UQ^bKnri~lKkM3#FEt9)Vz`^K}do^5>f&c!D)~RB|Pc^ zf7u28;0Z2M+%E73U*Hd(5i%zX!djZVLS>EaMKy~nY8DWY9VUA$A*=%>N2(w!5SdVR zAvN<#YW9VMG7!oux{_A{VkDGZ;3xw}hMy*5h$aW9lFLiXO^uJg#T6f)o1ape17h>U z#}}3+=0IeM1VH7!D2R{%5$YfU)RKVIAE5jI&NM}!@C6f~XekC2@(m0y_<@O)Rq+D@ zoZw?*<^8|_C)nUDuoxRZtL_H|IHAPITFwYkjhh7f32eEaCi5+}Msr(h+plBjG>iraWDe|!v|(YM#dWq5*JX>2NnfJkk#19j|?F3FJSTm1_^c;0Ft#U Aj{pDw literal 0 HcmV?d00001 diff --git a/server/__pycache__/config.cpython-311.pyc b/server/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f4b86e28eb219ecf563ae569399417929d70243 GIT binary patch literal 577 zcmZ3^%ge>Uz`&qtk)F=L$iVOz#DQTJDC2V*0|Uc!h7^Vr#vFzyhE#?uMyL!!3X>#^ z$*_P4&O~CQFfU_dU|0>;5yQm55XBtD!o-lun#zJI7sZm!kixQvF^VmPHHtljEs7(B zJ%uBMGlgpoa};L^V=#jz_e+r3elJ1h{bIDzWdFsYoML43i$&Qe#i)u!*~loRibXjE z!cGCRp&}`oOhq6Uf{B;>3=9laEXt;)rbTQF3=BoA3=9mK%(vL`@{4j4b8c~EmF5=2 zC*|iCm)v5@&dkY4Ez;z=#avuje2XQqD81|!YjHtNX2~rU5C7nhTPy+oK_R!8GxJJr zu{rzu_y+~wVhs*(4EMXm7v$>b>=Ezc864v1=j?im+sVh@**iWYGQc%>CBtWsUw)bD zXXNLm>X#O$7U>t~mlh?b>gT4WRupHJr0SQKm+L2&CS@k;7pE4Lr55QY=jWwmrt1|{ z{^GF7%}*)KNwq7IU|;~n9Yb*z0|UbcW=2NF8w^|xVEBQJfmfi%V?tn$_jMlGOFXhO zk}vWoUExt`!gASm3x_koRpU-X8M b#0@@?59}=bOdl9n_?a5GL9j@Sfq?-4zTA%- literal 0 HcmV?d00001 diff --git a/server/__pycache__/main.cpython-311.pyc b/server/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fecc7947d764568a182aea61dc9ae44063531405 GIT binary patch literal 3778 zcmZ3^%ge>Uz`(#|o}SLj%E0g##DQT>DC6@F1_p-d3@HpLj5!QZ5SlTHF@+(8DTgVS zIf|JPB*vV>lFJ&!3TCt9u!S(Bu(mKnv8S-LFhp^ru(vQoai(yzFhp^saJDc+ai?&# zFhudBaJMi-@iH-_@}=;k@TBmj@TKrCV`X4i%?h=f0W8Om!jmG9B8XK^2)n*?=0yHf zffV6vCXh)*QcMh~3|WF8HV88@r1CCfU|?7c;(+loMh1q}j9?}M0|O&N3S%%BYl^%C z3HoU=-r_DUNh~S}PAw`+Ez)GX#TJm0SP5n^Y9)izz%UB~1A{UH1H^uae2X>Q zKgh@B7E4KGL2405&q~Hyj7h~HUnu-C*3Zb#P1P?gPA$?e&Mz%WPSwv%O|2--EJ@Wb zFE7_mE=|fz)-MM8Mn5+(Gf%Ie@)lQmY6-+!#YMaf3=HfH3=G9q3=9k}7+x?mFg)cI z`oO@%Dgq`t81HiPPhjjc?=hd6c8Oc&0=LW!A>j^p5d86h6{hSn$Ro)hH-Q)+400*R z_n$Ms=?X1uG;0}A!iJGx*zngdW`WEDnaxnc01q+7WF|(2V1^zoP>2xI&021Z~`4*I36cmbh7#J9Cal(V62$Xa{AyVwfzyJ#gW>(1$ z49u*O*g}F|pr>qxNLO7)-3@Vx2^=8!;{!WPM-d+b0|Q2)0eRxH2P9CC0t`7gvf$#V z$v1_uij@H^83i+FGWlh`U}j*@WV*##lwX>ca*L%TGdFc51K56uABB=ji;7b7O5$@f zb8<4{LGndn3=9k+pums@d-g83z*Lbbk`tw;NY5y_D5!jqTjdJ3$^{k`urVm!0C}Mq zl=j=;X`d54^~=;U)G#c7djuS9Py*Fc%?v3F)y!cG)0x{?7#VtGOW>sf0|O$)QVSqRBKkg(w_$xO}; z$;?eHDguRsI4DSB;JM)g6EmyQT|u!A42+!8V4}nEhLG@dwMl9dHKu5E_@TnPe4;(M zGh8n6DPG}Iyug74fzpQ(o-mz)9HvO&hZ<@w46*bLVK-0+zXZ8QlLcIA+~UkmO)YTD z$t+7Pk_2TeDG-4kxO{L$kPwzm zPt={Fdx1wDD}sc!<3&EXD|~VnIItj4Xv<@UHYkmOQ}8hc28MQM`OV2t0`ec$RO-SI zYtqHgi6cdKFr+c2FtuzQtHj3^H9op#hvRe{tF5 zWEPhs=jRsKRmns2f)kORO-_DtVotH09zuZ{C`|=0FfjapB&rK?u@JPu@Ic}5ibE9# ztBzD%a12C8aMwx#7s6t|X(wF}3?|xZvO?2- zacW*lcz#h%3Z$-qX8=vcB2|!6KnckK?2TL8NKP-(fHoV7ry<-5$^c4886ch!lmp@! z;aLFU69~DN^@3dNMY-53Fb_h6A>>7&xGO?&7kIEENNypcYyzc0aBeAMgtv7-9)u7nytK@8aLxud0l`fp^ne5f(JfY|oc!c$aGnR*18P^s$KPTuD$PR+*Iyhqx%nxj zIjMF?BE-_19V3xeW!r$QD;yr<70?S0UDQp*6#ILZ3Ux1+x%nU427nmi%F%JOMVGKe5 literal 0 HcmV?d00001 diff --git a/server/__pycache__/network.cpython-311.pyc b/server/__pycache__/network.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..763cf31661513477df28e09578ea0f81ee6da2d8 GIT binary patch literal 5040 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 block.x-1 and self.x < block.x+1: - if self.y > block.y and self.y + self.vel_y - 1 < block.y: - self.on_ground = True - collide_y = 1 - if self.y < block.y and self.y + self.vel_y > block.y - 1: - collide_y = -1 - - if self.y > block.y-1 and self.y < block.y+1: - if self.x > block.x and self.x + self.vel_x - 1 < block.x: - collide_x = 1 - if self.x < block.x and self.x + self.vel_x > block.x - 1: - collide_x = -1 - - await block.onCollide(self, collide_x, collide_y) - - async def onCollide(self, player, x, y): - await super().onCollide(player, x, y) - # if x != 0: - # player.vel_x *= 0.5 - # self.vel_x = player.vel_x - # if y != 0: - # player.vel_y *= 0.5 - # self.vel_y = player.vel_y - # pass - - async def render(self): - self.vel_x *= 0.5 - self.vel_y *= 0.5 - self.x += self.vel_x - self.y += self.vel_y - # await self.setVel(self.vel_x * 0.5, self.vel_y * 0.5) - # await self.setPos(self.x + self.vel_x, self.y + self.vel_y) - return self.vel_x != 0 or self.vel_y != 0 - - async def keepAlive(self): - await writePacket(self.websocket, "R", [str(self.x), str(self.y), str(self.vel_x), str(self.vel_y)]) - - def toStatement(self, add=True): - return f"P1{self.name},{self.x},{self.y},{self.vel_x},{self.vel_y},{self.color}" if add else f"P0{self.name}" +import asyncio, time +from network import startServer +from player import Player +from block import Block +from config import * def getPlayers(): global WORLD @@ -202,140 +21,6 @@ def getPlayer(name): def current_milli_time(): return round(time.time() * 1000) -async def readPacket(websocket: ServerConnection) -> tuple[str, list[str]]: - data = await websocket.recv() - id,data = data[0], data[1:].splitlines() - print(id, data) - return id,data - -async def writePacket(websocket: ServerConnection, packet_id: str, packet_data: list[str]): - await websocket.send(packet_id + ("\n".join(packet_data))) - -async def handler(websocket: ServerConnection): - packet_id, packet_data = await readPacket(websocket) - - name = packet_data[0] - - if packet_id != "J": - await writePacket(websocket, "K", ["join packet is invalid"]) - return - if getPlayer(name) != None: - await writePacket(websocket, "K", ["this nickname is already in use"]) - return - - print(name, "joined to the server") - - try: - player = Player(websocket) - - await player.sendWorld([b.toStatement() for b in WORLD]) - - await player.sendBlockTypes(BLOCK_TYPES.keys()) - await player.setColor(random.choice(COLORS)) - await player.setPos(*SPAWN) - await player.setVel(0,0) - await player.setName(name) - await player.setWalkSpeed(0.5) - - await player.sendToPlayers() - - WORLD.append(player) - - while True: - packet_id, packet_data = await readPacket(websocket) - - if packet_id == "V": - vel_x, vel_y = float(packet_data[0]), float(packet_data[1]) - vel_x = max(min(vel_x, player.walk_speed), -player.walk_speed) - vel_y = max(min(vel_y, player.jump_speed), 0) - - player.vel_x += vel_x - - if player.on_ground: - player.vel_y += vel_y - player.on_ground = False - - await player.sendToPlayers() - - if packet_id == "K": - key,pressed = packet_data - pressed = pressed == "1" - - if key == "KeyR" and pressed: - await player.setPos(SPAWN[0], SPAWN[1]) - if key == "ShiftLeft": - if pressed: - await player.setWalkSpeed(1) - else: - await player.setWalkSpeed(0.5) - - if packet_id == "M": - message = packet_data[0] - message = f"{name} > {message}" - - for p in getPlayers(): - await p.sendMessage(message) - - print(message) - - if packet_id == "D": - x,y = packet_data - x,y = int(x),int(y) - - block = None - for i in WORLD: - if type(i) == Player: - continue - if i.x == x and i.y == y: - block = i - break - if not block: continue - - if block.type == "spawn": continue # spawn block protection - - if abs(x - player.x) ** 2 + abs(y - player.y) ** 2 > REACH_DISTANCE ** 2: - continue - - WORLD.remove(block) - - for p in getPlayers(): - await p.sendWorld([block.toStatement(False)]) - - if packet_id == "P": - x,y,block_type = packet_data - x,y = int(x),int(y) - - if block_type not in BLOCK_TYPES: - continue - - if abs(x - player.x) ** 2 + abs(y - player.y) ** 2 > REACH_DISTANCE ** 2: - continue - - found_block = False - for i in WORLD: - if type(i) == Player: - continue - if i.x == x and i.y == y: - found_block = True - break - if found_block: continue - - block = Block(x,y,block_type,BLOCK_TYPES[block_type],True) - - WORLD.append(block) - - for p in getPlayers(): - await p.sendWorld([block.toStatement()]) - except Exception as exc: - WORLD.remove(player) - - for p in getPlayers(): - await p.sendWorld([player.toStatement(False)]) - - await writePacket(websocket, "K", [str(exc)]) - - print(name, "left the server") - async def tickTimer(): while True: for b in WORLD: @@ -358,25 +43,7 @@ async def main(): asyncio.get_event_loop().create_task(tickTimer()) asyncio.get_event_loop().create_task(keepAliveTimer()) asyncio.get_event_loop().create_task(renderTimer()) - async with serve(handler, HOST, PORT) as server: - print(f"started server on {HOST}:{PORT}") - await asyncio.get_running_loop().create_future() - - - -HOST,PORT = sys.argv[1].split(":") -PORT = int(PORT) - -COLORS = ["#d22", "#2d2", "#22d", "#dd2", "#2dd", "#d2d", "#ddd"] -SPAWN = (0, 0) - -REACH_DISTANCE = 15 - -BLOCK_TYPES = { - "normal": "#555", - "jump_boost": "#2d2", - "killer": "#d22", -} + await startServer(HOST, PORT, getPlayer, getPlayers, WORLD) WORLD = [ Block(-1, -1, "normal", "#555", True), @@ -384,7 +51,5 @@ WORLD = [ Block(1, -1, "normal", "#555", True) ] - - if __name__ == "__main__": asyncio.run(main()) \ No newline at end of file diff --git a/server/network.py b/server/network.py new file mode 100644 index 0000000..0044551 --- /dev/null +++ b/server/network.py @@ -0,0 +1,61 @@ +from websockets.server import serve, ServerConnection +import asyncio +from config import BLOCK_TYPES, COLORS, SPAWN +from main import WORLD, getPlayer, getPlayers +from player import Player +import random + +async def startServer(host, port): + async with serve(handler, host, port): + print(f"started server on {host}:{port}") + await asyncio.get_running_loop().create_future() + +async def readPacket(websocket: ServerConnection) -> tuple[str, list[str]]: + data = await websocket.recv() + return data[0], data[1:].splitlines() + +async def writePacket(websocket: ServerConnection, packet_id: str, packet_data: list[str]): + await websocket.send(packet_id + ("\n".join(packet_data))) + +async def handler(websocket: ServerConnection): + packet_id, packet_data = await readPacket(websocket) + + name = packet_data[0] + + if packet_id != "J": + await writePacket(websocket, "K", ["join packet is invalid"]) + return + if getPlayer(name) != None: + await writePacket(websocket, "K", ["this nickname is already in use"]) + return + + print(name, "joined to the server") + + try: + player = Player(websocket) + + await player.sendWorld([b.toStatement() for b in WORLD]) + + await player.sendBlockTypes(BLOCK_TYPES.keys()) + await player.setColor(random.choice(COLORS)) + await player.setPos(*SPAWN) + await player.setVel(0,0) + await player.setName(name) + await player.setWalkSpeed(0.5) + + await player.sendToPlayers() + + WORLD.append(player) + + while True: + packet_id, packet_data = await readPacket(websocket) + player.onPacket(packet_id, packet_data) + except Exception as exc: + WORLD.remove(player) + + for p in getPlayers(): + await p.sendWorld([player.toStatement(False)]) + + await writePacket(websocket, "K", [str(exc)]) + + print(name, "left the server") \ No newline at end of file diff --git a/server/player.py b/server/player.py new file mode 100644 index 0000000..19dd784 --- /dev/null +++ b/server/player.py @@ -0,0 +1,255 @@ +from block import Block +from network import writePacket +from config import SPAWN, REACH_DISTANCE, BLOCK_TYPES +from main import getPlayers, WORLD +import time + +class Player(Block): + def __init__(self, websocket, x=None, y=None, name=None, color=None, vel_x=None, vel_y=None): + super().__init__(x, y, None, color, True) + self.x = x + self.y = y + + self.name = name + self.color = color + self.vel_x = vel_x + self.vel_y = vel_y + + self.websocket = websocket + + self.on_ground = False + + self.walk_speed = 1 + self.jump_speed = 2 + self.gravity_speed = 0.5 + + self.lsd_pos = (x, y) + self.lsd_time = time.time() + + async def sendPacket(self, packet_id, packet_data): + await writePacket(self.websocket, packet_id, packet_data) + + async def onPacket(self, packet_id, packet_data): + if packet_id == "V": + vel_x, vel_y = float(packet_data[0]), float(packet_data[1]) + vel_x = max(min(vel_x, self.walk_speed), -self.walk_speed) + vel_y = max(min(vel_y, self.jump_speed), 0) + + self.vel_x += vel_x + + if self.on_ground: + self.vel_y += vel_y + self.on_ground = False + + await self.sendToPlayers() + + if packet_id == "X": + x, y = float(packet_data[0]), float(packet_data[1]) + + ticks = (time.time() - self.lsd_time) * 20 + rx, ry = abs(x - self.lsd_pos[0]), y - self.lsd_pos[1] + + if rx > self.walk_speed * ticks: return + if ry < 0 and abs(ry) > self.gravity_speed * ticks: return + if ry > 0 and ry > self.jump_speed * ticks: return + + self.x = x + self.y = y + + self.lsd_pos = (x, y) + self.lsd_time = time.time() + + await self.sendToPlayers() + + if packet_id == "K": + key,pressed = packet_data + pressed = pressed == "1" + + if key == "KeyR" and pressed: + await self.setPos(SPAWN[0], SPAWN[1]) + if key == "ShiftLeft": + if pressed: + await self.setWalkSpeed(1) + else: + await self.setWalkSpeed(0.5) + + if packet_id == "M": + message = packet_data[0] + message = f"{self.name} > {message}" + + for p in getPlayers(): + await p.sendMessage(message) + + print(message) + + if packet_id == "D": + x,y = packet_data + x,y = int(x),int(y) + + block = None + for i in WORLD: + if type(i) == Player: + continue + if i.x == x and i.y == y: + block = i + break + if not block: return + + if block.type == "spawn": return # spawn block protection + + if abs(x - self.x) ** 2 + abs(y - self.y) ** 2 > REACH_DISTANCE ** 2: + return + + WORLD.remove(block) + + for p in getPlayers(): + await p.sendWorld([block.toStatement(False)]) + + if packet_id == "P": + x,y,block_type = packet_data + x,y = int(x),int(y) + + if block_type not in BLOCK_TYPES: + return + + if abs(x - self.x) ** 2 + abs(y - self.y) ** 2 > REACH_DISTANCE ** 2: + return + + found_block = False + for i in WORLD: + if type(i) == Player: + continue + if i.x == x and i.y == y: + found_block = True + break + if found_block: return + + block = Block(x,y,block_type,BLOCK_TYPES[block_type],True) + + WORLD.append(block) + + for p in getPlayers(): + await p.sendWorld([block.toStatement()]) + + async def setWalkSpeed(self, speed): + await writePacket(self.websocket, "S", ["W", str(speed)]) + self.walk_speed = speed + + async def setGravitySpeed(self, speed): + await writePacket(self.websocket, "S", ["G", str(speed)]) + self.gravity_speed = speed + + async def setJumpSpeed(self, speed): + await writePacket(self.websocket, "S", ["J", str(speed)]) + self.jump_speed = speed + + async def sendName(self, name): + await writePacket(self.websocket, "N", [name]) + + async def setName(self, name): + self.name = name + await self.sendName(name) + + async def setColor(self, color): + self.color = color + await writePacket(self.websocket, "C", [color]) + + async def setVel(self, x, y): + if x == self.vel_x and y == self.vel_y: return + + self.vel_x = x + self.vel_y = y + + await self.sendVel(x, y) + + async def setPos(self, x, y): + if x == self.x and y == self.y: return + + self.x = x + self.y = y + + await self.sendPos(x, y) + + async def sendVel(self, x, y): + await writePacket(self.websocket, "V", [str(x), str(y)]) + + async def sendPos(self, x, y): + await writePacket(self.websocket, "P", [str(x), str(y)]) + + async def sendMessage(self, message): + await writePacket(self.websocket, "M", message.split("\n")) + + async def sendWorld(self, statements): + if len(statements) == 0: return + await writePacket(self.websocket, "W", statements) + + async def sendBlockTypes(self, types): + await writePacket(self.websocket, "B", types) + + async def sendToPlayers(self): + for p in getPlayers(): + if p != self: + await p.sendWorld([self.toStatement()]) + + async def tick(self): + self.x = round(self.x * 100) / 100 + self.y = round(self.y * 100) / 100 + self.vel_x = round(self.vel_x * 100) / 100 + self.vel_y = round(self.vel_y * 100) / 100 + + if not self.on_ground: + self.vel_y -= self.gravity_speed + + await self.collide() + + async def collide(self): + global WORLD + + self.on_ground = False + + for block in WORLD: + if not block.collides: continue + if block == self: continue + + collide_x = 0 + collide_y = 0 + + if self.x > block.x-1 and self.x < block.x+1: + if self.y > block.y and self.y + self.vel_y - 1 < block.y: + self.on_ground = True + collide_y = 1 + if self.y < block.y and self.y + self.vel_y > block.y - 1: + collide_y = -1 + + if self.y > block.y-1 and self.y < block.y+1: + if self.x > block.x and self.x + self.vel_x - 1 < block.x: + collide_x = 1 + if self.x < block.x and self.x + self.vel_x > block.x - 1: + collide_x = -1 + + await block.onCollide(self, collide_x, collide_y) + + async def onCollide(self, player, x, y): + await super().onCollide(player, x, y) + # if x != 0: + # player.vel_x *= 0.5 + # self.vel_x = player.vel_x + # if y != 0: + # player.vel_y *= 0.5 + # self.vel_y = player.vel_y + # pass + + async def render(self): + self.vel_x *= 0.5 + self.vel_y *= 0.5 + self.x += self.vel_x + self.y += self.vel_y + # await self.setVel(self.vel_x * 0.5, self.vel_y * 0.5) + # await self.setPos(self.x + self.vel_x, self.y + self.vel_y) + return self.vel_x != 0 or self.vel_y != 0 + + async def keepAlive(self): + await writePacket(self.websocket, "R", [str(self.x), str(self.y), str(self.vel_x), str(self.vel_y)]) + + def toStatement(self, add=True): + return f"P1{self.name},{self.x},{self.y},{self.vel_x},{self.vel_y},{self.color}" if add else f"P0{self.name}" diff --git a/server/src/block.py b/server/src/block.py new file mode 100644 index 0000000..d49c593 --- /dev/null +++ b/server/src/block.py @@ -0,0 +1,35 @@ +from config import SPAWN + +class Block: + def __init__(self, x, y, block_type, color, collides): + self.x = x + self.y = y + self.type = block_type + self.color = color + self.collides = collides + + async def tick(self): + pass + + async def render(self): + pass + + async def onCollide(self, player, x, y): + if x != 0: player.vel_x = self.x + x - player.x + if y != 0: player.vel_y = self.y + y - player.y + + if x != 0 or y != 0: # special blocks + if self.type == "jump_boost": + player.setGravitySpeed(1.25) + player.setJumpSpeed(5) + player.on_ground = True + elif player.jump_speed != 2: + player.setGravitySpeed(0.5) + player.setJumpSpeed(2) + + if self.type == "killer": + await player.setPos(*SPAWN) + await player.sendToPlayers() + + def toStatement(self, add=True): + return f"B1{self.x},{self.y},{int(self.collides)},{self.type},{self.color}" if add else f"B0{self.x},{self.y}" \ No newline at end of file diff --git a/server/src/config.py b/server/src/config.py new file mode 100644 index 0000000..a2447d1 --- /dev/null +++ b/server/src/config.py @@ -0,0 +1,16 @@ +import sys + + +HOST,PORT = sys.argv[1].split(":") +PORT = int(PORT) + +COLORS = ["#d22", "#2d2", "#22d", "#dd2", "#2dd", "#d2d", "#ddd"] +SPAWN = (0, 0) + +REACH_DISTANCE = 15 + +BLOCK_TYPES = { + "normal": "#555", + "jump_boost": "#2d2", + "killer": "#d22", +} \ No newline at end of file diff --git a/server/src/main.py b/server/src/main.py new file mode 100644 index 0000000..6526332 --- /dev/null +++ b/server/src/main.py @@ -0,0 +1,55 @@ + +import asyncio, time +from network import startServer +from player import Player +from block import Block +from config import * + +def getPlayers(): + global WORLD + for b in WORLD: + if type(b) == Player: + yield b + +def getPlayer(name): + global WORLD + for b in WORLD: + if type(b) == Player: + if b.name == name: + return b + +def current_milli_time(): + return round(time.time() * 1000) + +async def tickTimer(): + while True: + for b in WORLD: + await b.tick() + await asyncio.sleep(1/20) + +async def keepAliveTimer(): + while True: + for b in getPlayers(): + await b.keepAlive() + await asyncio.sleep(1) + +async def renderTimer(): + while True: + for p in getPlayers(): + await p.sendWorld([b.toStatement() for b in WORLD if await b.render() and b != p]) + await asyncio.sleep(1/60) + +async def main(): + asyncio.get_event_loop().create_task(tickTimer()) + asyncio.get_event_loop().create_task(keepAliveTimer()) + asyncio.get_event_loop().create_task(renderTimer()) + await startServer(HOST, PORT) + +WORLD = [ + Block(-1, -1, "normal", "#555", True), + Block(0, -1, "spawn", "#2ad", True), + Block(1, -1, "normal", "#555", True) +] + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/server/src/network.py b/server/src/network.py new file mode 100644 index 0000000..0044551 --- /dev/null +++ b/server/src/network.py @@ -0,0 +1,61 @@ +from websockets.server import serve, ServerConnection +import asyncio +from config import BLOCK_TYPES, COLORS, SPAWN +from main import WORLD, getPlayer, getPlayers +from player import Player +import random + +async def startServer(host, port): + async with serve(handler, host, port): + print(f"started server on {host}:{port}") + await asyncio.get_running_loop().create_future() + +async def readPacket(websocket: ServerConnection) -> tuple[str, list[str]]: + data = await websocket.recv() + return data[0], data[1:].splitlines() + +async def writePacket(websocket: ServerConnection, packet_id: str, packet_data: list[str]): + await websocket.send(packet_id + ("\n".join(packet_data))) + +async def handler(websocket: ServerConnection): + packet_id, packet_data = await readPacket(websocket) + + name = packet_data[0] + + if packet_id != "J": + await writePacket(websocket, "K", ["join packet is invalid"]) + return + if getPlayer(name) != None: + await writePacket(websocket, "K", ["this nickname is already in use"]) + return + + print(name, "joined to the server") + + try: + player = Player(websocket) + + await player.sendWorld([b.toStatement() for b in WORLD]) + + await player.sendBlockTypes(BLOCK_TYPES.keys()) + await player.setColor(random.choice(COLORS)) + await player.setPos(*SPAWN) + await player.setVel(0,0) + await player.setName(name) + await player.setWalkSpeed(0.5) + + await player.sendToPlayers() + + WORLD.append(player) + + while True: + packet_id, packet_data = await readPacket(websocket) + player.onPacket(packet_id, packet_data) + except Exception as exc: + WORLD.remove(player) + + for p in getPlayers(): + await p.sendWorld([player.toStatement(False)]) + + await writePacket(websocket, "K", [str(exc)]) + + print(name, "left the server") \ No newline at end of file diff --git a/server/src/player.py b/server/src/player.py new file mode 100644 index 0000000..19dd784 --- /dev/null +++ b/server/src/player.py @@ -0,0 +1,255 @@ +from block import Block +from network import writePacket +from config import SPAWN, REACH_DISTANCE, BLOCK_TYPES +from main import getPlayers, WORLD +import time + +class Player(Block): + def __init__(self, websocket, x=None, y=None, name=None, color=None, vel_x=None, vel_y=None): + super().__init__(x, y, None, color, True) + self.x = x + self.y = y + + self.name = name + self.color = color + self.vel_x = vel_x + self.vel_y = vel_y + + self.websocket = websocket + + self.on_ground = False + + self.walk_speed = 1 + self.jump_speed = 2 + self.gravity_speed = 0.5 + + self.lsd_pos = (x, y) + self.lsd_time = time.time() + + async def sendPacket(self, packet_id, packet_data): + await writePacket(self.websocket, packet_id, packet_data) + + async def onPacket(self, packet_id, packet_data): + if packet_id == "V": + vel_x, vel_y = float(packet_data[0]), float(packet_data[1]) + vel_x = max(min(vel_x, self.walk_speed), -self.walk_speed) + vel_y = max(min(vel_y, self.jump_speed), 0) + + self.vel_x += vel_x + + if self.on_ground: + self.vel_y += vel_y + self.on_ground = False + + await self.sendToPlayers() + + if packet_id == "X": + x, y = float(packet_data[0]), float(packet_data[1]) + + ticks = (time.time() - self.lsd_time) * 20 + rx, ry = abs(x - self.lsd_pos[0]), y - self.lsd_pos[1] + + if rx > self.walk_speed * ticks: return + if ry < 0 and abs(ry) > self.gravity_speed * ticks: return + if ry > 0 and ry > self.jump_speed * ticks: return + + self.x = x + self.y = y + + self.lsd_pos = (x, y) + self.lsd_time = time.time() + + await self.sendToPlayers() + + if packet_id == "K": + key,pressed = packet_data + pressed = pressed == "1" + + if key == "KeyR" and pressed: + await self.setPos(SPAWN[0], SPAWN[1]) + if key == "ShiftLeft": + if pressed: + await self.setWalkSpeed(1) + else: + await self.setWalkSpeed(0.5) + + if packet_id == "M": + message = packet_data[0] + message = f"{self.name} > {message}" + + for p in getPlayers(): + await p.sendMessage(message) + + print(message) + + if packet_id == "D": + x,y = packet_data + x,y = int(x),int(y) + + block = None + for i in WORLD: + if type(i) == Player: + continue + if i.x == x and i.y == y: + block = i + break + if not block: return + + if block.type == "spawn": return # spawn block protection + + if abs(x - self.x) ** 2 + abs(y - self.y) ** 2 > REACH_DISTANCE ** 2: + return + + WORLD.remove(block) + + for p in getPlayers(): + await p.sendWorld([block.toStatement(False)]) + + if packet_id == "P": + x,y,block_type = packet_data + x,y = int(x),int(y) + + if block_type not in BLOCK_TYPES: + return + + if abs(x - self.x) ** 2 + abs(y - self.y) ** 2 > REACH_DISTANCE ** 2: + return + + found_block = False + for i in WORLD: + if type(i) == Player: + continue + if i.x == x and i.y == y: + found_block = True + break + if found_block: return + + block = Block(x,y,block_type,BLOCK_TYPES[block_type],True) + + WORLD.append(block) + + for p in getPlayers(): + await p.sendWorld([block.toStatement()]) + + async def setWalkSpeed(self, speed): + await writePacket(self.websocket, "S", ["W", str(speed)]) + self.walk_speed = speed + + async def setGravitySpeed(self, speed): + await writePacket(self.websocket, "S", ["G", str(speed)]) + self.gravity_speed = speed + + async def setJumpSpeed(self, speed): + await writePacket(self.websocket, "S", ["J", str(speed)]) + self.jump_speed = speed + + async def sendName(self, name): + await writePacket(self.websocket, "N", [name]) + + async def setName(self, name): + self.name = name + await self.sendName(name) + + async def setColor(self, color): + self.color = color + await writePacket(self.websocket, "C", [color]) + + async def setVel(self, x, y): + if x == self.vel_x and y == self.vel_y: return + + self.vel_x = x + self.vel_y = y + + await self.sendVel(x, y) + + async def setPos(self, x, y): + if x == self.x and y == self.y: return + + self.x = x + self.y = y + + await self.sendPos(x, y) + + async def sendVel(self, x, y): + await writePacket(self.websocket, "V", [str(x), str(y)]) + + async def sendPos(self, x, y): + await writePacket(self.websocket, "P", [str(x), str(y)]) + + async def sendMessage(self, message): + await writePacket(self.websocket, "M", message.split("\n")) + + async def sendWorld(self, statements): + if len(statements) == 0: return + await writePacket(self.websocket, "W", statements) + + async def sendBlockTypes(self, types): + await writePacket(self.websocket, "B", types) + + async def sendToPlayers(self): + for p in getPlayers(): + if p != self: + await p.sendWorld([self.toStatement()]) + + async def tick(self): + self.x = round(self.x * 100) / 100 + self.y = round(self.y * 100) / 100 + self.vel_x = round(self.vel_x * 100) / 100 + self.vel_y = round(self.vel_y * 100) / 100 + + if not self.on_ground: + self.vel_y -= self.gravity_speed + + await self.collide() + + async def collide(self): + global WORLD + + self.on_ground = False + + for block in WORLD: + if not block.collides: continue + if block == self: continue + + collide_x = 0 + collide_y = 0 + + if self.x > block.x-1 and self.x < block.x+1: + if self.y > block.y and self.y + self.vel_y - 1 < block.y: + self.on_ground = True + collide_y = 1 + if self.y < block.y and self.y + self.vel_y > block.y - 1: + collide_y = -1 + + if self.y > block.y-1 and self.y < block.y+1: + if self.x > block.x and self.x + self.vel_x - 1 < block.x: + collide_x = 1 + if self.x < block.x and self.x + self.vel_x > block.x - 1: + collide_x = -1 + + await block.onCollide(self, collide_x, collide_y) + + async def onCollide(self, player, x, y): + await super().onCollide(player, x, y) + # if x != 0: + # player.vel_x *= 0.5 + # self.vel_x = player.vel_x + # if y != 0: + # player.vel_y *= 0.5 + # self.vel_y = player.vel_y + # pass + + async def render(self): + self.vel_x *= 0.5 + self.vel_y *= 0.5 + self.x += self.vel_x + self.y += self.vel_y + # await self.setVel(self.vel_x * 0.5, self.vel_y * 0.5) + # await self.setPos(self.x + self.vel_x, self.y + self.vel_y) + return self.vel_x != 0 or self.vel_y != 0 + + async def keepAlive(self): + await writePacket(self.websocket, "R", [str(self.x), str(self.y), str(self.vel_x), str(self.vel_y)]) + + def toStatement(self, add=True): + return f"P1{self.name},{self.x},{self.y},{self.vel_x},{self.vel_y},{self.color}" if add else f"P0{self.name}" diff --git a/server/start.sh b/server/start.sh new file mode 100755 index 0000000..26aae65 --- /dev/null +++ b/server/start.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +HOST=localhost +PORT=8000 + +python3 src/main.py $HOST:$PORT \ No newline at end of file