Skip to content

Commit 8c77a12

Browse files
authored
Refactor block dropping when breaking block with a tool (#3533)
Related to #3532 Progress towards #2385
1 parent 0616035 commit 8c77a12

2 files changed

Lines changed: 103 additions & 87 deletions

File tree

src/server/BlockDrop.zig

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ const main = @import("main");
22
const Tag = main.Tag;
33
const items = main.items;
44
const Item = items.Item;
5+
const vec = main.vec;
6+
const Vec3d = vec.Vec3d;
7+
const Vec3f = vec.Vec3f;
8+
const Vec3i = vec.Vec3i;
9+
const blocks = main.blocks;
10+
const Block = blocks.Block;
511

612
itemStacks: []const items.ItemStack,
713
chance: f32,
@@ -20,3 +26,93 @@ pub fn isDroppedWhenBrokenWithItem(self: @This(), item: Item) bool {
2026

2127
return true;
2228
}
29+
30+
pub fn drop(self: @This(), pos: Vec3d, dir: Vec3f, velocity: f32) void {
31+
if (self.chance == 1 or main.random.nextFloat(&main.seed) < self.chance) {
32+
for (self.itemStacks) |itemStack| {
33+
main.server.world.?.drop(itemStack.clone(), pos, dir, velocity);
34+
}
35+
}
36+
}
37+
38+
pub const Location = struct {
39+
normalDir: Vec3f,
40+
min: Vec3f,
41+
max: Vec3f,
42+
43+
const half = @as(Vec3f, @splat(0.5));
44+
const itemHitBoxMargin: f32 = @floatCast(main.itemdrop.ItemDropManager.radius);
45+
const itemHitBoxMarginVec: Vec3f = @splat(itemHitBoxMargin);
46+
47+
fn insidePos(self: Location, _pos: Vec3i) Vec3d {
48+
const pos: Vec3d = @floatFromInt(_pos);
49+
return pos + self.randomOffset();
50+
}
51+
fn randomOffset(self: Location) Vec3f {
52+
const max = @min(@as(Vec3f, @splat(1.0)) - itemHitBoxMarginVec, @max(itemHitBoxMarginVec, self.max - itemHitBoxMarginVec));
53+
const min = @min(max, @max(itemHitBoxMarginVec, self.min + itemHitBoxMarginVec));
54+
const center = (max + min)*half;
55+
const width = (max - min)*half;
56+
return center + width*main.random.nextFloatVectorSigned(3, &main.seed)*half;
57+
}
58+
fn outsidePos(self: Location, _pos: Vec3i) Vec3d {
59+
const pos: Vec3d = @floatFromInt(_pos);
60+
const random = self.randomOffset();
61+
const minorVectors = minors(self);
62+
const minor1Offset = @as(Vec3f, @splat(vec.dot(random, minorVectors[0])))*minorVectors[0];
63+
const minor2Offset = @as(Vec3f, @splat(vec.dot(random, minorVectors[1])))*minorVectors[1];
64+
return pos + minor1Offset + minor2Offset + self.directionOffset()*self.major() + self.direction()*itemHitBoxMarginVec;
65+
}
66+
fn directionOffset(self: Location) Vec3d {
67+
return half + self.direction()*half;
68+
}
69+
inline fn direction(self: Location) Vec3f {
70+
return self.normalDir;
71+
}
72+
inline fn major(self: Location) Vec3f {
73+
return @abs(self.normalDir);
74+
}
75+
inline fn minors(self: Location) struct { Vec3f, Vec3f } {
76+
const minor1 = vec.normalize(vec.cross(self.normalDir, if (@reduce(.And, @abs(self.normalDir) == Vec3f{1.0, 0.0, 0.0})) Vec3f{0.0, 1.0, 0.0} else Vec3f{1.0, 0.0, 0.0}));
77+
const minor2 = vec.normalize(vec.cross(self.normalDir, minor1));
78+
return .{minor1, minor2};
79+
}
80+
fn dropDir(self: Location) Vec3f {
81+
const randomnessVec: Vec3f = main.random.nextFloatVectorSigned(3, &main.seed)*@as(Vec3f, @splat(0.25));
82+
const directionVec: Vec3f = @as(Vec3f, @floatCast(self.direction())) + randomnessVec;
83+
const z: f32 = directionVec[2];
84+
return vec.normalize(Vec3f{
85+
directionVec[0],
86+
directionVec[1],
87+
if (z < -0.5) 0 else if (z < 0.0) (z + 0.5)*4.0 else z + 2.0,
88+
});
89+
}
90+
fn dropVelocity(self: Location) f32 {
91+
const velocity = 3.5 + main.random.nextFloatSigned(&main.seed)*0.5;
92+
if (self.direction()[2] < -0.5) return velocity*0.333;
93+
return velocity;
94+
}
95+
};
96+
97+
pub const Context = struct {
98+
oldBlock: Block,
99+
newBlock: Block,
100+
item: Item = .null,
101+
102+
pub fn drop(self: Context, location: Location, pos: Vec3i) void {
103+
const dropAmount = self.oldBlock.mode().itemDropsOnChange(self.oldBlock, self.newBlock);
104+
if (dropAmount == 0) return;
105+
106+
const dropPos = if (self.newBlock.collide()) location.outsidePos(pos) else location.insidePos(pos);
107+
const dropDir = location.dropDir();
108+
const dropVelocity = location.dropVelocity();
109+
110+
for (0..dropAmount) |_| {
111+
for (self.oldBlock.blockDrops()) |blockDrop| {
112+
if (blockDrop.isDroppedWhenBrokenWithItem(self.item)) {
113+
blockDrop.drop(dropPos, dropDir, dropVelocity);
114+
}
115+
}
116+
}
117+
}
118+
};

src/sync.zig

Lines changed: 7 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,86 +1569,10 @@ pub const Command = struct { // MARK: Command
15691569
const UpdateBlock = struct { // MARK: UpdateBlock
15701570
source: InventoryAndSlot,
15711571
pos: Vec3i,
1572-
dropLocation: BlockDropLocation,
1572+
dropLocation: BlockDrop.Location,
15731573
oldBlock: Block,
15741574
newBlock: Block,
15751575

1576-
const half = @as(Vec3f, @splat(0.5));
1577-
const itemHitBoxMargin: f32 = @floatCast(main.itemdrop.ItemDropManager.radius);
1578-
const itemHitBoxMarginVec: Vec3f = @splat(itemHitBoxMargin);
1579-
1580-
const BlockDropLocation = struct {
1581-
normalDir: Vec3f,
1582-
min: Vec3f,
1583-
max: Vec3f,
1584-
1585-
pub fn drop(self: BlockDropLocation, pos: Vec3i, newBlock: Block, _drop: BlockDrop) void {
1586-
if (newBlock.collide()) {
1587-
self.dropOutside(pos, _drop);
1588-
} else {
1589-
self.dropInside(pos, _drop);
1590-
}
1591-
}
1592-
fn dropInside(self: BlockDropLocation, pos: Vec3i, _drop: BlockDrop) void {
1593-
for (_drop.itemStacks) |itemStack| {
1594-
main.server.world.?.drop(itemStack.clone(), self.insidePos(pos), self.dropDir(), self.dropVelocity());
1595-
}
1596-
}
1597-
fn insidePos(self: BlockDropLocation, _pos: Vec3i) Vec3d {
1598-
const pos: Vec3d = @floatFromInt(_pos);
1599-
return pos + self.randomOffset();
1600-
}
1601-
fn randomOffset(self: BlockDropLocation) Vec3f {
1602-
const max = @min(@as(Vec3f, @splat(1.0)) - itemHitBoxMarginVec, @max(itemHitBoxMarginVec, self.max - itemHitBoxMarginVec));
1603-
const min = @min(max, @max(itemHitBoxMarginVec, self.min + itemHitBoxMarginVec));
1604-
const center = (max + min)*half;
1605-
const width = (max - min)*half;
1606-
return center + width*main.random.nextFloatVectorSigned(3, &main.seed)*half;
1607-
}
1608-
fn dropOutside(self: BlockDropLocation, pos: Vec3i, _drop: BlockDrop) void {
1609-
for (_drop.itemStacks) |itemStack| {
1610-
main.server.world.?.drop(itemStack.clone(), self.outsidePos(pos), self.dropDir(), self.dropVelocity());
1611-
}
1612-
}
1613-
fn outsidePos(self: BlockDropLocation, _pos: Vec3i) Vec3d {
1614-
const pos: Vec3d = @floatFromInt(_pos);
1615-
const random = self.randomOffset();
1616-
const minorVectors = minors(self);
1617-
const minor1Offset = @as(Vec3f, @splat(vec.dot(random, minorVectors[0])))*minorVectors[0];
1618-
const minor2Offset = @as(Vec3f, @splat(vec.dot(random, minorVectors[1])))*minorVectors[1];
1619-
return pos + minor1Offset + minor2Offset + self.directionOffset()*self.major() + self.direction()*itemHitBoxMarginVec;
1620-
}
1621-
fn directionOffset(self: BlockDropLocation) Vec3d {
1622-
return half + self.direction()*half;
1623-
}
1624-
inline fn direction(self: BlockDropLocation) Vec3f {
1625-
return self.normalDir;
1626-
}
1627-
inline fn major(self: BlockDropLocation) Vec3f {
1628-
return @abs(self.normalDir);
1629-
}
1630-
inline fn minors(self: BlockDropLocation) struct { Vec3f, Vec3f } {
1631-
const minor1 = vec.normalize(vec.cross(self.normalDir, if (@reduce(.And, @abs(self.normalDir) == Vec3f{1.0, 0.0, 0.0})) Vec3f{0.0, 1.0, 0.0} else Vec3f{1.0, 0.0, 0.0}));
1632-
const minor2 = vec.normalize(vec.cross(self.normalDir, minor1));
1633-
return .{minor1, minor2};
1634-
}
1635-
fn dropDir(self: BlockDropLocation) Vec3f {
1636-
const randomnessVec: Vec3f = main.random.nextFloatVectorSigned(3, &main.seed)*@as(Vec3f, @splat(0.25));
1637-
const directionVec: Vec3f = @as(Vec3f, @floatCast(self.direction())) + randomnessVec;
1638-
const z: f32 = directionVec[2];
1639-
return vec.normalize(Vec3f{
1640-
directionVec[0],
1641-
directionVec[1],
1642-
if (z < -0.5) 0 else if (z < 0.0) (z + 0.5)*4.0 else z + 2.0,
1643-
});
1644-
}
1645-
fn dropVelocity(self: BlockDropLocation) f32 {
1646-
const velocity = 3.5 + main.random.nextFloatSigned(&main.seed)*0.5;
1647-
if (self.direction()[2] < -0.5) return velocity*0.333;
1648-
return velocity;
1649-
}
1650-
};
1651-
16521576
fn run(self: UpdateBlock, ctx: Context) error{serverFailure}!void {
16531577
const stack = self.source.ref();
16541578

@@ -1704,16 +1628,12 @@ pub const Command = struct { // MARK: Command
17041628
},
17051629
}
17061630
if (ctx.side == .server and ctx.gamemode != .creative and shouldDropSourceBlockOnSuccess) {
1707-
const dropAmount = self.oldBlock.mode().itemDropsOnChange(self.oldBlock, self.newBlock);
1708-
for (0..dropAmount) |_| {
1709-
for (self.oldBlock.blockDrops()) |drop| {
1710-
if (!drop.isDroppedWhenBrokenWithItem(handItem)) continue;
1711-
1712-
if (drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
1713-
self.dropLocation.drop(self.pos, self.newBlock, drop);
1714-
}
1715-
}
1716-
}
1631+
const dropCtx = BlockDrop.Context{
1632+
.oldBlock = self.oldBlock,
1633+
.newBlock = self.newBlock,
1634+
.item = handItem,
1635+
};
1636+
dropCtx.drop(self.dropLocation, self.pos);
17171637
}
17181638
}
17191639

0 commit comments

Comments
 (0)