diff --git a/chunks.py b/chunks.py index 2d1aa3d..934397e 100644 --- a/chunks.py +++ b/chunks.py @@ -1,3 +1,4 @@ +import string import threading import time from utils import CHUNK_WIDTH, CHUNK_HEIGHT, Position @@ -65,6 +66,20 @@ class ChunkDiff(): def empty(self): return not bool(self._chars) + + def legitimate(self): + for i, char in self._chars.items(): + if not (isinstance(char, str) and len(char) == 1 and ord(char) > 31 and (char not in string.whitespace or char == " ")): + return False + else: + return True + + def diff(self, chunk): + diffs = {} + for pos, char in self._chars.items(): + diffs[pos] = chunk._chars.get(pos, " ") + + return ChunkDiff.from_dict(diffs) def jsonify_changes(changes): dchanges = [] diff --git a/client.py b/client.py index 587bcfc..4216acb 100644 --- a/client.py +++ b/client.py @@ -116,7 +116,7 @@ class Client(): elif i == "\n": self.map_.newline() #elif i in string.digits + string.ascii_letters + string.punctuation + " ": #self.map_.write(i) - elif isinstance(i, str) and len(i) == 1 and (i not in string.whitespace or i == " "): + elif isinstance(i, str) and len(i) == 1 and ord(i) > 31 and (i not in string.whitespace or i == " "): self.map_.write(i) def connection_thread(self): diff --git a/server.py b/server.py index b1c3a5c..574196a 100644 --- a/server.py +++ b/server.py @@ -35,12 +35,41 @@ class WotServer(WebSocket): def handle_save_changes(self, dchanges): changes = dejsonify_changes(dchanges) - with pool: - pool.apply_changes(changes) + # check whether changes are correct (exclude certain characters) + # if not correct, send corrections them back to sender + legitimate_changes = [] + illegitimate_changes = [] + for chunk in changes: + if chunk[1].legitimate(): + legitimate_changes.append(chunk) + else: + illegitimate_changes.append(chunk) - for client in clients: - if client: - client.send_changes(changes) + if legitimate_changes: + with pool: + pool.apply_changes(legitimate_changes) + + for client in clients: + if client: + client.send_changes(legitimate_changes) + + if illegitimate_changes: + reverse_changes = self.reverse_changes(changes) + reverse_dchanges = jsonify_changes(reverse_changes) + message = {"type": "apply-changes", "data": reverse_dchanges} + self.sendMessage(json.dumps(message)) + + def reverse_changes(self, changes): + with pool: + reverse_changes = [] + for chunk in changes: + pos = chunk[0] + change = chunk[1] + real_chunk = pool.get(pos) or pool.create(pos) + reverse_change = change.diff(real_chunk.as_diff()) + reverse_changes.append((pos, reverse_change)) + + return reverse_changes def send_changes(self, changes): changes = [chunk for chunk in changes if chunk[0] in self.loaded_chunks]