1use std::fmt::{self, Display, Formatter};
2use std::hash::{Hash, Hasher};
3use std::io::{self, Cursor};
4use std::{
5 collections::{HashMap, HashSet},
6 fmt::Debug,
7};
8
9use azalea_block::BlockState;
10use azalea_block::fluid_state::FluidState;
11use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
12use azalea_core::position::{BlockPos, ChunkPos};
13use azalea_core::registry_holder::RegistryHolder;
14use bevy_ecs::{component::Component, entity::Entity};
15use derive_more::{Deref, DerefMut};
16use nohash_hasher::IntMap;
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19
20use crate::{ChunkStorage, PartialChunkStorage};
21
22pub struct PartialInstance {
31 pub chunks: PartialChunkStorage,
32 pub entity_infos: PartialEntityInfos,
35}
36
37impl PartialInstance {
38 pub fn new(chunk_radius: u32, owner_entity: Option<Entity>) -> Self {
39 PartialInstance {
40 chunks: PartialChunkStorage::new(chunk_radius),
41 entity_infos: PartialEntityInfos::new(owner_entity),
42 }
43 }
44
45 pub fn reset(&mut self) {
48 self.chunks = PartialChunkStorage::new(self.chunks.chunk_radius);
49 }
50}
51
52#[derive(Component, Copy, Clone, Debug, Default, PartialEq, Eq, Deref, DerefMut)]
69#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
70pub struct MinecraftEntityId(pub i32);
71
72impl Hash for MinecraftEntityId {
73 fn hash<H: Hasher>(&self, hasher: &mut H) {
74 hasher.write_i32(self.0);
75 }
76}
77impl nohash_hasher::IsEnabled for MinecraftEntityId {}
78
79impl AzaleaRead for MinecraftEntityId {
82 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
83 i32::azalea_read(buf).map(MinecraftEntityId)
84 }
85}
86impl AzaleaWrite for MinecraftEntityId {
87 fn azalea_write(&self, buf: &mut impl io::Write) -> Result<(), io::Error> {
88 i32::azalea_write(&self.0, buf)
89 }
90}
91impl AzaleaReadVar for MinecraftEntityId {
92 fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
93 i32::azalea_read_var(buf).map(MinecraftEntityId)
94 }
95}
96impl AzaleaWriteVar for MinecraftEntityId {
97 fn azalea_write_var(&self, buf: &mut impl io::Write) -> Result<(), io::Error> {
98 i32::azalea_write_var(&self.0, buf)
99 }
100}
101impl Display for MinecraftEntityId {
102 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
103 write!(f, "eid({})", self.0)
104 }
105}
106impl From<i32> for MinecraftEntityId {
107 fn from(id: i32) -> Self {
108 Self(id)
109 }
110}
111impl From<u32> for MinecraftEntityId {
112 fn from(id: u32) -> Self {
113 Self(id as i32)
114 }
115}
116
117#[derive(Debug, Default)]
120pub struct PartialEntityInfos {
121 pub owner_entity: Option<Entity>,
127 pub updates_received: IntMap<MinecraftEntityId, u32>,
133}
134
135impl PartialEntityInfos {
136 pub fn new(owner_entity: Option<Entity>) -> Self {
137 Self {
138 owner_entity,
139 updates_received: IntMap::default(),
140 }
141 }
142}
143
144#[derive(Default, Debug)]
147pub struct Instance {
148 pub chunks: ChunkStorage,
149
150 pub entities_by_chunk: HashMap<ChunkPos, HashSet<Entity>>,
152
153 pub entity_by_id: IntMap<MinecraftEntityId, Entity>,
160
161 pub registries: RegistryHolder,
162}
163
164impl Instance {
165 pub fn get_block_state(&self, pos: &BlockPos) -> Option<BlockState> {
166 self.chunks.get_block_state(pos)
167 }
168
169 pub fn get_fluid_state(&self, pos: &BlockPos) -> Option<FluidState> {
170 self.chunks.get_block_state(pos).map(FluidState::from)
171 }
172
173 pub fn set_block_state(&self, pos: &BlockPos, state: BlockState) -> Option<BlockState> {
174 self.chunks.set_block_state(pos, state)
175 }
176}
177
178impl Debug for PartialInstance {
179 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
180 f.debug_struct("PartialInstance")
181 .field("chunks", &self.chunks)
182 .field("entity_infos", &self.entity_infos)
183 .finish()
184 }
185}
186
187impl Default for PartialInstance {
188 fn default() -> Self {
191 let chunk_storage = PartialChunkStorage::default();
192 let entity_storage = PartialEntityInfos::default();
193 Self {
194 chunks: chunk_storage,
195 entity_infos: entity_storage,
196 }
197 }
198}
199
200impl From<ChunkStorage> for Instance {
201 fn from(chunks: ChunkStorage) -> Self {
204 Self {
205 chunks,
206 entities_by_chunk: HashMap::new(),
207 entity_by_id: IntMap::default(),
208 registries: RegistryHolder::default(),
209 }
210 }
211}