Add an ore rotation mode that allows you to put the ore on top of any other block.

fixes #611
This commit is contained in:
IntegratedQuantum 2025-01-30 21:37:03 +01:00
parent a414d49637
commit 38dcb5480e
15 changed files with 59 additions and 35 deletions

View File

@ -15,6 +15,7 @@
}, },
}, },
}, },
.allowOres = true,
.breakingPower = 1, .breakingPower = 1,
.rotation = .stairs, .rotation = .stairs,
.model = "cubyz:cube", .model = "cubyz:cube",

View File

@ -14,6 +14,7 @@
.drops = .{ .drops = .{
.{.items = .{"cubyz:coal"}}, .{.items = .{"cubyz:coal"}},
}, },
.rotation = .ore,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:coal_ore", .texture = "cubyz:coal_ore",
} }

View File

@ -14,6 +14,7 @@
.drops = .{ .drops = .{
.{.items = .{"cubyz:diamond"}}, .{.items = .{"cubyz:diamond"}},
}, },
.rotation = .ore,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:diamond_ore", .texture = "cubyz:diamond_ore",
} }

View File

@ -16,6 +16,7 @@
}, },
}, },
}, },
.allowOres = true,
.model = "cubyz:cube", .model = "cubyz:cube",
.rotation = .stairs, .rotation = .stairs,
.texture = "cubyz:ferrock", .texture = "cubyz:ferrock",

View File

@ -16,6 +16,7 @@
}, },
}, },
}, },
.allowOres = true,
.rotation = .stairs, .rotation = .stairs,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:glacite", .texture = "cubyz:glacite",

View File

@ -14,6 +14,7 @@
.drops = .{ .drops = .{
.{.items = .{.auto}}, .{.items = .{.auto}},
}, },
.rotation = .ore,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:iron_ore", .texture = "cubyz:iron_ore",
} }

View File

@ -16,6 +16,7 @@
}, },
}, },
}, },
.allowOres = true,
.rotation = .stairs, .rotation = .stairs,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:limestone", .texture = "cubyz:limestone",

View File

@ -15,6 +15,7 @@
}, },
}, },
}, },
.allowOres = true,
.rotation= .stairs, .rotation= .stairs,
.model= "cubyz:cube", .model= "cubyz:cube",
.texture= "cubyz:marble", .texture= "cubyz:marble",

View File

@ -15,6 +15,7 @@
}, },
}, },
}, },
.allowOres = true,
.rotation = .stairs, .rotation = .stairs,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:sandstone", .texture = "cubyz:sandstone",

View File

@ -16,6 +16,7 @@
}, },
}, },
}, },
.allowOres = true,
.rotation = .stairs, .rotation = .stairs,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:stone", .texture = "cubyz:stone",

View File

@ -16,6 +16,7 @@
}, },
}, },
}, },
.allowOres = true,
.rotation = .stairs, .rotation = .stairs,
.model = "cubyz:cube", .model = "cubyz:cube",
.texture = "cubyz:void_stone", .texture = "cubyz:void_stone",

View File

@ -47,15 +47,6 @@ pub const Ore = struct {
maxHeight: i32, maxHeight: i32,
blockType: u16, blockType: u16,
sources: []u16,
pub fn canCreateVeinInBlock(self: Ore, blockType: u16) bool {
for(self.sources) |source| {
if(blockType == source) return true;
}
return false;
}
}; };
var _transparent: [maxBlockCount]bool = undefined; var _transparent: [maxBlockCount]bool = undefined;
@ -84,20 +75,18 @@ var _lodReplacement: [maxBlockCount]u16 = undefined;
var _opaqueVariant: [maxBlockCount]u16 = undefined; var _opaqueVariant: [maxBlockCount]u16 = undefined;
var _friction: [maxBlockCount]f32 = undefined; var _friction: [maxBlockCount]f32 = undefined;
var _allowOres: [maxBlockCount]bool = 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;
pub var ores: main.List(Ore) = .init(allocator); pub var ores: main.List(Ore) = .init(allocator);
var unfinishedOreSourceBlockIds: main.List([][]const u8) = undefined;
pub fn init() void { pub fn init() void {
unfinishedOreSourceBlockIds = .init(main.globalAllocator);
} }
pub fn deinit() void { pub fn deinit() void {
unfinishedOreSourceBlockIds.deinit();
} }
pub fn register(_: []const u8, id: []const u8, zon: ZonElement) u16 { pub fn register(_: []const u8, id: []const u8, zon: ZonElement) u16 {
@ -124,23 +113,20 @@ pub fn register(_: []const u8, id: []const u8, zon: ZonElement) u16 {
_viewThrough[size] = zon.get(bool, "viewThrough", false) or _transparent[size] or _alwaysViewThrough[size]; _viewThrough[size] = zon.get(bool, "viewThrough", false) or _transparent[size] or _alwaysViewThrough[size];
_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);
const oreProperties = zon.getChild("ore"); const oreProperties = zon.getChild("ore");
if (oreProperties != .null) { if (oreProperties != .null) blk: {
// Extract the ids: if(!std.mem.eql(u8, zon.get([]const u8, "rotation", "no_rotation"), "ore")) {
const sourceBlocks = oreProperties.getChild("sources").toSlice(); std.log.err("Ore must have rotation mode \"ore\"!", .{});
const oreIds = main.globalAllocator.alloc([]const u8, sourceBlocks.len); break :blk;
for(sourceBlocks, oreIds) |source, *oreId| {
oreId.* = main.globalAllocator.dupe(u8, source.as([]const u8, ""));
} }
unfinishedOreSourceBlockIds.append(oreIds);
ores.append(Ore { ores.append(Ore {
.veins = oreProperties.get(f32, "veins", 0), .veins = oreProperties.get(f32, "veins", 0),
.size = oreProperties.get(f32, "size", 0), .size = oreProperties.get(f32, "size", 0),
.maxHeight = oreProperties.get(i32, "height", 0), .maxHeight = oreProperties.get(i32, "height", 0),
.density = oreProperties.get(f32, "density", 0.5), .density = oreProperties.get(f32, "density", 0.5),
.blockType = @intCast(size), .blockType = @intCast(size),
.sources = &.{},
}); });
} }
@ -209,15 +195,6 @@ pub fn finishBlocks(zonElements: std.StringHashMap(ZonElement)) void {
registerLodReplacement(i, zonElements.get(_id[i]) orelse continue); registerLodReplacement(i, zonElements.get(_id[i]) orelse continue);
registerOpaqueVariant(i, zonElements.get(_id[i]) orelse continue); registerOpaqueVariant(i, zonElements.get(_id[i]) orelse continue);
} }
for(ores.items, unfinishedOreSourceBlockIds.items) |*ore, oreIds| {
ore.sources = allocator.alloc(u16, oreIds.len);
for(ore.sources, oreIds) |*source, id| {
source.* = getTypeById(id);
main.globalAllocator.free(id);
}
main.globalAllocator.free(oreIds);
}
unfinishedOreSourceBlockIds.clearRetainingCapacity();
} }
pub fn reset() void { pub fn reset() void {
@ -226,7 +203,6 @@ pub fn reset() void {
meshes.reset(); meshes.reset();
_ = arena.reset(.free_all); _ = arena.reset(.free_all);
reverseIndices = .init(arena.allocator().allocator); reverseIndices = .init(arena.allocator().allocator);
std.debug.assert(unfinishedOreSourceBlockIds.items.len == 0);
} }
pub fn getTypeById(id: []const u8) u16 { pub fn getTypeById(id: []const u8) u16 {
@ -349,6 +325,10 @@ pub const Block = packed struct { // MARK: Block
return _friction[self.typ]; return _friction[self.typ];
} }
pub inline fn allowOres(self: Block) bool {
return _allowOres[self.typ];
}
pub fn canBeChangedInto(self: Block, newBlock: Block, item: main.items.ItemStack) main.rotation.RotationMode.CanBeChangedInto { pub fn canBeChangedInto(self: Block, newBlock: Block, item: main.items.ItemStack) main.rotation.RotationMode.CanBeChangedInto {
return newBlock.mode().canBeChangedInto(self, newBlock, item); return newBlock.mode().canBeChangedInto(self, newBlock, item);
} }
@ -501,7 +481,11 @@ pub const meshes = struct { // MARK: meshes
} }
pub inline fn textureIndex(block: Block, orientation: usize) u16 { pub inline fn textureIndex(block: Block, orientation: usize) u16 {
return textureData[block.typ].textureIndices[orientation]; if(orientation < 16) {
return textureData[block.typ].textureIndices[orientation];
} else {
return textureData[block.data].textureIndices[orientation - 16];
}
} }
fn extendedPath(_allocator: main.utils.NeverFailingAllocator, path: []const u8, ending: []const u8) []const u8 { fn extendedPath(_allocator: main.utils.NeverFailingAllocator, path: []const u8, ending: []const u8) []const u8 {

View File

@ -351,7 +351,7 @@ pub const Model = struct {
main.globalAllocator.free(self.internalQuads); main.globalAllocator.free(self.internalQuads);
} }
fn getRawFaces(model: Model, quadList: *main.List(QuadInfo)) void { pub fn getRawFaces(model: Model, quadList: *main.List(QuadInfo)) void {
for(model.internalQuads) |quadIndex| { for(model.internalQuads) |quadIndex| {
quadList.append(quads.items[quadIndex]); quadList.append(quads.items[quadIndex]);
} }

View File

@ -953,6 +953,34 @@ pub const RotationModes = struct {
return Torch.canBeChangedInto(oldBlock, newBlock, item); return Torch.canBeChangedInto(oldBlock, newBlock, item);
} }
}; };
pub const Ore = struct { // MARK: Ore
pub const id: []const u8 = "ore";
var modelCache: ?u16 = null;
fn init() void {}
fn deinit() void {}
pub fn createBlockModel(modelId: []const u8) u16 {
if(!std.mem.eql(u8, modelId, "cubyz:cube")) {
std.log.err("Ores can only be use on cube models.", .{modelId});
}
if(modelCache) |modelIndex| return modelIndex;
const baseModelIndex = main.models.getModelIndex("cubyz:cube");
const baseModel = main.models.models.items[baseModelIndex];
var quadList = main.List(main.models.QuadInfo).init(main.stackAllocator);
defer quadList.deinit();
baseModel.getRawFaces(&quadList);
const len = quadList.items.len;
for(0..len) |i| {
quadList.append(quadList.items[i]);
quadList.items[i + len].textureSlot += 16;
}
const modelIndex = main.models.Model.init(quadList.items);
modelCache = modelIndex;
return modelIndex;
}
};
}; };
// MARK: init/register // MARK: init/register

View File

@ -105,8 +105,9 @@ fn considerCoordinates(ore: *const main.blocks.Ore, relX: f32, relY: f32, relZ:
if(distSqr < 1) { if(distSqr < 1) {
// Add some roughness. The ore density gets smaller at the edges: // Add some roughness. The ore density gets smaller at the edges:
if((1 - distSqr)*ore.density >= random.nextFloat(&veinSeed)) { if((1 - distSqr)*ore.density >= random.nextFloat(&veinSeed)) {
if(ore.canCreateVeinInBlock(chunk.getBlock(curX, curY, curZ).typ)) { const stoneBlock = chunk.getBlock(curX, curY, curZ);
chunk.updateBlockInGeneration(curX, curY, curZ, .{.typ = ore.blockType, .data = 0}); if(chunk.getBlock(curX, curY, curZ).allowOres()) {
chunk.updateBlockInGeneration(curX, curY, curZ, .{.typ = ore.blockType, .data = stoneBlock.typ});
} }
} }
} }