Clear stale sign data when signs break
This commit is contained in:
@@ -283,11 +283,21 @@ class WorldState:
|
|||||||
return chunk.get_block_at(floor(x), floor(y), floor(z))
|
return chunk.get_block_at(floor(x), floor(y), floor(z))
|
||||||
|
|
||||||
def set_block_entity(self, position, entity_type, data):
|
def set_block_entity(self, position, entity_type, data):
|
||||||
self.block_entities[tuple(position)] = {
|
position = tuple(position)
|
||||||
|
if data is None:
|
||||||
|
self.block_entities.pop(position, None)
|
||||||
|
return
|
||||||
|
self.block_entities[position] = {
|
||||||
'type': entity_type,
|
'type': entity_type,
|
||||||
'data': nbt_plain(data),
|
'data': nbt_plain(data),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_sign_state(block_state_id):
|
||||||
|
from mosfet.info import blocks
|
||||||
|
name = blocks.BLOCKS.get(block_state_id)
|
||||||
|
return name is not None and name.endswith('_sign')
|
||||||
|
|
||||||
def set_block_at(self, x, y, z, block_state_id):
|
def set_block_at(self, x, y, z, block_state_id):
|
||||||
x, y, z = floor(x), floor(y), floor(z)
|
x, y, z = floor(x), floor(y), floor(z)
|
||||||
chunk = self.get_chunk(floor(x / 16), floor(z / 16))
|
chunk = self.get_chunk(floor(x / 16), floor(z / 16))
|
||||||
@@ -297,6 +307,9 @@ class WorldState:
|
|||||||
pos = (x, y, z)
|
pos = (x, y, z)
|
||||||
if previous in self.indexed_ids:
|
if previous in self.indexed_ids:
|
||||||
self.index.get(previous, set()).discard(pos)
|
self.index.get(previous, set()).discard(pos)
|
||||||
|
if (self._is_sign_state(previous) and
|
||||||
|
not self._is_sign_state(block_state_id)):
|
||||||
|
self.block_entities.pop(pos, None)
|
||||||
if block_state_id in self.indexed_ids:
|
if block_state_id in self.indexed_ids:
|
||||||
self.index.setdefault(block_state_id, set()).add(pos)
|
self.index.setdefault(block_state_id, set()).add(pos)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ class World:
|
|||||||
def block_at(self, x, y, z):
|
def block_at(self, x, y, z):
|
||||||
return self.g.chunks.get_block_at(x, y, z)
|
return self.g.chunks.get_block_at(x, y, z)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_sign_state(state_id):
|
||||||
|
name = blocks.BLOCKS.get(state_id)
|
||||||
|
return name is not None and name.endswith('_sign')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sign_component_text(value):
|
def _sign_component_text(value):
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -58,6 +63,12 @@ class World:
|
|||||||
for position, entity in self.g.chunks.block_entities.items():
|
for position, entity in self.g.chunks.block_entities.items():
|
||||||
if utils.phyp(center, position) > distance:
|
if utils.phyp(center, position) > distance:
|
||||||
continue
|
continue
|
||||||
|
get_block_at = getattr(self.g.chunks, 'get_block_at', None)
|
||||||
|
if callable(get_block_at):
|
||||||
|
state_id = get_block_at(*position)
|
||||||
|
if (state_id is not None and
|
||||||
|
not self._is_sign_state(state_id)):
|
||||||
|
continue
|
||||||
data = entity.get('data') or {}
|
data = entity.get('data') or {}
|
||||||
for side in ('front', 'back'):
|
for side in ('front', 'back'):
|
||||||
text_data = data.get(side + '_text')
|
text_data = data.get(side + '_text')
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from unittest.mock import patch
|
|||||||
from munch import Munch
|
from munch import Munch
|
||||||
|
|
||||||
from mosfet.commands import Commands
|
from mosfet.commands import Commands
|
||||||
|
from mosfet.info import blocks
|
||||||
from mosfet.protocol.managers import EntityManager, WorldState
|
from mosfet.protocol.managers import EntityManager, WorldState
|
||||||
from mosfet.world import World
|
from mosfet.world import World
|
||||||
|
|
||||||
@@ -45,6 +46,47 @@ class SignReadingTests(unittest.TestCase):
|
|||||||
signs = World(Munch(chunks=chunks)).find_signs((4, 65, -2), 1)
|
signs = World(Munch(chunks=chunks)).find_signs((4, 65, -2), 1)
|
||||||
self.assertEqual(signs[0]['lines'], ('Farm', '', '', ''))
|
self.assertEqual(signs[0]['lines'], ('Farm', '', '', ''))
|
||||||
|
|
||||||
|
def test_broken_sign_block_update_removes_cached_sign_entity(self):
|
||||||
|
position = (4, 65, -2)
|
||||||
|
sign_state = blocks.MCD_BLOCKS['oak_wall_sign']['minStateId']
|
||||||
|
|
||||||
|
class FakeColumn:
|
||||||
|
def __init__(self):
|
||||||
|
self.states = {}
|
||||||
|
|
||||||
|
def get_block_at(self, x, y, z):
|
||||||
|
return self.states.get((x, y, z), blocks.AIR)
|
||||||
|
|
||||||
|
def set_block_at(self, x, y, z, state_id):
|
||||||
|
previous = self.get_block_at(x, y, z)
|
||||||
|
self.states[(x, y, z)] = state_id
|
||||||
|
return previous
|
||||||
|
|
||||||
|
chunks = WorldState()
|
||||||
|
chunks.chunks[(0, -1)] = FakeColumn()
|
||||||
|
chunks.set_block_at(*position, sign_state)
|
||||||
|
chunks.set_block_entity(position, 7, {
|
||||||
|
'front_text': {'messages': ['mosfet1 stay', 'within 8 square', '', '']},
|
||||||
|
})
|
||||||
|
world = World(Munch(chunks=chunks))
|
||||||
|
|
||||||
|
self.assertEqual(len(world.find_signs(position, 1)), 1)
|
||||||
|
chunks.set_block_at(*position, blocks.AIR)
|
||||||
|
|
||||||
|
self.assertNotIn(position, chunks.block_entities)
|
||||||
|
self.assertEqual(world.find_signs(position, 1), [])
|
||||||
|
|
||||||
|
def test_sign_search_ignores_stale_block_entity_for_non_sign_block(self):
|
||||||
|
position = (4, 65, -2)
|
||||||
|
chunks = Munch(
|
||||||
|
block_entities={position: {'data': {'front_text': {
|
||||||
|
'messages': ['mosfet1 stay', 'within 8 square', '', ''],
|
||||||
|
}}}},
|
||||||
|
get_block_at=lambda *_position: blocks.AIR,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(World(Munch(chunks=chunks)).find_signs(position, 1), [])
|
||||||
|
|
||||||
def test_group_and_individual_sign_addresses(self):
|
def test_group_and_individual_sign_addresses(self):
|
||||||
group_world = World(Munch(chunks=Munch(block_entities={
|
group_world = World(Munch(chunks=Munch(block_entities={
|
||||||
(0, 64, 0): {'data': {'front_text': {'messages': [
|
(0, 64, 0): {'data': {'front_text': {'messages': [
|
||||||
|
|||||||
Reference in New Issue
Block a user