wtfpl license

This commit is contained in:
MeexReay 2024-12-22 01:35:05 +03:00
parent 1499902a29
commit b57e8938d2
6 changed files with 13 additions and 422 deletions

13
LICENSE Normal file
View file

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View file

@ -1,35 +0,0 @@
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}"

View file

@ -1,16 +0,0 @@
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",
}

View file

@ -1,55 +0,0 @@
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, getPlayer, getPlayers, WORLD)
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())

View file

@ -1,61 +0,0 @@
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")

View file

@ -1,255 +0,0 @@
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}"