From 38ab48d6f86942aecaf45474c235aa68b65b1160 Mon Sep 17 00:00:00 2001 From: Joscha Date: Thu, 6 Apr 2017 12:53:20 +0000 Subject: [PATCH] Add ability to write on map Todo: - make ChunkDiffs contain deletions - inserting a " " counts as deletion on chunk level - allow for more unicode characters! ^^ (only harmless ones though - no newline or control characters etc.) --- chunks.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++---- client.py | 4 +++ maps.py | 16 ++++++--- 3 files changed, 107 insertions(+), 10 deletions(-) diff --git a/chunks.py b/chunks.py index 80bf976..0154a66 100644 --- a/chunks.py +++ b/chunks.py @@ -1,12 +1,59 @@ import threading +import time +from utils import CHUNK_WIDTH, CHUNK_HEIGHT class ChunkDiff(): """ Represents differences between two chunks (changes to be made to a chunk). Can be used to transform a chunk into another chunk. + + Todo: Implement delete diff """ - pass + @classmethod + def combine(cls, diff_a, diff_b): + diff = cls() + diff.apply(diff_a) + diff.apply(diff_b) + return diff + + def __init__(self): + self._chars = {} + + @classmethod + def from_dict(cls, d): + diff = cls() + diff._chars = d + return diff + #self._chars = d.copy() + + def copy(self): + return ChunkDiff.from_dict(self.to_dict().copy()) + + def combine(self, diff): + newdiff = self.copy() + newdiff.apply(diff) + return newdiff + + def to_dict(self): + return self._chars + #return self._chars.copy() + + def set(self, x, y, character): + self._chars[x+y*CHUNK_WIDTH] = character + + def delete(self, x, y): + del self._chars[x+y*CHUNK_WIDTH] + + def apply(self, diff): + for i, c in diff._chars.items(): + self._chars[i] = c + + def lines(self): + d = self._chars + s = "".join(d.get(i, " ") for i in range(CHUNK_WIDTH*CHUNK_HEIGHT)) + return [s[i:i+CHUNK_WIDTH] for i in range(0, CHUNK_WIDTH*CHUNK_HEIGHT, CHUNK_WIDTH)] + class Chunk(): """ @@ -17,7 +64,35 @@ class Chunk(): - from accumulated changes """ - pass + def __init__(self): + self._content = ChunkDiff() + self._modifications = ChunkDiff() + + self.touch() + + def set(self, x, y, character): + self._modifications.set(x, y, character) + + def delete(self, x, y): + self._modifications.delete(x, y) + + def commit_changes(self): + self._content.apply(self._modifications) + self._modifications = ChunkDiff() + + def drop_changes(self): + self._modifications = ChunkDiff() + + def get_changes(self): + return self._modifications + + def touch(self): + self.last_modified = time.time() + + def draw_to(self, x, y, window): + for line in self._content.combine(self._modifications).lines(): + window.addstr(y, x, line) + y += 1 class ChunkPool(): """ @@ -27,6 +102,7 @@ class ChunkPool(): """ def __init__(self): + self._chunks = {} self._lock = threading.RLock() def __enter__(self): @@ -36,8 +112,17 @@ class ChunkPool(): def __exit__(self, type, value, tb): self._lock.release() - def load_list(self, coords): - pass + def create(self, pos): + self._chunks[pos] = Chunk() + return self._chunks[pos] - def get(self, x, y): - pass + def load(self, pos): + if not pos in self._chunks: + self.create(pos) + + def load_list(self, coords): + for pos in coords: + self.load(pos) + + def get(self, pos): + return self._chunks.get(pos) diff --git a/client.py b/client.py index 72e60be..85b6d5a 100644 --- a/client.py +++ b/client.py @@ -1,4 +1,5 @@ import curses +import string import sys import threading from maps import Map @@ -60,6 +61,9 @@ class Client(): elif i == "kDN5": self.map_.scroll(0, 10) elif i == "kLFT5": self.map_.scroll(-20, 0) elif i == "kRIT5": self.map_.scroll(20, 0) + # edit world + elif i in string.digits + string.ascii_letters + string.punctuation + " ": + self.map_.write(i) else: sys.stdout.write(repr(i) + "\n") diff --git a/maps.py b/maps.py index 1915d5c..4a2970b 100644 --- a/maps.py +++ b/maps.py @@ -43,7 +43,7 @@ class Map(): with self.chunkpool as pool: for x in range(chunkx(self.width) + 2): # +2, not +1, or there will be empty gaps for y in range(chunky(self.height) + 2): # in the bottom and right borders - chunk = pool.get(x+chunkx(self.worldx), y+chunky(self.worldy)) + chunk = pool.get(Position(x+chunkx(self.worldx), y+chunky(self.worldy))) if chunk: chunk.draw_to(x*CHUNK_WIDTH, y*CHUNK_HEIGHT, self._pad) else: @@ -97,14 +97,22 @@ class Map(): def write(self, char): with self.chunkpool as pool: - chunk = pool.get(chunkx(self.cursorx), chunky(self.cursory)) + chunk = pool.get(Position(chunkx(self.cursorx), chunky(self.cursory))) if not chunk: - chunk = pool.create(chunkx(self.cursorx), chunky(self.cursory)) + chunk = pool.create(Position(chunkx(self.cursorx), chunky(self.cursory))) - chunk.setch(inchunkx(self.cursorx), inchunky(self.cursory), char) + chunk.set(inchunkx(self.cursorx), inchunky(self.cursory), char) self.move_cursor(1, 0) + def delete(self): + with self.chunkpool as pool: + chunk = pool.get(Position(chunkx(self.cursorx-1), chunky(self.cursory))) + if chunk: + chunk.delete(inchunkx(self.cursorx-1), inchunky(self.cursory), char) + + self.move_cursor(-1, 0) + def move_cursor(self, dx, dy): self.cursorx += dx self.cursory += dy