class LogicServer(threading.Thread): def __init__(self): threading.Thread.__init__(self) self._game_running = True self._paused = False self._no_interaction = False self._is_started = False self._time = None self._panda = None self._objects = [] self._scheduled_events = [] # Internal methods def _tick(self): if self._paused: return self._no_interaction = True self._time = time.time() for event in self._scheduled_events: self._resolve_event(event) self._no_interaction = False def _resolve_event(self, _event_data): game, originator, event, call_time, fire_time, on_event, args, kwargs = _event_data mod_time = time.time() - self._time call_time += mod_time if fire_time is None: is_once = event(call_time, *args, **kwargs) if on_event is not None: self._fire_event(on_event, originator) if is_once: self._remove_event(_event_data) else: if call_time >= fire_time: mod_time = time.time() - self._time is_once = event(mod_time, *args, **kwargs) _event_data[3] = 0 if on_event is not None: self._fire_event(on_event, originator) if is_once: self._remove_event(_event_data) else: _event_data[3] = call_time def _resolve_event_return_stack(self, _event_data): game, originator, event, call_time, fire_time, on_event, args, kwargs = _event_data mod_time = time.time() - self._time call_time += mod_time if fire_time is None: return True, event, call_time, args, kwargs else: if call_time >= fire_time: _event_data[3] = 0 return True, event, call_time, args, kwargs else: _event_data[3] += call_time return False, None, None, None, None def _remove_event(self, event): try: self._scheduled_events.remove(event) except ValueError: pass # the event was already remove by some other means, usually by removing it in the logic def _fire_event(self, event, *args, **kwargs): for child in self._objects: stop = child._resolve_event(event, *args, **kwargs) if stop: return # API Methods def kill(self): """stops the execution of this Logic server""" assert self._is_started, "Cannot kill Logic server. It was either killed already or never started in the first place." self._game_running = False def parent_object(self, object): """parents Logic object to this server""" assert self._is_started, "Cannot reparent to Logic server. It was either killed already or never started in the first place." assert object not in self._objects, "Object already exists in the Logic, reparent failed." self._objects.append(object) def deparent_object(self, object): """parents Logic object to this server""" assert self._is_started, "Cannot reparent to Logic server. It was either killed already or never started in the first place." assert object in self._objects, "Object is not in the Logic, deparent failed." self._objects.remove(object) def schedule(self, originator, event, delay=None, on_event=None, *args, **kwargs): """schedules event on this Logic server""" assert self._is_started, "Cannot schedule event. It was either killed already or never started in the first place." event_data = [None, originator, event, 0, delay, on_event, args, kwargs] self._scheduled_events.append(event_data) def unschedule(self, originator, event): """unschedules event/events. If all is passed instead of event, it will unschedule ALL events owned by that originator. Otherwise, it will only unschedule first event (should be the only one anyways). """ assert self._is_started, "Cannot unschedule event. It was either killed already or never started in the first place." if event != "all": for ev in self._scheduled_events: if (ev[1] is originator) and (ev[2] is event): self._remove_event(ev) return else: for ev in self._scheduled_events: if (ev[1] is originator): self._remove_event(ev) def trigger(self, event, *args, **kwargs): """triggers event on all children of this Logic server""" assert self._is_started, "Cannot trigger an event. It was either killed already or never started in the first place." self._fire_event(event, *args, **kwargs) def pause(self): """pauses this Logic server""" assert self._is_started, "Cannot pause Logic server. It was either killed already or never started in the first place." self._paused = True def resume(self): """resumes this Logic server""" assert self._is_started, "Cannot run Logic server. It was either killed already or never started in the first place." self._paused = False def restart(self): """restarts this Logic server""" assert self._is_started, "Cannot run Logic server. It was either killed already or never started in the first place." self._paused = True def return_status(self): return self._is_started # Run method def run(self): self._is_started = True while self._game_running: self._tick() time.sleep(0.000001) self._is_started = False logic_server = LogicServer() def run_logic(): logic_server.start() def stop_logic(): logic_server.kill() def pause_logic(): logic_server.pause() def resume_logic(): logic_server.resume() def restart_logic(): logic_server.restart()