mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-09 03:59:53 -04:00
Directional drops (#1251)
* Add some crazy complicated logic to unstuck items * Add bouncinessFactor * Fix formatting issues * Use rayIntersection to determine direction of drop * Simplify blockDrop() code * Apply review change requests * Send bounding box for block drops * Rename BlockDrop to BlockDropLocation * Apply review change requests * Apply review change requests * Update src/Inventory.zig * Apply review change requests * Remove code reversing direction for carpet * Update src/Inventory.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> * Update src/Inventory.zig Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> * Remove factors variable * Strip types from randomOffset --------- Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>
This commit is contained in:
parent
735e99826e
commit
668f9d0a9a
@ -13,6 +13,7 @@ const Vec3d = vec.Vec3d;
|
|||||||
const Vec3f = vec.Vec3f;
|
const Vec3f = vec.Vec3f;
|
||||||
const Vec3i = vec.Vec3i;
|
const Vec3i = vec.Vec3i;
|
||||||
const ZonElement = main.ZonElement;
|
const ZonElement = main.ZonElement;
|
||||||
|
const Neighbor = main.chunk.Neighbor;
|
||||||
|
|
||||||
const Gamemode = main.game.Gamemode;
|
const Gamemode = main.game.Gamemode;
|
||||||
|
|
||||||
@ -1555,9 +1556,80 @@ pub const Command = struct { // MARK: Command
|
|||||||
const UpdateBlock = struct { // MARK: UpdateBlock
|
const UpdateBlock = struct { // MARK: UpdateBlock
|
||||||
source: InventoryAndSlot,
|
source: InventoryAndSlot,
|
||||||
pos: Vec3i,
|
pos: Vec3i,
|
||||||
|
dropLocation: BlockDropLocation,
|
||||||
oldBlock: Block,
|
oldBlock: Block,
|
||||||
newBlock: Block,
|
newBlock: Block,
|
||||||
|
|
||||||
|
const half = @as(Vec3f, @splat(0.5));
|
||||||
|
const itemHitBoxMargin: f32 = @floatCast(main.itemdrop.ItemDropManager.radius);
|
||||||
|
const itemHitBoxMarginVec: Vec3f = @splat(itemHitBoxMargin);
|
||||||
|
|
||||||
|
const BlockDropLocation = struct {
|
||||||
|
dir: Neighbor,
|
||||||
|
min: Vec3f,
|
||||||
|
max: Vec3f,
|
||||||
|
|
||||||
|
pub fn drop(self: BlockDropLocation, pos: Vec3i, newBlock: Block, _drop: main.blocks.BlockDrop) void {
|
||||||
|
if(newBlock.collide()) {
|
||||||
|
self.dropOutside(pos, _drop);
|
||||||
|
} else {
|
||||||
|
self.dropInside(pos, _drop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn dropInside(self: BlockDropLocation, pos: Vec3i, _drop: main.blocks.BlockDrop) void {
|
||||||
|
for(_drop.items) |itemStack| {
|
||||||
|
main.server.world.?.drop(itemStack.clone(), self.insidePos(pos), self.dropDir(), self.dropVelocity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn insidePos(self: BlockDropLocation, _pos: Vec3i) Vec3d {
|
||||||
|
const pos: Vec3d = @floatFromInt(_pos);
|
||||||
|
return pos + self.randomOffset();
|
||||||
|
}
|
||||||
|
fn randomOffset(self: BlockDropLocation) Vec3f {
|
||||||
|
const max = @min(@as(Vec3f, @splat(1.0)) - itemHitBoxMarginVec, @max(itemHitBoxMarginVec, self.max - itemHitBoxMarginVec));
|
||||||
|
const min = @min(max, @max(itemHitBoxMarginVec, self.min + itemHitBoxMarginVec));
|
||||||
|
const center = (max + min)*half;
|
||||||
|
const width = (max - min)*half;
|
||||||
|
return center + width*main.random.nextFloatVectorSigned(3, &main.seed)*half;
|
||||||
|
}
|
||||||
|
fn dropOutside(self: BlockDropLocation, pos: Vec3i, _drop: main.blocks.BlockDrop) void {
|
||||||
|
for(_drop.items) |itemStack| {
|
||||||
|
main.server.world.?.drop(itemStack.clone(), self.outsidePos(pos), self.dropDir(), self.dropVelocity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn outsidePos(self: BlockDropLocation, _pos: Vec3i) Vec3d {
|
||||||
|
const pos: Vec3d = @floatFromInt(_pos);
|
||||||
|
return pos + self.randomOffset()*self.minor() + self.directionOffset()*self.major() + self.direction()*itemHitBoxMarginVec;
|
||||||
|
}
|
||||||
|
fn directionOffset(self: BlockDropLocation) Vec3d {
|
||||||
|
return half + self.direction()*half;
|
||||||
|
}
|
||||||
|
inline fn direction(self: BlockDropLocation) Vec3d {
|
||||||
|
return @floatFromInt(self.dir.relPos());
|
||||||
|
}
|
||||||
|
inline fn major(self: BlockDropLocation) Vec3d {
|
||||||
|
return @floatFromInt(@abs(self.dir.relPos()));
|
||||||
|
}
|
||||||
|
inline fn minor(self: BlockDropLocation) Vec3d {
|
||||||
|
return @floatFromInt(self.dir.orthogonalComponents());
|
||||||
|
}
|
||||||
|
fn dropDir(self: BlockDropLocation) Vec3f {
|
||||||
|
const randomnessVec: Vec3f = main.random.nextFloatVectorSigned(3, &main.seed)*@as(Vec3f, @splat(0.25));
|
||||||
|
const directionVec: Vec3f = @as(Vec3f, @floatCast(self.direction())) + randomnessVec;
|
||||||
|
const z: f32 = directionVec[2];
|
||||||
|
return vec.normalize(Vec3f{
|
||||||
|
directionVec[0],
|
||||||
|
directionVec[1],
|
||||||
|
if(z < -0.5) 0 else if(z < 0.0) (z + 0.5)*4.0 else z + 2.0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn dropVelocity(self: BlockDropLocation) f32 {
|
||||||
|
const velocity = 3.5 + main.random.nextFloatSigned(&main.seed)*0.5;
|
||||||
|
if(self.direction()[2] < -0.5) return velocity*0.333;
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fn run(self: UpdateBlock, allocator: NeverFailingAllocator, cmd: *Command, side: Side, user: ?*main.server.User, gamemode: Gamemode) error{serverFailure}!void {
|
fn run(self: UpdateBlock, allocator: NeverFailingAllocator, cmd: *Command, side: Side, user: ?*main.server.User, gamemode: Gamemode) error{serverFailure}!void {
|
||||||
if(self.source.inv.type != .normal) return;
|
if(self.source.inv.type != .normal) return;
|
||||||
|
|
||||||
@ -1610,7 +1682,7 @@ pub const Command = struct { // MARK: Command
|
|||||||
for(0..amount) |_| {
|
for(0..amount) |_| {
|
||||||
for(self.newBlock.blockDrops()) |drop| {
|
for(self.newBlock.blockDrops()) |drop| {
|
||||||
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
|
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
|
||||||
blockDrop(self.pos, drop);
|
self.dropLocation.drop(self.pos, self.newBlock, drop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1621,25 +1693,18 @@ pub const Command = struct { // MARK: Command
|
|||||||
if(side == .server and gamemode != .creative and self.oldBlock.typ != self.newBlock.typ and shouldDropSourceBlockOnSuccess) {
|
if(side == .server and gamemode != .creative and self.oldBlock.typ != self.newBlock.typ and shouldDropSourceBlockOnSuccess) {
|
||||||
for(self.oldBlock.blockDrops()) |drop| {
|
for(self.oldBlock.blockDrops()) |drop| {
|
||||||
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
|
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
|
||||||
blockDrop(self.pos, drop);
|
self.dropLocation.drop(self.pos, self.newBlock, drop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blockDrop(pos: Vec3i, drop: main.blocks.BlockDrop) void {
|
|
||||||
for(drop.items) |itemStack| {
|
|
||||||
const dropPos = @as(Vec3d, @floatFromInt(pos)) + @as(Vec3d, @splat(0.5)) + main.random.nextDoubleVectorSigned(3, &main.seed)*@as(Vec3d, @splat(0.5 - main.itemdrop.ItemDropManager.radius));
|
|
||||||
const dir = vec.normalize(main.random.nextFloatVectorSigned(3, &main.seed));
|
|
||||||
main.server.world.?.drop(itemStack.clone(), dropPos, dir, main.random.nextFloat(&main.seed)*1.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize(self: UpdateBlock, writer: *utils.BinaryWriter) void {
|
fn serialize(self: UpdateBlock, writer: *utils.BinaryWriter) void {
|
||||||
self.source.write(writer);
|
self.source.write(writer);
|
||||||
writer.writeInt(i32, self.pos[0]);
|
writer.writeVec(Vec3i, self.pos);
|
||||||
writer.writeInt(i32, self.pos[1]);
|
writer.writeEnum(Neighbor, self.dropLocation.dir);
|
||||||
writer.writeInt(i32, self.pos[2]);
|
writer.writeVec(Vec3f, self.dropLocation.min);
|
||||||
|
writer.writeVec(Vec3f, self.dropLocation.max);
|
||||||
writer.writeInt(u32, @as(u32, @bitCast(self.oldBlock)));
|
writer.writeInt(u32, @as(u32, @bitCast(self.oldBlock)));
|
||||||
writer.writeInt(u32, @as(u32, @bitCast(self.newBlock)));
|
writer.writeInt(u32, @as(u32, @bitCast(self.newBlock)));
|
||||||
}
|
}
|
||||||
@ -1647,10 +1712,11 @@ pub const Command = struct { // MARK: Command
|
|||||||
fn deserialize(reader: *utils.BinaryReader, side: Side, user: ?*main.server.User) !UpdateBlock {
|
fn deserialize(reader: *utils.BinaryReader, side: Side, user: ?*main.server.User) !UpdateBlock {
|
||||||
return .{
|
return .{
|
||||||
.source = try InventoryAndSlot.read(reader, side, user),
|
.source = try InventoryAndSlot.read(reader, side, user),
|
||||||
.pos = .{
|
.pos = try reader.readVec(Vec3i),
|
||||||
try reader.readInt(i32),
|
.dropLocation = .{
|
||||||
try reader.readInt(i32),
|
.dir = try reader.readEnum(Neighbor),
|
||||||
try reader.readInt(i32),
|
.min = try reader.readVec(Vec3f),
|
||||||
|
.max = try reader.readVec(Vec3f),
|
||||||
},
|
},
|
||||||
.oldBlock = @bitCast(try reader.readInt(u32)),
|
.oldBlock = @bitCast(try reader.readInt(u32)),
|
||||||
.newBlock = @bitCast(try reader.readInt(u32)),
|
.newBlock = @bitCast(try reader.readInt(u32)),
|
||||||
|
@ -716,6 +716,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
|||||||
var currentSwingTime: f32 = 0;
|
var currentSwingTime: f32 = 0;
|
||||||
var selectionMin: Vec3f = undefined;
|
var selectionMin: Vec3f = undefined;
|
||||||
var selectionMax: Vec3f = undefined;
|
var selectionMax: Vec3f = undefined;
|
||||||
|
var selectionFace: chunk.Neighbor = undefined;
|
||||||
var lastPos: Vec3d = undefined;
|
var lastPos: Vec3d = undefined;
|
||||||
var lastDir: Vec3f = undefined;
|
var lastDir: Vec3f = undefined;
|
||||||
pub fn select(pos: Vec3d, _dir: Vec3f, item: ?main.items.Item) void {
|
pub fn select(pos: Vec3d, _dir: Vec3f, item: ?main.items.Item) void {
|
||||||
@ -750,6 +751,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
|||||||
selectedBlockPos = voxelPos;
|
selectedBlockPos = voxelPos;
|
||||||
selectionMin = intersection.min;
|
selectionMin = intersection.min;
|
||||||
selectionMax = intersection.max;
|
selectionMax = intersection.max;
|
||||||
|
selectionFace = intersection.face;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -927,7 +929,19 @@ pub const MeshSelection = struct { // MARK: MeshSelection
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn updateBlockAndSendUpdate(source: main.items.Inventory, slot: u32, x: i32, y: i32, z: i32, oldBlock: blocks.Block, newBlock: blocks.Block) void {
|
fn updateBlockAndSendUpdate(source: main.items.Inventory, slot: u32, x: i32, y: i32, z: i32, oldBlock: blocks.Block, newBlock: blocks.Block) void {
|
||||||
main.items.Inventory.Sync.ClientSide.executeCommand(.{.updateBlock = .{.source = .{.inv = source, .slot = slot}, .pos = .{x, y, z}, .oldBlock = oldBlock, .newBlock = newBlock}});
|
main.items.Inventory.Sync.ClientSide.executeCommand(.{
|
||||||
|
.updateBlock = .{
|
||||||
|
.source = .{.inv = source, .slot = slot},
|
||||||
|
.pos = .{x, y, z},
|
||||||
|
.dropLocation = .{
|
||||||
|
.dir = selectionFace,
|
||||||
|
.min = selectionMin,
|
||||||
|
.max = selectionMax,
|
||||||
|
},
|
||||||
|
.oldBlock = oldBlock,
|
||||||
|
.newBlock = newBlock,
|
||||||
|
},
|
||||||
|
});
|
||||||
mesh_storage.updateBlock(x, y, z, newBlock);
|
mesh_storage.updateBlock(x, y, z, newBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ pub const RayIntersectionResult = struct {
|
|||||||
distance: f64,
|
distance: f64,
|
||||||
min: Vec3f,
|
min: Vec3f,
|
||||||
max: Vec3f,
|
max: Vec3f,
|
||||||
|
face: Neighbor,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Degrees = enum(u2) {
|
pub const Degrees = enum(u2) {
|
||||||
@ -65,10 +66,27 @@ pub const RotationMode = struct { // MARK: RotationMode
|
|||||||
const boxTMin = @reduce(.Max, @min(t1, t2));
|
const boxTMin = @reduce(.Max, @min(t1, t2));
|
||||||
const boxTMax = @reduce(.Min, @max(t1, t2));
|
const boxTMax = @reduce(.Min, @max(t1, t2));
|
||||||
if(boxTMin <= boxTMax and boxTMax > 0) {
|
if(boxTMin <= boxTMax and boxTMax > 0) {
|
||||||
|
var face: Neighbor = undefined;
|
||||||
|
if(boxTMin == t1[0]) {
|
||||||
|
face = Neighbor.dirNegX;
|
||||||
|
} else if(boxTMin == t1[1]) {
|
||||||
|
face = Neighbor.dirNegY;
|
||||||
|
} else if(boxTMin == t1[2]) {
|
||||||
|
face = Neighbor.dirDown;
|
||||||
|
} else if(boxTMin == t2[0]) {
|
||||||
|
face = Neighbor.dirPosX;
|
||||||
|
} else if(boxTMin == t2[1]) {
|
||||||
|
face = Neighbor.dirPosY;
|
||||||
|
} else if(boxTMin == t2[2]) {
|
||||||
|
face = Neighbor.dirUp;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
return .{
|
return .{
|
||||||
.distance = boxTMin,
|
.distance = boxTMin,
|
||||||
.min = min,
|
.min = min,
|
||||||
.max = max,
|
.max = max,
|
||||||
|
.face = face,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -296,15 +296,12 @@ pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos:
|
|||||||
if(item) |_item| {
|
if(item) |_item| {
|
||||||
switch(_item) {
|
switch(_item) {
|
||||||
.baseItem => |baseItem| {
|
.baseItem => |baseItem| {
|
||||||
if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Select only one eigth of a block
|
if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Select only one eighth of a block
|
||||||
if(intersectionPos(block, relativePlayerPos, playerDir)) |intersection| {
|
if(intersectionPos(block, relativePlayerPos, playerDir)) |intersection| {
|
||||||
const offset: Vec3f = @floatFromInt(intersection.minPos);
|
const offset: Vec3f = @floatFromInt(intersection.minPos);
|
||||||
const half: Vec3f = @splat(0.5);
|
const half: Vec3f = @splat(0.5);
|
||||||
return .{
|
const fullIntersection = RotationMode.DefaultFunctions.rayIntersection(block, item, relativePlayerPos, playerDir) orelse unreachable;
|
||||||
.distance = intersection.minT,
|
return .{.distance = intersection.minT, .min = half*offset, .max = half + half*offset, .face = fullIntersection.face};
|
||||||
.min = half*offset,
|
|
||||||
.max = half + half*offset,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user