DanisRace/Scripts/Multiplayer_Client.py
Victorious Children Studios 594e088a83 07-07-24
2024-07-13 16:15:50 +03:00

222 lines
5.9 KiB
Python

# GPLv3 or later
# (C) J.Y.Amihud ( blenderdumbass ) 2024
# Multiplayer client functions
import bge
import time
import json
import zlib
import traceback
from Scripts import Vehicle
from Scripts import Character_Controll
from Scripts import Opt
from Scripts import Settings
from Scripts.Multiplayer_Shared import *
from Scripts import Reuse
from Scripts.Common import *
settings = Settings.load_settings()
host = settings.get("mp-host", "")
def DescribeScene():
scene = bge.logic.getCurrentScene()
dani = scene.objects["Dani_Box"]
cam = scene.active_camera
garage = scene.objects["GarageColider"]
garageDistance = 31
chunksize = 250
data = {}
addr = Opt.Address(dani.position, chunksize)
if addr not in data:
data[addr] = []
danidata = Character_Controll.Encode(dani)
data[addr].append(danidata)
userId = bge.logic.globalDict.get("userId")
for car in bge.logic.globalDict["allcars"]:
if car.get("inview") and car.getDistanceTo(garage) > garageDistance:
if car.get("ownerId") and car.get("ownerId") != userId:
continue
addr = Opt.Address(car.position, chunksize)
cardata = Vehicle.Encode(car)
if addr not in data:
data[addr] = []
data[addr].append(cardata)
return data
def MainLoop():
scene = bge.logic.getCurrentScene()
dani = scene.objects["Dani_Box"]
cam = scene.active_camera
chunksize = 250
bge.logic.globalDict["networkQueue"] = {}
while True:
try:
# A bit of delay, to not owerwhelm the server
time.sleep(0.1)
# Testing if the game is still runing.
# it will fail when the game engine stops.
try: bge.logic.getRealTime()
except: return
if bge.logic.globalDict.get("restore-physics-timer"):
continue
if bge.logic.globalDict.get("network-scene"):
continue
######### SENDING THE DATA TO SERVER ############
data = {}
# Login
LoginEncode(data)
# Scene
data["scene"] = DescribeScene()
data["vision"] = Opt.Surround(cam.position,
chunksize,
cam.orientation.to_euler())
# Queue
networkQueue = bge.logic.globalDict["networkQueue"]
for key in networkQueue:
if networkQueue[key]:
data[key] = networkQueue[key].pop(0)
######### DEALING WITH RESPONSE ############
data = Send(host, data)
for key in data:
payload = data[key]
if key == "login":
LoginDecode(payload)
elif key == "scene":
bge.logic.globalDict["network-scene"] = payload
elif key == "message":
bge.logic.globalDict["print"] = payload
else:
print(key, payload)
except Exception:
print("\n\nNETWORK CLIENT ERROR:", clr["bold"]+clr["tdrd"], traceback.format_exc(), clr["bold"])
def SecondaryLoop():
# This loop runs in the game loop, not the separate thread.
# And it deals with updates sent by the other thread.
if bge.logic.globalDict.get("network-scene"):
data = bge.logic.globalDict["network-scene"]
SceneDecode(data)
bge.logic.globalDict["network-scene"] = None
def LoginEncode(data):
data["login"] = {}
data["login"]["userId"] = bge.logic.globalDict.get("userId")
data["login"]["username"] = settings.get("mp-name")
data["login"]["room"] = settings.get("mp-room")
def LoginDecode(data):
if data.get("userId"):
bge.logic.globalDict["userId"] = data["userId"]
if data.get("room"):
settings["mp-room"] = data["room"]
def SceneDecode(data):
netObjects = bge.logic.globalDict["netObjects"]
if not data:
return
for addr in data:
chunk = data[addr]
for obj in chunk:
# update = True
# if obj.get("netId") in netObjects["netId"]:
# if obj.get("ownerId"):
# netObjects["netId"][obj.get("netId")]["ownerId"] = obj.get("ownerId")
# obj["ID"] = id(netObjects["netId"][obj.get("netId")])
# Sometimes we want to update some things like netId.
if obj.get("ID") in netObjects["pythonId"]\
and obj.get("name") == netObjects["pythonId"][obj["ID"]].name:
netObjects["pythonId"][obj["ID"]]["netId"] = obj.get("netId")
netObjects["netId"][obj.get("netId")] = netObjects["pythonId"][obj["ID"]]
if obj.get("type") == "veh":
Vehicle.Decode(obj, network=True)
elif obj.get("type") == "chr":
Character_Controll.Decode(obj, network=True)
def QueueToSend(key, data):
networkQueue = bge.logic.globalDict["networkQueue"]
if key not in networkQueue:
networkQueue[key] = []
networkQueue[key].append(data)
def GrabOwnership(obj):
# This function grabs ownership of an object.
# Like when a player steals a car spawned by
# another player.
userId = bge.logic.globalDict["userId"]
ownerId = obj.get("ownerId")
netId = obj.get("netId")
# First we will check that the ownership isn't ours.
if userId != ownerId and netId:
QueueToSend("change-ownership",{
"netId" :netId,
"userId":userId
})
obj["ownerId"] = userId