В очень плотно и сложно связанных системах, подобно описанной, хорошо работает паттерн ActorModel. Идея состоит в том, что ваш код разделен на огромную кучу крошечных подпрограмм, каждая из которых умеет
- выполнять атомарные действия
- отправлять сообщения другим акторам
- создавать новые акторы
Пользовательские запросы, таким образом, будут отправлять сообщение каким-то высокоуровневым акторам, которые в свою очередь будут отправлять новые сообщения, создавая граф действий. Любой процесс можно будет наглядно представить в виде такого графа.
Что касается вашего конкретного кейса, у меня создалось впечатление, что вас скорее интересует работа с единым хранилищем данных игровых объектов. Для этого тоже есть масса интересных решений, например Unidirectional Data Flow.
Хранение состояния игры в одном единственном месте, обращение к нему через прослойки-мапперы. Есть несколько вариантов реализации перехвата изменений - это может быть иммутабельное состояние, для которого достаточно будет считать дельту между старым и новым, публикуя изменения глобально, так чтобы участки программы, которым эти изменения интересны, сами их подхватывали, либо реактивное состояние, которое запоминает, кто к ней обращался за какими данными и уведомляет их о конкретных изменениях непосредственно в момент их применения.
Разумеется, для сложной игровой механики, совершенно необходимо писать и поддерживать юнит- и интеграционные тесты. С тестированием вы избежите огромной кучи багов, например пресловутого "если я это где-то забуду".
Но в любом из этих случаев, как грамотно сказал один программист: "Архитектуру легко придумать сложной", имея в виду, что нужно стремиться ее упрощать.