I am currently trying to work on a simple game to test out some networking and learn sockets. Currently the setup is practically the exact same as the bgmc networking template (wish I had found this before I wrote the code – would have saved so much time). It works: the client connects, and creates a player entity that represents it on every other client that is at the same position/orientation.
Now, what I struggle to understand is how to have objects that aren’t determined by clients:
The game is based on trying to avoid obstacles (just avoiding swinging pendulums and stuff), and every client basically needs to be “synced to the exact same time” that every obstacle is. The problem there, however, is that the client can’t determine this, because then there would be multiple entities of the obstacles all at different timing at the same place. How do I go about making it so the server determines the positions.orientations of those objects on the map?
This probably has an obvious answer. My mind just isn’t in the right mood right now
Thanks
Here’s the bgmc_net.py code:
from socket import AF_INET, SOCK_DGRAM, socket
from pickle import dumps, loads
import urllib.request as urlReq
from time import time
def client(controller):
from bge import logic
scene = logic.getCurrentScene()
objects = scene.objects
ob = controller.owner
if not hasattr(logic, 'user_id'):
logic.remote_users = {}
logic.memory = {}
logic.user_id = time()
logic.client = socket(AF_INET, SOCK_DGRAM)
logic.client.setblocking(0)
player = objects['Player']
data = [logic.user_id, player.worldPosition[:], player.getAxisVect((0,1,0))[:],player.getAxisVect((0,0,1))[:]]
packet = dumps(data)
logic.client.sendto(packet, (ob['server'], 35107))
try:
received_packet = logic.client.recv(1024)
logic.memory = loads(received_packet)
except:
pass
active = []
for user_id in logic.memory:
user_pos, yVect, zVect = logic.memory[user_id]
if user_id in logic.remote_users:
logic.remote_users[user_id].worldPosition = user_pos
logic.remote_users[user_id].alignAxisToVect(yVect, 1)
logic.remote_users[user_id].alignAxisToVect(zVect, 2)
else:
ob.worldPosition = user_pos
new_user = scene.addObject('RemoteUser', ob)
new_user.worldPosition = user_pos
new_user.alignAxisToVect(yVect, 1)
new_user.alignAxisToVect(zVect, 2)
logic.remote_users[user_id] = new_user
active.append(user_id)
for uid in [uid for uid in logic.remote_users if uid not in active]:
logic.remote_users[uid].endObject()
del logic.remote_users[uid]
class netServer:
def __init__(self):
print('''
[ Simple Python Server - BGMC Edition ]
Make sure that port 35107 is forwarded
and players will be able to join at:
''', str(urlReq.urlopen("http://icanhazip.com/").read()).split("'")[1][:-2], '
')
self.memory = {}
self.history = {}
self.socket = socket(AF_INET, SOCK_DGRAM)
self.socket.bind(('', 35107))
self.socket.setblocking(0)
self.serve()
def serve(self):
while True:
try:
packet, address = self.socket.recvfrom(256)
data = loads(packet)
user_id = data[0]
user_sd = data[1:]
if not user_id in self.memory: print('User %s joined' %user_id)
self.memory[user_id] = user_sd
self.history[user_id] = time()
data = {_id:self.memory[_id] for _id in self.memory if _id != user_id}
packet = dumps(data)
self.socket.sendto(packet, address)
except:
pass
inactive = [ uid for uid in self.history if time() - self.history[uid] > 1]
for uid in inactive:
del self.memory[uid]
del self.history[uid]
print('User %s left' %uid)
if __name__ == '__main__':
bgmcServer = netServer()
Mine’s slightly different, as I wanted the server and client to be separate, but basically works on the same concept