mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-05 12:17:53 -04:00
Simplified Block Touch Detection (#1143)
* Add block touch detection * Fix touch detection syntax errors * Remove Whitespace * Fix off by one in negatives * Remove Block Touch Detection * Simpler touch detection as suggested by Quantum * Remove touchRetraction because for some reason it is no longer needed * Touch Functions are now function pointers * Remove unwanted debug prints * Add parameter names to TouchFunction declaration * Add error check --------- Co-authored-by: gfh <@> Co-authored-by: SuperIceG <102669377+SEGenjoysBlivits@users.noreply.github.com>
This commit is contained in:
parent
471210f585
commit
2b3547d103
@ -13,6 +13,7 @@ const items = @import("items.zig");
|
|||||||
const models = @import("models.zig");
|
const models = @import("models.zig");
|
||||||
const rotation = @import("rotation.zig");
|
const rotation = @import("rotation.zig");
|
||||||
const RotationMode = rotation.RotationMode;
|
const RotationMode = rotation.RotationMode;
|
||||||
|
const Entity = main.server.Entity;
|
||||||
|
|
||||||
pub const BlockTag = enum(u32) {
|
pub const BlockTag = enum(u32) {
|
||||||
air = 0,
|
air = 0,
|
||||||
@ -109,6 +110,8 @@ var _friction: [maxBlockCount]f32 = undefined;
|
|||||||
|
|
||||||
var _allowOres: [maxBlockCount]bool = undefined;
|
var _allowOres: [maxBlockCount]bool = undefined;
|
||||||
|
|
||||||
|
var _touchFunction: [maxBlockCount]?*const TouchFunction = undefined;
|
||||||
|
|
||||||
var reverseIndices = std.StringHashMap(u16).init(allocator.allocator);
|
var reverseIndices = std.StringHashMap(u16).init(allocator.allocator);
|
||||||
|
|
||||||
var size: u32 = 0;
|
var size: u32 = 0;
|
||||||
@ -149,6 +152,7 @@ pub fn register(_: []const u8, id: []const u8, zon: ZonElement) u16 {
|
|||||||
_hasBackFace[size] = zon.get(bool, "hasBackFace", false);
|
_hasBackFace[size] = zon.get(bool, "hasBackFace", false);
|
||||||
_friction[size] = zon.get(f32, "friction", 20);
|
_friction[size] = zon.get(f32, "friction", 20);
|
||||||
_allowOres[size] = zon.get(bool, "allowOres", false);
|
_allowOres[size] = zon.get(bool, "allowOres", false);
|
||||||
|
_touchFunction[size] = TouchFunctions.getFunctionPointer(zon.get([]const u8, "touchFunction", ""));
|
||||||
|
|
||||||
const oreProperties = zon.getChild("ore");
|
const oreProperties = zon.getChild("ore");
|
||||||
if(oreProperties != .null) blk: {
|
if(oreProperties != .null) blk: {
|
||||||
@ -374,11 +378,44 @@ pub const Block = packed struct { // MARK: Block
|
|||||||
return _allowOres[self.typ];
|
return _allowOres[self.typ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn touchFunction(self: Block) ?*const TouchFunction {
|
||||||
|
return _touchFunction[self.typ];
|
||||||
|
}
|
||||||
|
|
||||||
pub fn canBeChangedInto(self: Block, newBlock: Block, item: main.items.ItemStack, shouldDropSourceBlockOnSuccess: *bool) main.rotation.RotationMode.CanBeChangedInto {
|
pub fn canBeChangedInto(self: Block, newBlock: Block, item: main.items.ItemStack, shouldDropSourceBlockOnSuccess: *bool) main.rotation.RotationMode.CanBeChangedInto {
|
||||||
return newBlock.mode().canBeChangedInto(self, newBlock, item, shouldDropSourceBlockOnSuccess);
|
return newBlock.mode().canBeChangedInto(self, newBlock, item, shouldDropSourceBlockOnSuccess);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const TouchFunction = fn(block: Block, entity: Entity, posX: i32, posY: i32, posZ: i32, isEntityInside: bool) void;
|
||||||
|
|
||||||
|
pub const TouchFunctions = struct {
|
||||||
|
var hashMap: std.StringHashMap(*const TouchFunction) = undefined;
|
||||||
|
|
||||||
|
pub fn init() void {
|
||||||
|
hashMap = .init(main.globalAllocator.allocator);
|
||||||
|
inline for(@typeInfo(TouchFunctions).@"struct".decls) |declaration| {
|
||||||
|
if(@TypeOf(@field(TouchFunctions, declaration.name)) == TouchFunction) {
|
||||||
|
hashMap.putNoClobber(declaration.name, &@field(TouchFunctions, declaration.name)) catch unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit() void {
|
||||||
|
hashMap.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getFunctionPointer(id: []const u8) ?*const TouchFunction {
|
||||||
|
const pointer = hashMap.getPtr(id);
|
||||||
|
if(pointer == null) {
|
||||||
|
if(id.len != 0)
|
||||||
|
std.log.err("Could not find touch function {s}.", .{id});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return pointer.?.*;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const meshes = struct { // MARK: meshes
|
pub const meshes = struct { // MARK: meshes
|
||||||
const AnimationData = extern struct {
|
const AnimationData = extern struct {
|
||||||
startFrame: u32,
|
startFrame: u32,
|
||||||
|
57
src/game.zig
57
src/game.zig
@ -25,6 +25,7 @@ const models = main.models;
|
|||||||
const Fog = graphics.Fog;
|
const Fog = graphics.Fog;
|
||||||
const renderer = @import("renderer.zig");
|
const renderer = @import("renderer.zig");
|
||||||
const settings = @import("settings.zig");
|
const settings = @import("settings.zig");
|
||||||
|
const Block = main.blocks.Block;
|
||||||
|
|
||||||
pub const camera = struct { // MARK: camera
|
pub const camera = struct { // MARK: camera
|
||||||
pub var rotation: Vec3f = Vec3f{0, 0, 0};
|
pub var rotation: Vec3f = Vec3f{0, 0, 0};
|
||||||
@ -362,6 +363,61 @@ pub const collision = struct {
|
|||||||
return resultingMovement;
|
return resultingMovement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isBlockIntersecting(block: Block, posX: i32, posY: i32, posZ: i32, center: Vec3d, extent: Vec3d) bool {
|
||||||
|
const model = &models.models.items[block.mode().model(block)];
|
||||||
|
const position = Vec3d{@floatFromInt(posX), @floatFromInt(posY), @floatFromInt(posZ)};
|
||||||
|
for(model.neighborFacingQuads) |quads| {
|
||||||
|
for(quads) |quadIndex| {
|
||||||
|
const quad = &models.quads.items[quadIndex];
|
||||||
|
if(triangleAABB(.{quad.corners[0] + quad.normal + position, quad.corners[2] + quad.normal + position, quad.corners[1] + quad.normal + position}, center, extent) or
|
||||||
|
triangleAABB(.{quad.corners[1] + quad.normal + position, quad.corners[2] + quad.normal + position, quad.corners[3] + quad.normal + position}, center, extent)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(model.internalQuads) |quadIndex| {
|
||||||
|
const quad = &models.quads.items[quadIndex];
|
||||||
|
if(triangleAABB(.{quad.corners[0] + position, quad.corners[2] + position, quad.corners[1] + position}, center, extent) or
|
||||||
|
triangleAABB(.{quad.corners[1] + position, quad.corners[2] + position, quad.corners[3] + position}, center, extent)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn touchBlocks(entity: main.server.Entity, hitBox: Box, side: main.utils.Side) void {
|
||||||
|
const boundingBox: Box = .{.min = entity.pos + hitBox.min, .max = entity.pos + hitBox.max};
|
||||||
|
|
||||||
|
const minX: i32 = @intFromFloat(@floor(boundingBox.min[0] - 0.01));
|
||||||
|
const maxX: i32 = @intFromFloat(@floor(boundingBox.max[0] + 0.01));
|
||||||
|
const minY: i32 = @intFromFloat(@floor(boundingBox.min[1] - 0.01));
|
||||||
|
const maxY: i32 = @intFromFloat(@floor(boundingBox.max[1] + 0.01));
|
||||||
|
const minZ: i32 = @intFromFloat(@floor(boundingBox.min[2] - 0.01));
|
||||||
|
const maxZ: i32 = @intFromFloat(@floor(boundingBox.max[2] + 0.01));
|
||||||
|
|
||||||
|
const center: Vec3d = boundingBox.center();
|
||||||
|
const extent: Vec3d = boundingBox.extent();
|
||||||
|
|
||||||
|
const extentX: Vec3d = extent + Vec3d{0.01, -0.01, -0.01};
|
||||||
|
const extentY: Vec3d = extent + Vec3d{-0.01, 0.01, -0.01};
|
||||||
|
const extentZ: Vec3d = extent + Vec3d{-0.01, -0.01, 0.01};
|
||||||
|
|
||||||
|
var posX: i32 = minX;
|
||||||
|
while(posX <= maxX) : (posX += 1) {
|
||||||
|
var posY: i32 = minY;
|
||||||
|
while(posY <= maxY) : (posY += 1) {
|
||||||
|
var posZ: i32 = minZ;
|
||||||
|
while(posZ <= maxZ) : (posZ += 1) {
|
||||||
|
const block: ?Block =
|
||||||
|
if(side == .client) main.renderer.mesh_storage.getBlock(posX, posY, posZ) else main.server.world.?.getBlock(posX, posY, posZ);
|
||||||
|
if(block == null or block.?.touchFunction() == null)
|
||||||
|
continue;
|
||||||
|
const touchX: bool = isBlockIntersecting(block.?, posX, posY, posZ, center, extentX);
|
||||||
|
const touchY: bool = isBlockIntersecting(block.?, posX, posY, posZ, center, extentY);
|
||||||
|
const touchZ: bool = isBlockIntersecting(block.?, posX, posY, posZ, center, extentZ);
|
||||||
|
if(touchX or touchY or touchZ)
|
||||||
|
block.?.touchFunction().?(block.?, entity, posX, posY, posZ, touchX and touchY and touchZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const Box = struct {
|
pub const Box = struct {
|
||||||
min: Vec3d,
|
min: Vec3d,
|
||||||
max: Vec3d,
|
max: Vec3d,
|
||||||
@ -1126,6 +1182,7 @@ pub fn update(deltaTime: f64) void { // MARK: update()
|
|||||||
} else if(Player.eyeCoyote > 0) {
|
} else if(Player.eyeCoyote > 0) {
|
||||||
Player.eyePos[2] -= move[2];
|
Player.eyePos[2] -= move[2];
|
||||||
}
|
}
|
||||||
|
collision.touchBlocks(Player.super, hitBox, .client);
|
||||||
} else {
|
} else {
|
||||||
Player.super.pos += move;
|
Player.super.pos += move;
|
||||||
}
|
}
|
||||||
|
@ -580,6 +580,9 @@ pub fn main() void { // MARK: main()
|
|||||||
rotation.init();
|
rotation.init();
|
||||||
defer rotation.deinit();
|
defer rotation.deinit();
|
||||||
|
|
||||||
|
blocks.TouchFunctions.init();
|
||||||
|
defer blocks.TouchFunctions.deinit();
|
||||||
|
|
||||||
models.init();
|
models.init();
|
||||||
defer models.deinit();
|
defer models.deinit();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user