Skip to content

Commit c8b82bf

Browse files
Create a checkSupportBlocks block update callback for torch decay instead of handling it through the rotation mode (#2459)
I'm open for better name suggestions. I considered merging this into the decay callback, but I think it makes more sense as a separate thing since it only looks at direct connections. In the future this could be extended to include carpet and signs. @careeoki should lanterns and signs break when their support block is broken? this is a first step towards #2330 and already demonstrates that this makes it more flexible, since now the addon author can decide how a block behaves when neighbor blocks are broken, instead of depending on the rotation mode code. fixes #1103
1 parent 7c1774f commit c8b82bf

File tree

9 files changed

+94
-33
lines changed

9 files changed

+94
-33
lines changed

assets/cubyz/blocks/bolete.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
.absorbedLight = 0x010101,
1111
.collide = false,
1212
.rotation = "cubyz:torch",
13+
.onUpdate = .{
14+
.type = .checkSupportBlocks,
15+
},
1316
.model = .{
1417
.base = "cubyz:bolete/floor",
1518
.side = "cubyz:bolete/shelf",

assets/cubyz/blocks/glimmergill.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
.emittedLight = 0x392862,
1212
.collide = false,
1313
.rotation = "cubyz:torch",
14+
.onUpdate = .{
15+
.type = .checkSupportBlocks,
16+
},
1417
.model = .{
1518
.base = "cubyz:glimmergill/floor",
1619
.side = "cubyz:glimmergill/shelf",

assets/cubyz/blocks/sulfur_torch.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
.absorbedLight = 0x010101,
1111
.collide = false,
1212
.rotation = "cubyz:torch",
13+
.onUpdate = .{
14+
.type = .checkSupportBlocks,
15+
},
1316
.model = .{
1417
.base = "cubyz:torch",
1518
.side = "cubyz:torch_side",

assets/cubyz/blocks/toadstool.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
.absorbedLight = 0x010101,
1111
.collide = false,
1212
.rotation = "cubyz:torch",
13+
.onUpdate = .{
14+
.type = .checkSupportBlocks,
15+
},
1316
.model = .{
1417
.base = "cubyz:toadstool/floor",
1518
.side = "cubyz:toadstool/shelf",

assets/cubyz/blocks/torch.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
.absorbedLight = 0x010101,
1111
.collide = false,
1212
.rotation = "cubyz:torch",
13+
.onUpdate = .{
14+
.type = .checkSupportBlocks,
15+
},
1316
.model = .{
1417
.base = "cubyz:torch",
1518
.side = "cubyz:torch_side",

mods/cubyz/rotation/torch.zig

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ const Vec3i = vec.Vec3i;
1616
const ZonElement = main.ZonElement;
1717

1818
pub const naturalStandard: u16 = 1;
19-
pub const dependsOnNeighbors = true;
2019
var rotatedModels: std.StringHashMap(ModelIndex) = undefined;
2120
const TorchData = packed struct(u5) {
2221
center: bool,
@@ -139,35 +138,6 @@ pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, relativeD
139138
}
140139
}
141140

142-
pub fn updateData(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool {
143-
const neighborModel = blocks.meshes.model(neighborBlock).model();
144-
const neighborSupport = !neighborBlock.replacable() and neighborModel.neighborFacingQuads[neighbor.reverse().toInt()].len != 0;
145-
var currentData: TorchData = @bitCast(@as(u5, @truncate(block.data)));
146-
switch(neighbor) {
147-
.dirNegX => {
148-
currentData.negX = currentData.negX and neighborSupport;
149-
},
150-
.dirPosX => {
151-
currentData.posX = currentData.posX and neighborSupport;
152-
},
153-
.dirNegY => {
154-
currentData.negY = currentData.negY and neighborSupport;
155-
},
156-
.dirPosY => {
157-
currentData.posY = currentData.posY and neighborSupport;
158-
},
159-
.dirDown => {
160-
currentData.center = currentData.center and neighborSupport;
161-
},
162-
else => {},
163-
}
164-
const result: u16 = @as(u5, @bitCast(currentData));
165-
if(result == block.data) return false;
166-
block.data = result;
167-
if(result == 0) block.typ = 0;
168-
return true;
169-
}
170-
171141
fn closestRay(comptime typ: enum {bit, intersection}, block: Block, _: main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) if(typ == .intersection) ?RayIntersectionResult else u16 {
172142
var result: ?RayIntersectionResult = null;
173143
var resultBit: u16 = 0;
@@ -210,3 +180,16 @@ pub fn canBeChangedInto(oldBlock: Block, newBlock: Block, item: main.items.ItemS
210180
},
211181
}
212182
}
183+
184+
// MARK: non-interface fns
185+
186+
pub fn updateBlockFromNeighborConnectivity(block: *Block, neighborSupportive: [6]bool) void {
187+
var data: main.rotation.list.@"cubyz:torch".TorchData = @bitCast(@as(u5, @truncate(block.data)));
188+
if(data.center and !neighborSupportive[Neighbor.dirDown.toInt()]) data.center = false;
189+
if(data.negX and !neighborSupportive[Neighbor.dirNegX.toInt()]) data.negX = false;
190+
if(data.posX and !neighborSupportive[Neighbor.dirPosX.toInt()]) data.posX = false;
191+
if(data.negY and !neighborSupportive[Neighbor.dirNegY.toInt()]) data.negY = false;
192+
if(data.posY and !neighborSupportive[Neighbor.dirPosY.toInt()]) data.posY = false;
193+
block.data = @as(u5, @bitCast(data));
194+
if(block.data == 0) block.typ = 0;
195+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
pub const checkSupportBlocks = @import("checkSupportBlocks.zig");
12
pub const decay = @import("decay.zig");
23
pub const replaceBlock = @import("replaceBlock.zig");
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const std = @import("std");
2+
3+
const main = @import("main");
4+
const Block = main.blocks.Block;
5+
const blocks = main.blocks;
6+
const Neighbor = main.chunk.Neighbor;
7+
const vec = main.vec;
8+
const Vec3i = vec.Vec3i;
9+
const Vec3d = vec.Vec3d;
10+
const Vec3f = vec.Vec3f;
11+
const ZonElement = main.ZonElement;
12+
const server = main.server;
13+
14+
pub fn init(_: ZonElement) ?*@This() {
15+
return @as(*@This(), undefined);
16+
}
17+
18+
pub fn run(_: *@This(), params: main.callbacks.ServerBlockCallback.Params) main.callbacks.Result {
19+
const wx = params.chunk.super.pos.wx + params.blockPos.x;
20+
const wy = params.chunk.super.pos.wy + params.blockPos.y;
21+
const wz = params.chunk.super.pos.wz + params.blockPos.z;
22+
23+
var neighborSupportive: [6]bool = undefined;
24+
25+
for(Neighbor.iterable) |neighbor| {
26+
const neighborBlock: Block = main.server.world.?.getBlock(wx +% neighbor.relX(), wy +% neighbor.relY(), wz +% neighbor.relZ()) orelse .{.typ = 0, .data = 0};
27+
const neighborModel = main.blocks.meshes.model(neighborBlock).model();
28+
neighborSupportive[neighbor.toInt()] = !neighborBlock.replacable() and neighborModel.neighborFacingQuads[neighbor.reverse().toInt()].len != 0;
29+
}
30+
31+
var newBlock: Block = params.block;
32+
33+
if(params.block.mode() == main.rotation.getByID("cubyz:torch")) {
34+
main.rotation.list.@"cubyz:torch".updateBlockFromNeighborConnectivity(&newBlock, neighborSupportive);
35+
} else {
36+
std.log.err("Expected {s} to have cubyz:torch as rotation", .{params.block.id()});
37+
}
38+
39+
if(newBlock == params.block) return .ignored;
40+
41+
if(main.server.world.?.cmpxchgBlock(wx, wy, wz, params.block, newBlock) == null) {
42+
const drops = params.block.blockDrops();
43+
for(drops) |drop| {
44+
if(drop.chance == 1 or main.random.nextFloat(&main.seed) < drop.chance) {
45+
for(drop.items) |stack| {
46+
var dir = main.vec.normalize(main.random.nextFloatVectorSigned(3, &main.seed));
47+
// Bias upwards
48+
dir[2] += main.random.nextFloat(&main.seed)*4.0;
49+
const model = params.block.mode().model(params.block).model();
50+
const pos = Vec3f{
51+
@as(f32, @floatFromInt(wx)) + model.min[0] + main.random.nextFloat(&main.seed)*(model.max[0] - model.min[0]),
52+
@as(f32, @floatFromInt(wy)) + model.min[1] + main.random.nextFloat(&main.seed)*(model.max[1] - model.min[1]),
53+
@as(f32, @floatFromInt(wz)) + model.min[2] + main.random.nextFloat(&main.seed)*(model.max[2] - model.min[2]),
54+
};
55+
main.server.world.?.drop(stack.clone(), pos, dir, 1);
56+
}
57+
}
58+
}
59+
return .handled;
60+
}
61+
return .ignored;
62+
}

src/callbacks/block/server/decay.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const Vec3i = vec.Vec3i;
88
const Vec3d = vec.Vec3d;
99
const Vec3f = vec.Vec3f;
1010
const ZonElement = main.ZonElement;
11-
const Server = main.server;
11+
const server = main.server;
1212
const Branch = main.rotation.list.@"cubyz:branch";
1313

1414
decayReplacement: blocks.Block,
@@ -57,7 +57,7 @@ fn preventsDecay(self: *@This(), log: Block) bool {
5757
}
5858
return false;
5959
}
60-
fn foundWayToLog(self: *@This(), world: *Server.ServerWorld, leaf: Block, wx: i32, wy: i32, wz: i32) bool {
60+
fn foundWayToLog(self: *@This(), world: *server.ServerWorld, leaf: Block, wx: i32, wy: i32, wz: i32) bool {
6161

6262
// init array to mark already searched blocks.
6363
const checkRange = 5;
@@ -125,7 +125,7 @@ pub fn run(self: *@This(), params: main.callbacks.ServerBlockCallback.Params) ma
125125
std.log.err("Expected {s} to have cubyz:decayable or cubyz:branch as rotation", .{params.block.id()});
126126
}
127127

128-
if(Server.world) |world| {
128+
if(server.world) |world| {
129129
if(world.getBlock(wx, wy, wz)) |leaf| {
130130
// check if there is any log in the proximity?^
131131
if(self.foundWayToLog(world, leaf, wx, wy, wz))

0 commit comments

Comments
 (0)