commit
72f5fdf619
|
@ -11,7 +11,7 @@ jobs:
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
# TODO: refactor toolchain version
|
# TODO: refactor toolchain version
|
||||||
toolchain: 1.49.0
|
toolchain: 1.53.0
|
||||||
components: clippy, rustfmt
|
components: clippy, rustfmt
|
||||||
default: true
|
default: true
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
@ -49,7 +49,7 @@ jobs:
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: 1.49.0
|
toolchain: 1.53.0
|
||||||
components: clippy, rustfmt
|
components: clippy, rustfmt
|
||||||
default: true
|
default: true
|
||||||
- name: Build binary
|
- name: Build binary
|
||||||
|
@ -83,7 +83,7 @@ jobs:
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: 1.49.0
|
toolchain: 1.53.0
|
||||||
components: clippy, rustfmt
|
components: clippy, rustfmt
|
||||||
default: true
|
default: true
|
||||||
- name: Build binary
|
- name: Build binary
|
||||||
|
@ -128,7 +128,7 @@ jobs:
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
# TODO: refactor toolchain version
|
# TODO: refactor toolchain version
|
||||||
toolchain: 1.49.0
|
toolchain: 1.53.0
|
||||||
components: clippy, rustfmt
|
components: clippy, rustfmt
|
||||||
default: true
|
default: true
|
||||||
- name: Install wasm-pack
|
- name: Install wasm-pack
|
||||||
|
|
|
@ -3,6 +3,7 @@ name = "stevenarella"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
authors = [ "Thinkofdeath <thinkofdeath@spigotmc.org>", "iceiix <ice_ix@protonmail.ch>" ]
|
authors = [ "Thinkofdeath <thinkofdeath@spigotmc.org>", "iceiix <ice_ix@protonmail.ch>" ]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
resolver = "2"
|
||||||
description = "Multi-protocol multi-platform Minecraft-compatible client"
|
description = "Multi-protocol multi-platform Minecraft-compatible client"
|
||||||
repository = "https://github.com/iceiix/stevenarella"
|
repository = "https://github.com/iceiix/stevenarella"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
|
@ -19,6 +20,7 @@ crate-type = ["cdylib", "rlib"]
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
split-debuginfo = "unpacked"
|
||||||
# Steven runs horrendously slow with no optimizations, and often freezes.
|
# Steven runs horrendously slow with no optimizations, and often freezes.
|
||||||
# However, building with full -O3 optimizations takes too long for a debug build.
|
# However, building with full -O3 optimizations takes too long for a debug build.
|
||||||
# Use an -O1 optimization level strikes a good compromise between build and program performance.
|
# Use an -O1 optimization level strikes a good compromise between build and program performance.
|
||||||
|
|
|
@ -67,7 +67,7 @@ from [GitHub Actions](https://actions-badge.atrox.dev/iceiix/stevenarella/goto?r
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
Requires Rust stable version 1.49.0 or newer.
|
Requires Rust stable version 1.53.0 or newer.
|
||||||
|
|
||||||
**Debian/Ubuntu**
|
**Debian/Ubuntu**
|
||||||
|
|
||||||
|
|
|
@ -5883,47 +5883,53 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_burn<W: WorldAccess>(world: &W, pos: Position) -> bool {
|
fn can_burn<W: WorldAccess>(world: &W, pos: Position) -> bool {
|
||||||
matches!(world.get_block(pos), Block::Planks { .. }
|
matches!(
|
||||||
| Block::DoubleWoodenSlab { .. }
|
world.get_block(pos),
|
||||||
| Block::WoodenSlab { .. }
|
Block::Planks { .. }
|
||||||
| Block::FenceGate { .. }
|
| Block::DoubleWoodenSlab { .. }
|
||||||
| Block::SpruceFenceGate { .. }
|
| Block::WoodenSlab { .. }
|
||||||
| Block::BirchFenceGate { .. }
|
| Block::FenceGate { .. }
|
||||||
| Block::JungleFenceGate { .. }
|
| Block::SpruceFenceGate { .. }
|
||||||
| Block::DarkOakFenceGate { .. }
|
| Block::BirchFenceGate { .. }
|
||||||
| Block::AcaciaFenceGate { .. }
|
| Block::JungleFenceGate { .. }
|
||||||
| Block::Fence { .. }
|
| Block::DarkOakFenceGate { .. }
|
||||||
| Block::SpruceFence { .. }
|
| Block::AcaciaFenceGate { .. }
|
||||||
| Block::BirchFence { .. }
|
| Block::Fence { .. }
|
||||||
| Block::JungleFence { .. }
|
| Block::SpruceFence { .. }
|
||||||
| Block::DarkOakFence { .. }
|
| Block::BirchFence { .. }
|
||||||
| Block::AcaciaFence { .. }
|
| Block::JungleFence { .. }
|
||||||
| Block::OakStairs { .. }
|
| Block::DarkOakFence { .. }
|
||||||
| Block::BirchStairs { .. }
|
| Block::AcaciaFence { .. }
|
||||||
| Block::SpruceStairs { .. }
|
| Block::OakStairs { .. }
|
||||||
| Block::JungleStairs { .. }
|
| Block::BirchStairs { .. }
|
||||||
| Block::AcaciaStairs { .. }
|
| Block::SpruceStairs { .. }
|
||||||
| Block::DarkOakStairs { .. }
|
| Block::JungleStairs { .. }
|
||||||
| Block::Log { .. }
|
| Block::AcaciaStairs { .. }
|
||||||
| Block::Log2 { .. }
|
| Block::DarkOakStairs { .. }
|
||||||
| Block::Leaves { .. }
|
| Block::Log { .. }
|
||||||
| Block::Leaves2 { .. }
|
| Block::Log2 { .. }
|
||||||
| Block::BookShelf { .. }
|
| Block::Leaves { .. }
|
||||||
| Block::TNT { .. }
|
| Block::Leaves2 { .. }
|
||||||
| Block::TallGrass { .. }
|
| Block::BookShelf { .. }
|
||||||
| Block::DoublePlant { .. }
|
| Block::TNT { .. }
|
||||||
| Block::YellowFlower { .. }
|
| Block::TallGrass { .. }
|
||||||
| Block::RedFlower { .. }
|
| Block::DoublePlant { .. }
|
||||||
| Block::DeadBush { .. }
|
| Block::YellowFlower { .. }
|
||||||
| Block::Wool { .. }
|
| Block::RedFlower { .. }
|
||||||
| Block::Vine { .. }
|
| Block::DeadBush { .. }
|
||||||
| Block::CoalBlock { .. }
|
| Block::Wool { .. }
|
||||||
| Block::HayBlock { .. }
|
| Block::Vine { .. }
|
||||||
| Block::Carpet { .. })
|
| Block::CoalBlock { .. }
|
||||||
|
| Block::HayBlock { .. }
|
||||||
|
| Block::Carpet { .. }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_snowy<W: WorldAccess>(world: &W, pos: Position) -> bool {
|
fn is_snowy<W: WorldAccess>(world: &W, pos: Position) -> bool {
|
||||||
matches!(world.get_block(pos.shift(Direction::Up)), Block::Snow { .. } | Block::SnowLayer { .. })
|
matches!(
|
||||||
|
world.get_block(pos.shift(Direction::Up)),
|
||||||
|
Block::Snow { .. } | Block::SnowLayer { .. }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_connect_sides<F: Fn(Block) -> bool, W: WorldAccess>(
|
fn can_connect_sides<F: Fn(Block) -> bool, W: WorldAccess>(
|
||||||
|
@ -5945,25 +5951,31 @@ fn can_connect<F: Fn(Block) -> bool, W: WorldAccess>(world: &W, pos: Position, f
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_connect_fence(block: Block) -> bool {
|
fn can_connect_fence(block: Block) -> bool {
|
||||||
matches!(block, Block::Fence { .. }
|
matches!(
|
||||||
| Block::SpruceFence { .. }
|
block,
|
||||||
| Block::BirchFence { .. }
|
Block::Fence { .. }
|
||||||
| Block::JungleFence { .. }
|
| Block::SpruceFence { .. }
|
||||||
| Block::DarkOakFence { .. }
|
| Block::BirchFence { .. }
|
||||||
| Block::AcaciaFence { .. }
|
| Block::JungleFence { .. }
|
||||||
| Block::FenceGate { .. }
|
| Block::DarkOakFence { .. }
|
||||||
| Block::SpruceFenceGate { .. }
|
| Block::AcaciaFence { .. }
|
||||||
| Block::BirchFenceGate { .. }
|
| Block::FenceGate { .. }
|
||||||
| Block::JungleFenceGate { .. }
|
| Block::SpruceFenceGate { .. }
|
||||||
| Block::DarkOakFenceGate { .. }
|
| Block::BirchFenceGate { .. }
|
||||||
| Block::AcaciaFenceGate { .. })
|
| Block::JungleFenceGate { .. }
|
||||||
|
| Block::DarkOakFenceGate { .. }
|
||||||
|
| Block::AcaciaFenceGate { .. }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_connect_glasspane(block: Block) -> bool {
|
fn can_connect_glasspane(block: Block) -> bool {
|
||||||
matches!(block, Block::Glass { .. }
|
matches!(
|
||||||
| Block::StainedGlass { .. }
|
block,
|
||||||
| Block::GlassPane { .. }
|
Block::Glass { .. }
|
||||||
| Block::StainedGlassPane { .. })
|
| Block::StainedGlass { .. }
|
||||||
|
| Block::GlassPane { .. }
|
||||||
|
| Block::StainedGlassPane { .. }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_connect_redstone<W: WorldAccess>(world: &W, pos: Position, dir: Direction) -> RedstoneSide {
|
fn can_connect_redstone<W: WorldAccess>(world: &W, pos: Position, dir: Direction) -> RedstoneSide {
|
||||||
|
@ -6198,7 +6210,12 @@ fn door_collision(facing: Direction, hinge: Side, open: bool) -> Vec<Aabb3<f64>>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_repeater_state<W: WorldAccess>(world: &W, pos: Position, facing: Direction) -> bool {
|
fn update_repeater_state<W: WorldAccess>(world: &W, pos: Position, facing: Direction) -> bool {
|
||||||
let f = |dir| matches!(world.get_block(pos.shift(dir)), Block::RepeaterPowered { .. });
|
let f = |dir| {
|
||||||
|
matches!(
|
||||||
|
world.get_block(pos.shift(dir)),
|
||||||
|
Block::RepeaterPowered { .. }
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
f(facing.clockwise()) || f(facing.counter_clockwise())
|
f(facing.clockwise()) || f(facing.counter_clockwise())
|
||||||
}
|
}
|
||||||
|
|
|
@ -601,8 +601,8 @@ impl ComponentMem {
|
||||||
data: vec![],
|
data: vec![],
|
||||||
component_size: mem::size_of::<T>(),
|
component_size: mem::size_of::<T>(),
|
||||||
drop_func: Box::new(|data| unsafe {
|
drop_func: Box::new(|data| unsafe {
|
||||||
let mut val: T = mem::MaybeUninit::uninit().assume_init();
|
let mut val = mem::MaybeUninit::<T>::uninit();
|
||||||
ptr::copy(data as *mut T, &mut val, 1);
|
ptr::copy(data as *mut T, val.as_mut_ptr(), 1);
|
||||||
mem::drop(val);
|
mem::drop(val);
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,20 +491,12 @@ impl Program {
|
||||||
|
|
||||||
pub fn uniform_location(&self, name: &str) -> Option<Uniform> {
|
pub fn uniform_location(&self, name: &str) -> Option<Uniform> {
|
||||||
let u = unsafe { glow_context().get_uniform_location(self.0, name) };
|
let u = unsafe { glow_context().get_uniform_location(self.0, name) };
|
||||||
if let Some(u) = u {
|
u.map(Uniform)
|
||||||
Some(Uniform(u))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attribute_location(&self, name: &str) -> Option<Attribute> {
|
pub fn attribute_location(&self, name: &str) -> Option<Attribute> {
|
||||||
let a = unsafe { glow_context().get_attrib_location(self.0, name) };
|
let a = unsafe { glow_context().get_attrib_location(self.0, name) };
|
||||||
if let Some(a) = a {
|
a.map(|a| Attribute(a as i32))
|
||||||
Some(Attribute(a as i32))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,7 +797,7 @@ impl Drop for MappedBuffer {
|
||||||
unsafe {
|
unsafe {
|
||||||
glow_context().unmap_buffer(self.target);
|
glow_context().unmap_buffer(self.target);
|
||||||
}
|
}
|
||||||
mem::forget(mem::replace(&mut self.inner, Vec::new()));
|
mem::forget(std::mem::take(&mut self.inner))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
82
src/main.rs
82
src/main.rs
|
@ -631,53 +631,53 @@ fn handle_window_event<T>(
|
||||||
use winit::event::*;
|
use winit::event::*;
|
||||||
match event {
|
match event {
|
||||||
Event::MainEventsCleared => return true,
|
Event::MainEventsCleared => return true,
|
||||||
Event::DeviceEvent { event, .. } => {
|
Event::DeviceEvent {
|
||||||
if let DeviceEvent::MouseMotion {
|
event: DeviceEvent::MouseMotion {
|
||||||
delta: (xrel, yrel),
|
delta: (xrel, yrel),
|
||||||
} = event
|
},
|
||||||
{
|
..
|
||||||
let (rx, ry) = if xrel > 1000.0 || yrel > 1000.0 {
|
} => {
|
||||||
// Heuristic for if we were passed an absolute value instead of relative
|
let (rx, ry) = if xrel > 1000.0 || yrel > 1000.0 {
|
||||||
// Workaround https://github.com/tomaka/glutin/issues/1084 MouseMotion event returns absolute instead of relative values, when running Linux in a VM
|
// Heuristic for if we were passed an absolute value instead of relative
|
||||||
// Note SDL2 had a hint to handle this scenario:
|
// Workaround https://github.com/tomaka/glutin/issues/1084 MouseMotion event returns absolute instead of relative values, when running Linux in a VM
|
||||||
// sdl2::hint::set_with_priority("SDL_MOUSE_RELATIVE_MODE_WARP", "1", &sdl2::hint::Hint::Override);
|
// Note SDL2 had a hint to handle this scenario:
|
||||||
let s = 8000.0 + 0.01;
|
// sdl2::hint::set_with_priority("SDL_MOUSE_RELATIVE_MODE_WARP", "1", &sdl2::hint::Hint::Override);
|
||||||
(
|
let s = 8000.0 + 0.01;
|
||||||
(xrel - game.last_mouse_xrel) / s,
|
(
|
||||||
(yrel - game.last_mouse_yrel) / s,
|
(xrel - game.last_mouse_xrel) / s,
|
||||||
)
|
(yrel - game.last_mouse_yrel) / s,
|
||||||
} else {
|
)
|
||||||
let s = 2000.0 + 0.01;
|
} else {
|
||||||
(xrel / s, yrel / s)
|
let s = 2000.0 + 0.01;
|
||||||
};
|
(xrel / s, yrel / s)
|
||||||
|
};
|
||||||
|
|
||||||
game.last_mouse_xrel = xrel;
|
game.last_mouse_xrel = xrel;
|
||||||
game.last_mouse_yrel = yrel;
|
game.last_mouse_yrel = yrel;
|
||||||
|
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
if game.focused {
|
if game.focused {
|
||||||
window.set_cursor_grab(true).unwrap();
|
window.set_cursor_grab(true).unwrap();
|
||||||
window.set_cursor_visible(false);
|
window.set_cursor_visible(false);
|
||||||
if let Some(player) = game.server.player {
|
if let Some(player) = game.server.player {
|
||||||
let rotation = game
|
let rotation = game
|
||||||
.server
|
.server
|
||||||
.entities
|
.entities
|
||||||
.get_component_mut(player, game.server.rotation)
|
.get_component_mut(player, game.server.rotation)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
rotation.yaw -= rx;
|
rotation.yaw -= rx;
|
||||||
rotation.pitch -= ry;
|
rotation.pitch -= ry;
|
||||||
if rotation.pitch < (PI / 2.0) + 0.01 {
|
if rotation.pitch < (PI / 2.0) + 0.01 {
|
||||||
rotation.pitch = (PI / 2.0) + 0.01;
|
rotation.pitch = (PI / 2.0) + 0.01;
|
||||||
}
|
}
|
||||||
if rotation.pitch > (PI / 2.0) * 3.0 - 0.01 {
|
if rotation.pitch > (PI / 2.0) * 3.0 - 0.01 {
|
||||||
rotation.pitch = (PI / 2.0) * 3.0 - 0.01;
|
rotation.pitch = (PI / 2.0) * 3.0 - 0.01;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
window.set_cursor_grab(false).unwrap();
|
|
||||||
window.set_cursor_visible(true);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
window.set_cursor_grab(false).unwrap();
|
||||||
|
window.set_cursor_visible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -547,7 +547,7 @@ impl Factory {
|
||||||
ambient_occlusion: raw.ambient_occlusion,
|
ambient_occlusion: raw.ambient_occlusion,
|
||||||
weight: raw.weight,
|
weight: raw.weight,
|
||||||
};
|
};
|
||||||
let elements = ::std::mem::replace(&mut raw.elements, vec![]);
|
let elements = std::mem::take(&mut raw.elements);
|
||||||
for el in elements {
|
for el in elements {
|
||||||
let all_dirs = Direction::all();
|
let all_dirs = Direction::all();
|
||||||
for (i, face) in el.faces.iter().enumerate() {
|
for (i, face) in el.faces.iter().enumerate() {
|
||||||
|
|
|
@ -1902,31 +1902,29 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_block_entities(&mut self, block_entities: Vec<Option<crate::nbt::NamedTag>>) {
|
fn load_block_entities(&mut self, block_entities: Vec<Option<crate::nbt::NamedTag>>) {
|
||||||
for optional_block_entity in block_entities {
|
for block_entity in block_entities.into_iter().flatten() {
|
||||||
if let Some(block_entity) = optional_block_entity {
|
let x = block_entity.1.get("x").unwrap().as_int().unwrap();
|
||||||
let x = block_entity.1.get("x").unwrap().as_int().unwrap();
|
let y = block_entity.1.get("y").unwrap().as_int().unwrap();
|
||||||
let y = block_entity.1.get("y").unwrap().as_int().unwrap();
|
let z = block_entity.1.get("z").unwrap().as_int().unwrap();
|
||||||
let z = block_entity.1.get("z").unwrap().as_int().unwrap();
|
if let Some(tile_id) = block_entity.1.get("id") {
|
||||||
if let Some(tile_id) = block_entity.1.get("id") {
|
let tile_id = tile_id.as_str().unwrap();
|
||||||
let tile_id = tile_id.as_str().unwrap();
|
let action;
|
||||||
let action;
|
match tile_id {
|
||||||
match tile_id {
|
// Fake a sign update
|
||||||
// Fake a sign update
|
"Sign" => action = 9,
|
||||||
"Sign" => action = 9,
|
// Not something we care about, so break the loop
|
||||||
// Not something we care about, so break the loop
|
_ => continue,
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
self.on_block_entity_update(packet::play::clientbound::UpdateBlockEntity {
|
|
||||||
location: Position::new(x, y, z),
|
|
||||||
action,
|
|
||||||
nbt: Some(block_entity.clone()),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
warn!(
|
|
||||||
"Block entity at ({},{},{}) missing id tag: {:?}",
|
|
||||||
x, y, z, block_entity
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
self.on_block_entity_update(packet::play::clientbound::UpdateBlockEntity {
|
||||||
|
location: Position::new(x, y, z),
|
||||||
|
action,
|
||||||
|
nbt: Some(block_entity.clone()),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Block entity at ({},{},{}) missing id tag: {:?}",
|
||||||
|
x, y, z, block_entity
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -661,15 +661,12 @@ impl World {
|
||||||
|
|
||||||
let cpos = CPos(x, z);
|
let cpos = CPos(x, z);
|
||||||
{
|
{
|
||||||
let chunk = if new {
|
if new {
|
||||||
self.chunks.insert(cpos, Chunk::new(cpos));
|
self.chunks.insert(cpos, Chunk::new(cpos));
|
||||||
self.chunks.get_mut(&cpos).unwrap()
|
} else if !self.chunks.contains_key(&cpos) {
|
||||||
} else {
|
return Ok(());
|
||||||
if !self.chunks.contains_key(&cpos) {
|
}
|
||||||
return Ok(());
|
let chunk = self.chunks.get_mut(&cpos).unwrap();
|
||||||
}
|
|
||||||
self.chunks.get_mut(&cpos).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
for i in 0..16 {
|
for i in 0..16 {
|
||||||
if chunk.sections[i].is_none() {
|
if chunk.sections[i].is_none() {
|
||||||
|
@ -816,15 +813,12 @@ impl World {
|
||||||
) -> Result<(), protocol::Error> {
|
) -> Result<(), protocol::Error> {
|
||||||
let cpos = CPos(x, z);
|
let cpos = CPos(x, z);
|
||||||
{
|
{
|
||||||
let chunk = if new {
|
if new {
|
||||||
self.chunks.insert(cpos, Chunk::new(cpos));
|
self.chunks.insert(cpos, Chunk::new(cpos));
|
||||||
self.chunks.get_mut(&cpos).unwrap()
|
} else if !self.chunks.contains_key(&cpos) {
|
||||||
} else {
|
return Ok(());
|
||||||
if !self.chunks.contains_key(&cpos) {
|
}
|
||||||
return Ok(());
|
let chunk = self.chunks.get_mut(&cpos).unwrap();
|
||||||
}
|
|
||||||
self.chunks.get_mut(&cpos).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Block type array - whole byte per block
|
// Block type array - whole byte per block
|
||||||
let mut block_types = [[0u8; 4096]; 16];
|
let mut block_types = [[0u8; 4096]; 16];
|
||||||
|
@ -1015,15 +1009,12 @@ impl World {
|
||||||
|
|
||||||
let cpos = CPos(x, z);
|
let cpos = CPos(x, z);
|
||||||
{
|
{
|
||||||
let chunk = if new {
|
if new {
|
||||||
self.chunks.insert(cpos, Chunk::new(cpos));
|
self.chunks.insert(cpos, Chunk::new(cpos));
|
||||||
self.chunks.get_mut(&cpos).unwrap()
|
} else if !self.chunks.contains_key(&cpos) {
|
||||||
} else {
|
return Ok(());
|
||||||
if !self.chunks.contains_key(&cpos) {
|
}
|
||||||
return Ok(());
|
let chunk = self.chunks.get_mut(&cpos).unwrap();
|
||||||
}
|
|
||||||
self.chunks.get_mut(&cpos).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
for i in 0..16 {
|
for i in 0..16 {
|
||||||
if chunk.sections[i].is_none() {
|
if chunk.sections[i].is_none() {
|
||||||
|
|
Loading…
Reference in New Issue