t.position = s.position
break
game.changed = True
+ game.changed_fovs = True
cmd_LOGIN.argtypes = 'string'
def cmd_BECOME_ADMIN(game, password, connection_id):
map_control = game.get_map(big_yx, 'control')
map_control[little_yx] = control_char
game.changed = True
+ game.changed_fovs = True
cmd_SET_TILE_CONTROL.argtypes = 'yx_tuple:nonneg char'
def cmd_THING_PROTECTION(game, thing_id, protection_char, connection_id):
if big_yx not in game.annotations:
game.annotations[big_yx] = {}
game.annotations[big_yx][little_yx] = msg
- game.changed = True
+ #game.changed = True
cmd_GOD_ANNOTATE.argtypes = 'yx_tuple yx_tuple:nonneg string'
def cmd_GOD_PORTAL(game, big_yx, little_yx, msg):
if big_yx not in game.portals:
game.portals[big_yx] = {}
game.portals[big_yx][little_yx] = msg
- game.changed = True
+ #game.changed = True
cmd_GOD_PORTAL.argtypes = 'yx_tuple yx_tuple:nonneg string'
def cmd_MAP_LINE(game, big_yx, y, line):
else:
game.things += [t_new]
game.changed = True
+ game.changed_fovs = True
cmd_THING.argtypes = 'yx_tuple yx_tuple:nonneg string:thing_type int:nonneg'
def cmd_THING_NAME(game, thing_id, name, pw, connection_id):
def __init__(self, save_file, *args, **kwargs):
super().__init__(*args, **kwargs)
self.changed = True
+ self.changed_fovs = True
self.io = GameIO(self, save_file)
self.tasks = {}
self.thing_types = {}
"""Send out game state data relevant to clients."""
# TODO: limit to connection_id if provided
+ print('DEBUG send_gamestate')
self.io.send('TURN ' + str(self.turn))
from plomrogue.mapping import FovMap
import multiprocessing
- pool = multiprocessing.Pool()
- players = []
c_ids = [c_id for c_id in self.sessions]
- for c_id in c_ids:
- players += [self.get_player(c_id)]
+ # Only recalc FOVs for players with ._fov = None
player_fovs = []
- for player in players:
- player.prepare_multiprocessible_fov_stencil()
+ player_fov_ids = []
+ for c_id in c_ids:
+ player = self.get_player(c_id)
+ if player._fov:
+ continue
+ player.prepare_multiprocessible_fov_stencil() #!
player_fovs += [player._fov]
- new_fovs = pool.map(FovMap.init_terrain, [fov for fov in player_fovs])
- for i in range(len(players)):
- players[i]._fov = new_fovs[i]
- pool.close()
- pool.join()
+ player_fov_ids += [player.id_]
+ if len(player_fovs) > 0:
+ print('DEBUG regenerating FOVs')
+ pool = multiprocessing.Pool()
+ new_fovs = pool.map(FovMap.init_terrain, [fov for fov in player_fovs]) #!
+ pool.close()
+ pool.join()
+ for i in range(len(player_fov_ids)):
+ id_ = player_fov_ids[i]
+ player = self.get_thing(id_)
+ player._fov = new_fovs[i]
for c_id in c_ids:
player = self.get_player(c_id)
- visible_terrain = player.fov_stencil_map()
self.io.send('FOV %s' % quote(player.fov_stencil.terrain), c_id)
self.io.send('MAP %s %s %s' % (self.get_map_geometry_shape(),
player.fov_stencil.geometry.size,
- quote(visible_terrain)), c_id)
- visible_control = player.fov_stencil_map('control')
- self.io.send('MAP_CONTROL %s' % quote(visible_control), c_id)
+ quote(player.visible_terrain)), c_id)
+ self.io.send('MAP_CONTROL %s' % quote(player.visible_control), c_id)
for t in [t for t in self.things if player.fov_test(*t.position)]:
target_yx = player.fov_stencil.target_yx(*t.position)
self.io.send('THING %s %s %s %s %s' % (target_yx, t.type_,
if hasattr(t, 'name'):
self.io.send('CHAT ' + quote(t.name + ' left the map.'))
self.things.remove(t)
+ self.changed_fovs = True
to_delete += [connection_id]
for connection_id in to_delete:
del self.sessions[connection_id]
for connection_id in [c_id for c_id in self.sessions
if self.sessions[c_id]['thing_id'] == t.id_]:
self.io.send('PLAY_ERROR ' + quote(str(e)), connection_id)
+ if self.changed_fovs:
+ for t in [t for t in self.things]:
+ t.invalidate_map_view()
if self.changed:
self.turn += 1
# send_gamestate() can be rather expensive, due to among other reasons
datetime.datetime.now() -self.send_gamestate_interval:
self.send_gamestate()
self.changed = False
+ self.changed_fovs = False
self.save()
self.last_send_gamestate = datetime.datetime.now()
if yxyx[0] not in obstacles:
obstacles[yxyx[0]] = []
obstacles[yxyx[0]] += [yxyx[1]]
- for yx in self:
+ for yx in self: # TODO: iter and source_yxyx expensive, cache earlier?
big_yx, little_yx = self.source_yxyx(yx)
if big_yx in obstacles and little_yx in obstacles[big_yx]:
self.source_map_segment += 'X'
self.thing.position = self.get_move_target()
if self.thing.carrying:
self.thing.carrying.position = self.thing.position
+ self.thing.game.changed_fovs = True
big_yx = self.thing.position[0]
little_yx = self.thing.position[1]
self.thing.game.maps[big_yx][little_yx] = self.args[0]
+ self.thing.game.changed_fovs = True
if not self.thing.game.can_do_tile_with_pw(*yxyx, self.args[0]):
continue
self.thing.game.maps[yxyx[0]][yxyx[1]] = '.'
+ self.thing.game.changed_fovs = True
to_pick_up = self.thing.game.get_thing(self.args[0])
to_pick_up.position = self.thing.position[:]
self.thing.carrying = to_pick_up
+ #self.thing.game.changed_fovs = True
t.accept(self.thing.carrying)
break
self.thing.carrying = None
+ #self.thing.game.changed_fovs = True
t.open()
else:
t.close()
+ self.thing.game.changed_fovs = True
self.thing.send_msg('RANDOM_COLORS')
self.thing.send_msg('CHAT "You are drunk now."')
self.thing.drunk = 10000
+ self.thing.game.changed_fovs = True
position=self.position)
self.game.things += [t]
self.game.changed = True
+ self.game.changed_fovs = True
self.playlist_index -= 1
if self.playlist_index < -1:
self.playlist_index = -1
+ self.game.changed = True
return ['removed song']
elif command == 'REWIND':
self.playlist_index = -1
msg += 'pick it up and then use "(un-)wear" on it!'
self.sound('BOTTLE DEPOSITOR', msg)
self.game.changed = True
+ self.game.changed_fovs = True
def accept(self):
self.bottle_counter += 1
super().__init__(*args, **kwargs)
self.next_task = [None]
self.task = None
+ self.invalidate_map_view()
+
+ def invalidate_map_view(self):
self._fov = None
+ self._visible_terrain = None
+ self._visible_control = None
def set_next_task(self, task_name, args=()):
task_class = self.game.tasks[task_name]
if self.drunk == 0:
for c_id in self.game.sessions:
if self.game.sessions[c_id]['thing_id'] == self.id_:
+ # TODO: refactor with self.send_msg
self.game.io.send('DEFAULT_COLORS', c_id)
self.game.io.send('CHAT "You sober up."', c_id)
+ self.game.changed_fovs = True
break
self.game.changed = True
- self._fov = None
if self.task is None:
self.task = self.get_next_task()
return
return True
return False
- def fov_stencil_map(self, map_type='normal'):
+ def fov_stencil_map(self, map_type):
visible_terrain = ''
for yx in self.fov_stencil:
if self.fov_stencil[yx] == '.':
visible_terrain += ' '
return visible_terrain
+ @property
+ def visible_terrain(self):
+ if self._visible_terrain:
+ return self._visible_terrain
+ self._visible_terrain = self.fov_stencil_map('normal')
+ return self._visible_terrain
+
+ @property
+ def visible_control(self):
+ if self._visible_control:
+ return self._visible_control
+ self._visible_control = self.fov_stencil_map('control')
+ return self._visible_control
+
class Thing_Player(ThingAnimate):