Add ChunkMap for better debugging
This commit is contained in:
parent
42d72422c6
commit
68c50f894b
5 changed files with 153 additions and 33 deletions
21
chunks.py
21
chunks.py
|
|
@ -58,7 +58,7 @@ class ChunkDiff():
|
||||||
return [s[i:i+CHUNK_WIDTH] for i in range(0, CHUNK_WIDTH*CHUNK_HEIGHT, CHUNK_WIDTH)]
|
return [s[i:i+CHUNK_WIDTH] for i in range(0, CHUNK_WIDTH*CHUNK_HEIGHT, CHUNK_WIDTH)]
|
||||||
|
|
||||||
def empty(self):
|
def empty(self):
|
||||||
return bool(self._chars)
|
return not bool(self._chars)
|
||||||
|
|
||||||
|
|
||||||
class Chunk():
|
class Chunk():
|
||||||
|
|
@ -96,8 +96,11 @@ class Chunk():
|
||||||
def get_changes(self):
|
def get_changes(self):
|
||||||
return self._modifications
|
return self._modifications
|
||||||
|
|
||||||
def touch(self):
|
def touch(self, now=None):
|
||||||
self.last_modified = time.time()
|
self.last_modified = now or time.time()
|
||||||
|
|
||||||
|
def age(self, now=None):
|
||||||
|
return self.last_modified - (now or time.time())
|
||||||
|
|
||||||
def draw_to(self, x, y, window):
|
def draw_to(self, x, y, window):
|
||||||
for line in self._content.combine(self._modifications).lines():
|
for line in self._content.combine(self._modifications).lines():
|
||||||
|
|
@ -136,9 +139,21 @@ class ChunkPool():
|
||||||
if not pos in self._chunks:
|
if not pos in self._chunks:
|
||||||
self.create(pos)
|
self.create(pos)
|
||||||
|
|
||||||
|
def unload(self, pos):
|
||||||
|
if pos in self._chunks:
|
||||||
|
del self._chunks[pos]
|
||||||
|
|
||||||
def load_list(self, coords):
|
def load_list(self, coords):
|
||||||
for pos in coords:
|
for pos in coords:
|
||||||
self.load(pos)
|
self.load(pos)
|
||||||
|
|
||||||
|
def unload_list(self, coords):
|
||||||
|
for pos in coords:
|
||||||
|
self.unload(pos)
|
||||||
|
|
||||||
|
def clean_up(self, except_for=[]):
|
||||||
|
coords = [pos for pos in self._chunks if not pos in except_for]
|
||||||
|
self.unload_list(coords)
|
||||||
|
|
||||||
def get(self, pos):
|
def get(self, pos):
|
||||||
return self._chunks.get(pos)
|
return self._chunks.get(pos)
|
||||||
|
|
|
||||||
23
client.py
23
client.py
|
|
@ -2,18 +2,19 @@ import curses
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
from maps import Map
|
from maps import Map, ChunkMap
|
||||||
from chunks import ChunkPool
|
from clientchunkpool import ClientChunkPool
|
||||||
|
|
||||||
# import fron chunks, maps, clientchunkpool
|
# import fron chunks, maps, clientchunkpool
|
||||||
|
|
||||||
class Client():
|
class Client():
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
self.stopping = False
|
self.stopping = False
|
||||||
|
self.chunkmap_active = False
|
||||||
|
|
||||||
self.address = address
|
self.address = address
|
||||||
self.drawevent = threading.Event()
|
self.drawevent = threading.Event()
|
||||||
self.pool = ChunkPool()
|
self.pool = ClientChunkPool()
|
||||||
#self.map_ = Map(sizex, sizey, self.pool)
|
#self.map_ = Map(sizex, sizey, self.pool)
|
||||||
#self.chunkmap = Chunkmap(sizex, sizey, self.pool) # size changeable by +/-?
|
#self.chunkmap = Chunkmap(sizex, sizey, self.pool) # size changeable by +/-?
|
||||||
|
|
||||||
|
|
@ -22,6 +23,7 @@ class Client():
|
||||||
def launch(self, stdscr):
|
def launch(self, stdscr):
|
||||||
sizey, sizex = stdscr.getmaxyx()
|
sizey, sizex = stdscr.getmaxyx()
|
||||||
self.map_ = Map(sizex, sizey, self.pool, self.drawevent)
|
self.map_ = Map(sizex, sizey, self.pool, self.drawevent)
|
||||||
|
self.chunkmap = ChunkMap(self.map_)
|
||||||
|
|
||||||
# start input thread
|
# start input thread
|
||||||
self.inputthread = threading.Thread(
|
self.inputthread = threading.Thread(
|
||||||
|
|
@ -37,6 +39,16 @@ class Client():
|
||||||
stdscr.noutrefresh()
|
stdscr.noutrefresh()
|
||||||
with self.map_ as m:
|
with self.map_ as m:
|
||||||
m.draw()
|
m.draw()
|
||||||
|
|
||||||
|
if self.chunkmap_active:
|
||||||
|
self.chunkmap.draw()
|
||||||
|
curses.curs_set(False)
|
||||||
|
else:
|
||||||
|
curses.curs_set(True)
|
||||||
|
|
||||||
|
#m.update_cursor()
|
||||||
|
#m.noutrefresh()
|
||||||
|
|
||||||
curses.doupdate()
|
curses.doupdate()
|
||||||
self.drawevent.clear()
|
self.drawevent.clear()
|
||||||
|
|
||||||
|
|
@ -45,7 +57,10 @@ class Client():
|
||||||
i = scr.getkey()
|
i = scr.getkey()
|
||||||
|
|
||||||
if i == "\x1b": self.stop()
|
if i == "\x1b": self.stop()
|
||||||
#elif i == "r": self.map_.redraw()
|
elif i == "KEY_F(2)":
|
||||||
|
self.chunkmap_active = not self.chunkmap_active
|
||||||
|
self.drawevent.set()
|
||||||
|
elif i == "KEY_F(5)": self.map_.redraw()
|
||||||
# normal cursor movement
|
# normal cursor movement
|
||||||
elif i == "KEY_UP": self.map_.move_cursor(0, -1)
|
elif i == "KEY_UP": self.map_.move_cursor(0, -1)
|
||||||
elif i == "KEY_DOWN": self.map_.move_cursor(0, 1)
|
elif i == "KEY_DOWN": self.map_.move_cursor(0, 1)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
from .chunks.py import ChunkPool
|
from chunks import ChunkPool
|
||||||
|
|
||||||
class ClientChunkPool(ChunkPool):
|
class ClientChunkPool(ChunkPool):
|
||||||
"""
|
"""
|
||||||
A ChunkPool that requests/loads chunks from a client.
|
A ChunkPool that requests/loads chunks from a client.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.max_age = 10 #s
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
124
maps.py
124
maps.py
|
|
@ -1,3 +1,4 @@
|
||||||
|
from collections import namedtuple
|
||||||
import curses
|
import curses
|
||||||
import math
|
import math
|
||||||
import threading
|
import threading
|
||||||
|
|
@ -29,6 +30,9 @@ class Map():
|
||||||
self._pad = curses.newpad(5, 5)
|
self._pad = curses.newpad(5, 5)
|
||||||
self.resize(width, height)
|
self.resize(width, height)
|
||||||
|
|
||||||
|
if curses.has_colors():
|
||||||
|
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) # chunk not loaded
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
return self
|
return self
|
||||||
|
|
@ -51,14 +55,18 @@ class Map():
|
||||||
else:
|
else:
|
||||||
self.draw_empty_to(x*CHUNK_WIDTH, y*CHUNK_HEIGHT)
|
self.draw_empty_to(x*CHUNK_WIDTH, y*CHUNK_HEIGHT)
|
||||||
|
|
||||||
# set cursor position in world
|
self.update_cursor()
|
||||||
|
self.noutrefresh()
|
||||||
|
|
||||||
|
def noutrefresh(self):
|
||||||
|
self._pad.noutrefresh(inchunky(self.worldy), inchunkx(self.worldx), 0, 0, self.height-1, self.width-1)
|
||||||
|
|
||||||
|
def update_cursor(self):
|
||||||
self._pad.move(
|
self._pad.move(
|
||||||
self.cursory - chunky(self.worldy)*CHUNK_HEIGHT,
|
self.cursory - chunky(self.worldy)*CHUNK_HEIGHT,
|
||||||
self.cursorx - chunkx(self.worldx)*CHUNK_WIDTH
|
self.cursorx - chunkx(self.worldx)*CHUNK_WIDTH
|
||||||
)
|
)
|
||||||
|
|
||||||
self._pad.noutrefresh(inchunky(self.worldy), inchunkx(self.worldx), 0, 0, self.height-1, self.width-1)
|
|
||||||
|
|
||||||
def draw_empty_to(self, x, y):
|
def draw_empty_to(self, x, y):
|
||||||
if curses.has_colors():
|
if curses.has_colors():
|
||||||
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
||||||
|
|
@ -71,7 +79,9 @@ class Map():
|
||||||
|
|
||||||
def load_visible(self):
|
def load_visible(self):
|
||||||
with self.chunkpool as pool:
|
with self.chunkpool as pool:
|
||||||
pool.load_list(self.visible_chunk_coords())
|
coords = self.visible_chunk_coords()
|
||||||
|
pool.load_list(coords)
|
||||||
|
#pool.clean_up(except_for=coords)
|
||||||
|
|
||||||
self.drawevent.set()
|
self.drawevent.set()
|
||||||
|
|
||||||
|
|
@ -103,9 +113,8 @@ class Map():
|
||||||
def write(self, char):
|
def write(self, char):
|
||||||
with self.chunkpool as pool:
|
with self.chunkpool as pool:
|
||||||
chunk = pool.get(Position(chunkx(self.cursorx), chunky(self.cursory)))
|
chunk = pool.get(Position(chunkx(self.cursorx), chunky(self.cursory)))
|
||||||
if not chunk:
|
|
||||||
chunk = pool.create(Position(chunkx(self.cursorx), chunky(self.cursory)))
|
|
||||||
|
|
||||||
|
if chunk:
|
||||||
chunk.set(inchunkx(self.cursorx), inchunky(self.cursory), char)
|
chunk.set(inchunkx(self.cursorx), inchunky(self.cursory), char)
|
||||||
|
|
||||||
self.move_cursor(1, 0, False)
|
self.move_cursor(1, 0, False)
|
||||||
|
|
@ -178,6 +187,7 @@ class Map():
|
||||||
|
|
||||||
#self.load_visible()
|
#self.load_visible()
|
||||||
|
|
||||||
|
ChunkStyle = namedtuple("ChunkStyle", "string color")
|
||||||
|
|
||||||
class ChunkMap():
|
class ChunkMap():
|
||||||
"""
|
"""
|
||||||
|
|
@ -185,17 +195,93 @@ class ChunkMap():
|
||||||
Might show additional details too (i.e. if a chunk has been modified).
|
Might show additional details too (i.e. if a chunk has been modified).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, chunkpool):
|
styles = {
|
||||||
self.cpool = chunkpool
|
"empty": ChunkStyle("()", 2),
|
||||||
#
|
"normal": ChunkStyle("[]", 3),
|
||||||
# def draw(self):
|
"old": ChunkStyle("{}", 4),
|
||||||
# pass
|
"visible": ChunkStyle("##", 5),
|
||||||
#
|
"modified": ChunkStyle("!!", 6),
|
||||||
# def resize(self, size):
|
}
|
||||||
# pass
|
|
||||||
#
|
|
||||||
def move(self, x, y, corner):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def toggle(self):
|
def __init__(self, map_):
|
||||||
pass
|
self.map_ = map_
|
||||||
|
self.chunkpool = map_.chunkpool
|
||||||
|
self.corner = "ur" # upper right
|
||||||
|
|
||||||
|
#minx, maxx, miny, maxy = self.get_min_max()
|
||||||
|
#self.win = curses.newwin(maxy-miny+2, maxx-minx+2)
|
||||||
|
self.win = curses.newwin(2, 2)
|
||||||
|
|
||||||
|
if curses.has_colors():
|
||||||
|
curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_BLUE) # empty chunk
|
||||||
|
curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) # chunk
|
||||||
|
curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_YELLOW) # old chunk
|
||||||
|
curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_GREEN) # visible chunk
|
||||||
|
curses.init_pair(6, curses.COLOR_BLACK, curses.COLOR_RED) # modified chunk
|
||||||
|
|
||||||
|
def update_size(self, sizex, sizey):
|
||||||
|
winy, winx = self.win.getmaxyx()
|
||||||
|
if winx != 2*sizex + 4 or winy != sizey + 3:
|
||||||
|
self.win.resize(sizey + 3, 2*sizex + 4)
|
||||||
|
sys.stderr.write("{}\n".format(self.win.getmaxyx()))
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
with self.chunkpool as pool:
|
||||||
|
minx, maxx, miny, maxy = self.get_min_max(pool)
|
||||||
|
sizex = maxx - minx
|
||||||
|
sizey = maxy - miny
|
||||||
|
sys.stderr.write("{} {} {} {} | {} {}\n".format(minx, maxx, miny, maxy, sizex, sizey))
|
||||||
|
self.update_size(sizex, sizey)
|
||||||
|
|
||||||
|
self.win.erase()
|
||||||
|
self.win.border()
|
||||||
|
|
||||||
|
for pos, chunk in pool._chunks.items():
|
||||||
|
tp = self.type_of(pos, chunk)
|
||||||
|
sys.stderr.write(tp + "\n")
|
||||||
|
sys.stderr.write("{} {}\n".format(pos.x - minx + 1, pos.y - miny + 1))
|
||||||
|
if curses.has_colors():
|
||||||
|
self.win.addstr(
|
||||||
|
pos.y - miny + 1,
|
||||||
|
2*(pos.x - minx) + 1,
|
||||||
|
" ",
|
||||||
|
curses.color_pair(self.styles[tp].color)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.win.addstr(
|
||||||
|
pos.y - miny + 1,
|
||||||
|
2*(pos.x - minx) + 1,
|
||||||
|
self.styles[tp].string
|
||||||
|
)
|
||||||
|
|
||||||
|
self.win.noutrefresh()
|
||||||
|
|
||||||
|
def get_min_max(self, pool):
|
||||||
|
minx = min(pos.x for pos in pool._chunks)
|
||||||
|
maxx = max(pos.x for pos in pool._chunks)
|
||||||
|
miny = min(pos.y for pos in pool._chunks)
|
||||||
|
maxy = max(pos.y for pos in pool._chunks)
|
||||||
|
|
||||||
|
return minx, maxx, miny, maxy
|
||||||
|
|
||||||
|
def get_size(self):
|
||||||
|
minx, maxx, miny, maxy = self.get_min_max()
|
||||||
|
return maxx - minx, maxy - miny
|
||||||
|
|
||||||
|
def type_of(self, pos, chunk):
|
||||||
|
if chunk.modified():
|
||||||
|
return "modified"
|
||||||
|
|
||||||
|
if pos in self.map_.visible_chunk_coords():
|
||||||
|
return "visible"
|
||||||
|
|
||||||
|
if chunk.age() > self.chunkpool.max_age:
|
||||||
|
return "old"
|
||||||
|
|
||||||
|
if chunk.empty():
|
||||||
|
return "empty"
|
||||||
|
|
||||||
|
return "normal"
|
||||||
|
|
||||||
|
#def move(self, x, y, corner):
|
||||||
|
#pass
|
||||||
|
|
|
||||||
4
utils.py
4
utils.py
|
|
@ -2,8 +2,8 @@ from collections import namedtuple
|
||||||
|
|
||||||
Position = namedtuple("Position", "x y")
|
Position = namedtuple("Position", "x y")
|
||||||
|
|
||||||
CHUNK_WIDTH = 16
|
CHUNK_WIDTH = 64
|
||||||
CHUNK_HEIGHT = 8
|
CHUNK_HEIGHT = 32
|
||||||
|
|
||||||
def chunkx(value):
|
def chunkx(value):
|
||||||
return value//CHUNK_WIDTH
|
return value//CHUNK_WIDTH
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue