mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -04:00

Resolves: #1600 --------- Co-authored-by: IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>
100 lines
3.3 KiB
Zig
100 lines
3.3 KiB
Zig
const std = @import("std");
|
|
|
|
const main = @import("main");
|
|
const blocks = main.blocks;
|
|
const Block = blocks.Block;
|
|
const Neighbor = main.chunk.Neighbor;
|
|
const ModelIndex = main.models.ModelIndex;
|
|
const rotation = main.rotation;
|
|
const RotationMode = rotation.RotationMode;
|
|
const vec = main.vec;
|
|
const Vec3f = vec.Vec3f;
|
|
const Vec3i = vec.Vec3i;
|
|
const ZonElement = main.ZonElement;
|
|
|
|
var rotatedModels: std.StringHashMap(ModelIndex) = undefined;
|
|
|
|
pub fn init() void {
|
|
rotatedModels = .init(main.globalAllocator.allocator);
|
|
}
|
|
|
|
pub fn deinit() void {
|
|
rotatedModels.deinit();
|
|
}
|
|
|
|
pub fn reset() void {
|
|
rotatedModels.clearRetainingCapacity();
|
|
}
|
|
|
|
fn transform(quad: *main.models.QuadInfo, data: u16) void {
|
|
quad.textureSlot = data%16;
|
|
}
|
|
|
|
pub fn createBlockModel(block: Block, modeData: *u16, zon: ZonElement) ModelIndex {
|
|
const modelId = zon.get([]const u8, "model", "cubyz:cube");
|
|
const stateCount = zon.get(u16, "states", 2);
|
|
const blockId = block.id();
|
|
if(stateCount <= 1) {
|
|
std.log.err("Block '{s}' uses texture pile with {} states. 'texturePile' should have at least 2 states, use 'no_rotation' instead", .{blockId, stateCount});
|
|
} else if(stateCount > 16) {
|
|
std.log.err("Block '{s}' uses texture pile with {} states. 'texturePile' can have at most 16 states.", .{blockId, stateCount});
|
|
}
|
|
modeData.* = stateCount;
|
|
|
|
if(rotatedModels.get(modelId)) |modelIndex| return modelIndex;
|
|
|
|
const baseModel = main.models.getModelIndex(modelId).model();
|
|
|
|
const modelIndex = baseModel.transformModel(transform, .{@as(u16, @intCast(0))});
|
|
for(1..16) |data| {
|
|
_ = baseModel.transformModel(transform, .{@as(u16, @intCast(data))});
|
|
}
|
|
rotatedModels.put(modelId, modelIndex) catch unreachable;
|
|
return modelIndex;
|
|
}
|
|
|
|
pub fn model(block: Block) ModelIndex {
|
|
return blocks.meshes.modelIndexStart(block).add(@min(block.data, block.modeData() - 1));
|
|
}
|
|
|
|
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, _: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool {
|
|
if(blockPlacing) {
|
|
currentData.data = 0;
|
|
return true;
|
|
}
|
|
if(currentData.data >= currentData.modeData() - 1) {
|
|
return false;
|
|
}
|
|
currentData.data = currentData.data + 1;
|
|
return true;
|
|
}
|
|
|
|
pub fn onBlockBreaking(_: ?main.items.Item, _: Vec3f, _: Vec3f, currentData: *Block) void {
|
|
if(currentData.data == 0) {
|
|
currentData.* = .{.typ = 0, .data = 0};
|
|
} else {
|
|
currentData.data = @min(currentData.data, currentData.modeData() - 1) - 1;
|
|
}
|
|
}
|
|
|
|
fn isItemBlock(block: Block, item: main.items.ItemStack) bool {
|
|
return item.item != null and item.item.? == .baseItem and item.item.?.baseItem.block() == block.typ;
|
|
}
|
|
|
|
pub fn canBeChangedInto(oldBlock: Block, newBlock: Block, item: main.items.ItemStack, shouldDropSourceBlockOnSuccess: *bool) RotationMode.CanBeChangedInto {
|
|
switch(RotationMode.DefaultFunctions.canBeChangedInto(oldBlock, newBlock, item, shouldDropSourceBlockOnSuccess)) {
|
|
.no, .yes_costsDurability, .yes_dropsItems => return .no,
|
|
.yes_costsItems => |r| return .{.yes_costsItems = r},
|
|
.yes => {
|
|
const oldAmount = if(oldBlock.typ == newBlock.typ) @min(oldBlock.data, oldBlock.modeData() - 1) else 0;
|
|
if(oldAmount == newBlock.data) return .no;
|
|
if(oldAmount < newBlock.data) {
|
|
if(!isItemBlock(newBlock, item)) return .no;
|
|
return .{.yes_costsItems = newBlock.data - oldAmount};
|
|
} else {
|
|
return .{.yes_dropsItems = oldAmount - newBlock.data};
|
|
}
|
|
},
|
|
}
|
|
}
|