Remove collision from water
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import { AIR } from "$/common/constants.ts";
|
|
||||||
import { move_body } from "$/common/physics.ts";
|
import { move_body } from "$/common/physics.ts";
|
||||||
import type { ClientLevel } from "../level/client_level.ts";
|
import type { ClientLevel } from "../level/client_level.ts";
|
||||||
|
|
||||||
@@ -73,7 +72,7 @@ export abstract class Entity {
|
|||||||
|
|
||||||
// falls and moves by its velocity for one tick, see move_body
|
// falls and moves by its velocity for one tick, see move_body
|
||||||
move() {
|
move() {
|
||||||
const collisions = move_body(this, this.gravity, (x, y, z) => this.level.get_block(x, y, z) !== AIR);
|
const collisions = move_body(this, this.gravity, (x, y, z) => this.level.has_collision(x, y, z));
|
||||||
this.colliding_x = collisions.x;
|
this.colliding_x = collisions.x;
|
||||||
this.colliding_y = collisions.y;
|
this.colliding_y = collisions.y;
|
||||||
this.colliding_z = collisions.z;
|
this.colliding_z = collisions.z;
|
||||||
|
|||||||
@@ -254,6 +254,12 @@ export class ClientLevel {
|
|||||||
return chunk.blocks[index] & ID_MASK;
|
return chunk.blocks[index] & ID_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// whether entities bump into the block there. unloaded chunks count as solid, so nothing falls out of the world
|
||||||
|
has_collision(x: number, y: number, z: number) {
|
||||||
|
const block = this.get_block(x, y, z);
|
||||||
|
return block === VOID || (block !== AIR && (this.#blocks[block]?.has_collision ?? true));
|
||||||
|
}
|
||||||
|
|
||||||
// only changes what this client shows, drops and everything else happen on the server
|
// only changes what this client shows, drops and everything else happen on the server
|
||||||
break_block(x: number, y: number, z: number) {
|
break_block(x: number, y: number, z: number) {
|
||||||
const block_chunk_x = Math.floor(x / CHUNK_SIZE);
|
const block_chunk_x = Math.floor(x / CHUNK_SIZE);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"block": {
|
"block": {
|
||||||
"id": "bworld:chest",
|
"id": "bworld:chest",
|
||||||
"textures": "bworld:planks",
|
"textures": "bworld:planks",
|
||||||
"collision": false,
|
|
||||||
"mining": {
|
"mining": {
|
||||||
"toughness": 8,
|
"toughness": 8,
|
||||||
"tool": "axe"
|
"tool": "axe"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"block": {
|
"block": {
|
||||||
"id": "bworld:dirt",
|
"id": "bworld:dirt",
|
||||||
"textures": "bworld:dirt",
|
"textures": "bworld:dirt",
|
||||||
"collision": false,
|
|
||||||
"mining": {
|
"mining": {
|
||||||
"toughness": 2,
|
"toughness": 2,
|
||||||
"tool": "shovel"
|
"tool": "shovel"
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
"bottom": "bworld:dirt",
|
"bottom": "bworld:dirt",
|
||||||
"side": "bworld:grass_side"
|
"side": "bworld:grass_side"
|
||||||
},
|
},
|
||||||
"collision": false,
|
|
||||||
"mining": {
|
"mining": {
|
||||||
"toughness": 2,
|
"toughness": 2,
|
||||||
"tool": "shovel"
|
"tool": "shovel"
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
"top": "bworld:hoed_dirt",
|
"top": "bworld:hoed_dirt",
|
||||||
"bottom": "bworld:dirt"
|
"bottom": "bworld:dirt"
|
||||||
},
|
},
|
||||||
"collision": false,
|
|
||||||
"mining": {
|
"mining": {
|
||||||
"toughness": 5,
|
"toughness": 5,
|
||||||
"tool": "shovel"
|
"tool": "shovel"
|
||||||
|
|||||||
@@ -829,7 +829,7 @@ export class GameServer {
|
|||||||
if (this.#entities.size === 0) {
|
if (this.#entities.size === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const is_solid = (x: number, y: number, z: number) => this.world.get_block_nid(x, y, z) !== AIR;
|
const is_solid = (x: number, y: number, z: number) => this.world.has_collision(x, y, z);
|
||||||
|
|
||||||
const active = [...this.#entities.values()].filter((entity) => this.#near_any_player(entity.x, entity.z));
|
const active = [...this.#entities.values()].filter((entity) => this.#near_any_player(entity.x, entity.z));
|
||||||
for (const entity of active) {
|
for (const entity of active) {
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ export class ServerWorld {
|
|||||||
return this.#get_chunk(chunk_x, chunk_z)[index_in_chunk(x, y, z, chunk_x, chunk_z)];
|
return this.#get_chunk(chunk_x, chunk_z)[index_in_chunk(x, y, z, chunk_x, chunk_z)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// whether entities bump into the block there, water and other blocks with "collision": false don't
|
||||||
|
has_collision(x: number, y: number, z: number) {
|
||||||
|
return this.get_block_info(x, y, z)?.has_collision ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
get_block_info(x: number, y: number, z: number): BlockRegistry | undefined {
|
get_block_info(x: number, y: number, z: number): BlockRegistry | undefined {
|
||||||
const nid = this.get_block_nid(x, y, z);
|
const nid = this.get_block_nid(x, y, z);
|
||||||
return nid === AIR ? undefined : EverythingRegistry.get_by_id<BlockRegistry>("blocks", nid);
|
return nid === AIR ? undefined : EverythingRegistry.get_by_id<BlockRegistry>("blocks", nid);
|
||||||
|
|||||||
@@ -114,3 +114,16 @@ Deno.test("q throws one of an item the way the player looks, ctrl throws the who
|
|||||||
send(1, { type: "drop_item", container: "crafting", index: 9, all: true });
|
send(1, { type: "drop_item", container: "crafting", index: 9, all: true });
|
||||||
assertEquals(game.item_entities().length, 2);
|
assertEquals(game.item_entities().length, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test("water has no collision, items sink through it to the floor", async () => {
|
||||||
|
const { game, join } = await test_game("mods");
|
||||||
|
join(1, "alice");
|
||||||
|
build_floor(game);
|
||||||
|
for (let y = 100; y <= 102; y++) {
|
||||||
|
game.set_block(6, y, 0, "bworld:water");
|
||||||
|
}
|
||||||
|
const item = game.spawn_item(6.5, 104, 0.5, new ItemStack("bworld:dirt"));
|
||||||
|
for (let i = 0; i < 40; i++) game.tick();
|
||||||
|
assert(item.on_ground);
|
||||||
|
assertEquals(item.y, 100, "on the stone under the water");
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user