Skip to content

Commit

Permalink
Reduce air drag and reduce intitial velocity of item drops when break…
Browse files Browse the repository at this point in the history
…ing a block.

Also offset their initial position randomly within the block.

progress towards #868
  • Loading branch information
IntegratedQuantum committed Jan 1, 2025
1 parent 613498d commit 1c5229e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 27 deletions.
47 changes: 26 additions & 21 deletions src/Inventory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ItemStack = main.items.ItemStack;
const Tool = main.items.Tool;
const NeverFailingAllocator = main.utils.NeverFailingAllocator;
const vec = main.vec;
const Vec3d = vec.Vec3d;
const Vec3f = vec.Vec3f;
const Vec3i = vec.Vec3i;
const ZonElement = main.ZonElement;
Expand Down Expand Up @@ -465,7 +466,7 @@ pub const Command = struct { // MARK: Command
},
};

const SyncOperation = struct {
const SyncOperation = struct { // MARK: SyncOperation
// Since the client doesn't know about all inventories, we can only use create(+amount)/delete(-amount) operations to apply the server side updates.
inv: InventoryAndSlot,
amount: i32,
Expand Down Expand Up @@ -536,7 +537,7 @@ pub const Command = struct { // MARK: Command
return list.toOwnedSlice();
}

fn do(self: *Command, allocator: NeverFailingAllocator, side: Side, user: ?*main.server.User, gamemode: main.game.Gamemode) error{serverFailure}!void {
fn do(self: *Command, allocator: NeverFailingAllocator, side: Side, user: ?*main.server.User, gamemode: main.game.Gamemode) error{serverFailure}!void { // MARK: do()
std.debug.assert(self.baseOperations.items.len == 0); // do called twice without cleaning up
switch(self.payload) {
inline else => |payload| {
Expand Down Expand Up @@ -654,7 +655,7 @@ pub const Command = struct { // MARK: Command
}
}

fn executeBaseOperation(self: *Command, allocator: NeverFailingAllocator, _op: BaseOperation, side: Side) void {
fn executeBaseOperation(self: *Command, allocator: NeverFailingAllocator, _op: BaseOperation, side: Side) void { // MARK: executeBaseOperation()
var op = _op;
switch(op) {
.move => |info| {
Expand Down Expand Up @@ -706,7 +707,7 @@ pub const Command = struct { // MARK: Command
return true;
}

fn tryCraftingTo(self: *Command, allocator: NeverFailingAllocator, dest: InventoryAndSlot, source: InventoryAndSlot, side: Side, user: ?*main.server.User) void {
fn tryCraftingTo(self: *Command, allocator: NeverFailingAllocator, dest: InventoryAndSlot, source: InventoryAndSlot, side: Side, user: ?*main.server.User) void { // MARK: tryCraftingTo()
std.debug.assert(source.inv.type == .crafting);
std.debug.assert(dest.inv.type == .normal);
if(source.slot != source.inv._items.len - 1) return;
Expand Down Expand Up @@ -768,7 +769,7 @@ pub const Command = struct { // MARK: Command
}}, side);
}

const Open = struct {
const Open = struct { // MARK: Open
inv: Inventory,
source: Source,

Expand Down Expand Up @@ -820,7 +821,7 @@ pub const Command = struct { // MARK: Command
}
};

const Close = struct {
const Close = struct { // MARK: Close
inv: Inventory,
allocator: NeverFailingAllocator,

Expand Down Expand Up @@ -848,7 +849,7 @@ pub const Command = struct { // MARK: Command
}
};

const DepositOrSwap = struct {
const DepositOrSwap = struct { // MARK: DepositOrSwap
dest: InventoryAndSlot,
source: InventoryAndSlot,

Expand Down Expand Up @@ -910,7 +911,7 @@ pub const Command = struct { // MARK: Command
}
};

const Deposit = struct {
const Deposit = struct { // MARK: Deposit
dest: InventoryAndSlot,
source: InventoryAndSlot,
amount: u16,
Expand Down Expand Up @@ -957,7 +958,7 @@ pub const Command = struct { // MARK: Command
}
};

const TakeHalf = struct {
const TakeHalf = struct { // MARK: TakeHalf
dest: InventoryAndSlot,
source: InventoryAndSlot,

Expand Down Expand Up @@ -1020,7 +1021,7 @@ pub const Command = struct { // MARK: Command
}
};

const Drop = struct {
const Drop = struct { // MARK: Drop
source: InventoryAndSlot,
desiredAmount: u16 = 0xffff,

Expand Down Expand Up @@ -1075,7 +1076,7 @@ pub const Command = struct { // MARK: Command
}
};

const FillFromCreative = struct {
const FillFromCreative = struct { // MARK: FillFromCreative
dest: InventoryAndSlot,
item: ?Item,
amount: u16 = 0,
Expand Down Expand Up @@ -1128,7 +1129,7 @@ pub const Command = struct { // MARK: Command
}
};

const DepositOrDrop = struct {
const DepositOrDrop = struct { // MARK: DepositOrDrop
dest: Inventory,
source: Inventory,

Expand Down Expand Up @@ -1189,7 +1190,7 @@ pub const Command = struct { // MARK: Command
}
};

const Clear = struct {
const Clear = struct { // MARK: Clear
inv: Inventory,

pub fn run(self: Clear, allocator: NeverFailingAllocator, cmd: *Command, side: Side, _: ?*main.server.User, _: Gamemode) error{serverFailure}!void {
Expand Down Expand Up @@ -1220,7 +1221,7 @@ pub const Command = struct { // MARK: Command
}
};

const UpdateBlock = struct {
const UpdateBlock = struct { // MARK: UpdateBlock
source: InventoryAndSlot,
pos: Vec3i,
oldBlock: Block,
Expand Down Expand Up @@ -1275,9 +1276,7 @@ pub const Command = struct { // MARK: Command
for(0..amount) |_| {
for(self.newBlock.blockDrops()) |drop| {
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
for(drop.items) |itemStack| {
main.server.world.?.drop(itemStack.clone(), @as(vec.Vec3d, @floatFromInt(self.pos)) + vec.Vec3d{0.5, 0.5, 0.5}, main.random.nextFloatVectorSigned(3, &main.seed), main.random.nextFloat(&main.seed)*20);
}
blockDrop(self.pos, drop);
}
}
}
Expand All @@ -1288,14 +1287,20 @@ pub const Command = struct { // MARK: Command
if(side == .server and gamemode != .creative and self.oldBlock.typ != self.newBlock.typ) {
for(self.oldBlock.blockDrops()) |drop| {
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
for(drop.items) |itemStack| {
main.server.world.?.drop(itemStack.clone(), @as(vec.Vec3d, @floatFromInt(self.pos)) + vec.Vec3d{0.5, 0.5, 0.5}, main.random.nextFloatVectorSigned(3, &main.seed), main.random.nextFloat(&main.seed)*20);
}
blockDrop(self.pos, 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, data: *main.List(u8)) void {
self.source.write(data.addMany(8)[0..8]);
std.mem.writeInt(i32, data.addMany(4)[0..4], self.pos[0], .big);
Expand Down Expand Up @@ -1334,7 +1339,7 @@ const Source = union(SourceType) {
other: void,
};

const Inventory = @This();
const Inventory = @This(); // MARK: Inventory

const Type = enum(u8) {
normal = 0,
Expand Down
10 changes: 4 additions & 6 deletions src/itemdrop.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ const ItemDrop = struct { // MARK: ItemDrop

pub const ItemDropManager = struct { // MARK: ItemDropManager
/// Half the side length of all item entities hitboxes as a cube.
const radius: f64 = 0.1;
pub const radius: f64 = 0.1;
/// Side length of all item entities hitboxes as a cube.
const diameter: f64 = 2*radius;
pub const diameter: f64 = 2*radius;

const pickupRange: f64 = 1.0;
pub const pickupRange: f64 = 1.0;

const maxSpeed = 10;

Expand Down Expand Up @@ -285,7 +285,6 @@ pub const ItemDropManager = struct { // MARK: ItemDropManager
self.fixStuckInBlock(chunk, pos, vel, deltaTime);
return;
}
var drag: f64 = self.airDragFactor;
vel.* += Vec3d{0, 0, -self.gravity*deltaTime};
inline for(0..3) |i| {
const move = vel.*[i]*deltaTime;// + acceleration[i]*deltaTime;
Expand All @@ -299,10 +298,9 @@ pub const ItemDropManager = struct { // MARK: ItemDropManager
} else {
pos.*[i] += move;
}
drag += 0.5; // TODO: Calculate drag from block properties and add buoyancy.
}
// Apply drag:
vel.* *= @splat(@max(0, 1 - drag*deltaTime));
vel.* *= @splat(@max(0, 1 - self.airDragFactor*deltaTime));
}

fn fixStuckInBlock(self: *ItemDropManager, chunk: *ServerChunk, pos: *Vec3d, vel: *Vec3d, deltaTime: f64) void {
Expand Down

0 comments on commit 1c5229e

Please sign in to comment.