mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-12 14:01:59 -04:00
parent
8418202df8
commit
6473362c6e
5
assets/cubyz/items/chisel.json
Normal file
5
assets/cubyz/items/chisel.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"texture" : "special/chisel.png",
|
||||||
|
"stackSize" : 1,
|
||||||
|
"onLeftUse" : "chisel",
|
||||||
|
}
|
@ -91,7 +91,7 @@ pub const Player = struct {
|
|||||||
|
|
||||||
pub fn breakBlock() void { // TODO: Breaking animation and tools
|
pub fn breakBlock() void { // TODO: Breaking animation and tools
|
||||||
if(!main.Window.grabbed) return;
|
if(!main.Window.grabbed) return;
|
||||||
main.renderer.MeshSelection.breakBlock();
|
main.renderer.MeshSelection.breakBlock(&inventory__SEND_CHANGES_TO_SERVER.items[selectedSlot]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ const Mat4f = vec.Mat4f;
|
|||||||
const Vec2f = vec.Vec2f;
|
const Vec2f = vec.Vec2f;
|
||||||
const Vec2i = vec.Vec2i;
|
const Vec2i = vec.Vec2i;
|
||||||
const Vec3i = vec.Vec3i;
|
const Vec3i = vec.Vec3i;
|
||||||
|
const Vec3d = vec.Vec3d;
|
||||||
|
const Vec3f = vec.Vec3f;
|
||||||
const NeverFailingAllocator = main.utils.NeverFailingAllocator;
|
const NeverFailingAllocator = main.utils.NeverFailingAllocator;
|
||||||
|
|
||||||
/// Holds the basic properties of a tool crafting material.
|
/// Holds the basic properties of a tool crafting material.
|
||||||
@ -69,6 +71,8 @@ pub const BaseItem = struct {
|
|||||||
block: ?u16,
|
block: ?u16,
|
||||||
foodValue: f32, // TODO: Effects.
|
foodValue: f32, // TODO: Effects.
|
||||||
|
|
||||||
|
leftClickUse: ?*const fn(world: *main.game.World, pos: Vec3i, relativePlayerPos: Vec3d, playerDir: Vec3f, currentData: *Block) bool,
|
||||||
|
|
||||||
var unobtainable = BaseItem {
|
var unobtainable = BaseItem {
|
||||||
.image = graphics.Image.defaultImage,
|
.image = graphics.Image.defaultImage,
|
||||||
.texture = null,
|
.texture = null,
|
||||||
@ -78,6 +82,7 @@ pub const BaseItem = struct {
|
|||||||
.material = null,
|
.material = null,
|
||||||
.block = null,
|
.block = null,
|
||||||
.foodValue = 0,
|
.foodValue = 0,
|
||||||
|
.leftClickUse = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn init(self: *BaseItem, allocator: NeverFailingAllocator, texturePath: []const u8, replacementTexturePath: []const u8, id: []const u8, json: JsonElement) void {
|
fn init(self: *BaseItem, allocator: NeverFailingAllocator, texturePath: []const u8, replacementTexturePath: []const u8, id: []const u8, json: JsonElement) void {
|
||||||
@ -104,6 +109,14 @@ pub const BaseItem = struct {
|
|||||||
};
|
};
|
||||||
self.texture = null;
|
self.texture = null;
|
||||||
self.foodValue = json.get(f32, "food", 0);
|
self.foodValue = json.get(f32, "food", 0);
|
||||||
|
self.leftClickUse = if(std.mem.eql(u8, json.get([]const u8, "onLeftUse", ""), "chisel")) &chiselFunction else null; // TODO: Proper registry.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chiselFunction(world: *main.game.World, pos: Vec3i, relativePlayerPos: Vec3d, playerDir: Vec3f, currentData: *Block) bool {
|
||||||
|
if(currentData.mode() == main.rotation.getByID("stairs")) {
|
||||||
|
return main.rotation.RotationModes.Stairs.chisel(world, pos, relativePlayerPos, playerDir, currentData);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashCode(self: BaseItem) u32 {
|
fn hashCode(self: BaseItem) u32 {
|
||||||
|
@ -832,8 +832,25 @@ pub const MeshSelection = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn breakBlock() void {
|
pub fn breakBlock(inventoryStack: *main.items.ItemStack) void {
|
||||||
if(selectedBlockPos) |selectedPos| {
|
if(selectedBlockPos) |selectedPos| {
|
||||||
|
var block = mesh_storage.getBlockFromRenderThread(selectedPos[0], selectedPos[1], selectedPos[2]) orelse return;
|
||||||
|
// TODO: Breaking animation and tools.
|
||||||
|
if(inventoryStack.item) |item| {
|
||||||
|
switch(item) {
|
||||||
|
.baseItem => |baseItem| {
|
||||||
|
if(baseItem.leftClickUse) |leftClick| {
|
||||||
|
const relPos = lastPos - @as(Vec3d, @floatFromInt(selectedPos));
|
||||||
|
if(leftClick(main.game.world.?, selectedPos, relPos, lastDir, &block)) {
|
||||||
|
// TODO: world.updateBlock(bi.x, bi.y, bi.z, block.data); (→ Sending it over the network)
|
||||||
|
mesh_storage.updateBlock(selectedPos[0], selectedPos[1], selectedPos[2], block);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
mesh_storage.updateBlock(selectedPos[0], selectedPos[1], selectedPos[2], .{.typ = 0, .data = 0});
|
mesh_storage.updateBlock(selectedPos[0], selectedPos[1], selectedPos[2], .{.typ = 0, .data = 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ fn rotationMatrixTransform(quad: *main.models.QuadInfo, transformMatrix: Mat4f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RotationModes = struct {
|
pub const RotationModes = struct {
|
||||||
pub const NoRotation = struct {
|
pub const NoRotation = struct {
|
||||||
pub const id: []const u8 = "no_rotation";
|
pub const id: []const u8 = "no_rotation";
|
||||||
fn init() void {}
|
fn init() void {}
|
||||||
@ -196,8 +196,11 @@ const RotationModes = struct {
|
|||||||
pub const id: []const u8 = "stairs";
|
pub const id: []const u8 = "stairs";
|
||||||
var modelIndex: u16 = 0;
|
var modelIndex: u16 = 0;
|
||||||
|
|
||||||
|
fn subBlockMask(x: u1, y: u1, z: u1) u8 {
|
||||||
|
return @as(u8, 1) << ((@as(u3, x)*2 + @as(u3, y))*2 + z);
|
||||||
|
}
|
||||||
fn hasSubBlock(stairData: u8, x: u1, y: u1, z: u1) bool {
|
fn hasSubBlock(stairData: u8, x: u1, y: u1, z: u1) bool {
|
||||||
return stairData & @as(u8, 1) << ((@as(u3, x)*2 + @as(u3, y))*2 + z) == 0;
|
return stairData & subBlockMask(x, y, z) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init() void {
|
fn init() void {
|
||||||
@ -301,7 +304,7 @@ const RotationModes = struct {
|
|||||||
// Greedy mesh it:
|
// Greedy mesh it:
|
||||||
var faces: [2]GreedyFaceInfo = undefined;
|
var faces: [2]GreedyFaceInfo = undefined;
|
||||||
const frontFaces = mergeFaces(visibleFront, &faces);
|
const frontFaces = mergeFaces(visibleFront, &faces);
|
||||||
for(frontFaces) |face| {
|
for(frontFaces) |*face| {
|
||||||
var xLower = @abs(xAxis)*@as(Vec3f, @splat(face.min[0]));
|
var xLower = @abs(xAxis)*@as(Vec3f, @splat(face.min[0]));
|
||||||
var xUpper = @abs(xAxis)*@as(Vec3f, @splat(face.max[0]));
|
var xUpper = @abs(xAxis)*@as(Vec3f, @splat(face.max[0]));
|
||||||
if(@reduce(.Add, xAxis) > 0) std.mem.swap(Vec3f, &xLower, &xUpper);
|
if(@reduce(.Add, xAxis) > 0) std.mem.swap(Vec3f, &xLower, &xUpper);
|
||||||
@ -309,6 +312,25 @@ const RotationModes = struct {
|
|||||||
var yUpper = @abs(yAxis)*@as(Vec3f, @splat(face.max[1]));
|
var yUpper = @abs(yAxis)*@as(Vec3f, @splat(face.max[1]));
|
||||||
if(@reduce(.Add, yAxis) > 0) std.mem.swap(Vec3f, &yLower, &yUpper);
|
if(@reduce(.Add, yAxis) > 0) std.mem.swap(Vec3f, &yLower, &yUpper);
|
||||||
const zValue: Vec3f = @floatFromInt(zComponent*zMap[1]);
|
const zValue: Vec3f = @floatFromInt(zComponent*zMap[1]);
|
||||||
|
if(neighbor != chunk.Neighbors.dirUp) {
|
||||||
|
if(neighbor == chunk.Neighbors.dirNegX or neighbor == chunk.Neighbors.dirPosY) {
|
||||||
|
face.min[1] = 1 - face.min[1];
|
||||||
|
face.max[1] = 1 - face.max[1];
|
||||||
|
const swap = face.min[1];
|
||||||
|
face.min[1] = face.max[1];
|
||||||
|
face.max[1] = swap;
|
||||||
|
} else if(neighbor == chunk.Neighbors.dirDown) {
|
||||||
|
face.min[0] = 1 - face.min[0];
|
||||||
|
face.max[0] = 1 - face.max[0];
|
||||||
|
const swap = face.min[0];
|
||||||
|
face.min[0] = face.max[0];
|
||||||
|
face.max[0] = swap;
|
||||||
|
} else {
|
||||||
|
face.min = Vec2f{1, 1} - face.min;
|
||||||
|
face.max = Vec2f{1, 1} - face.max;
|
||||||
|
std.mem.swap(Vec2f, &face.min, &face.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
quads.append(.{
|
quads.append(.{
|
||||||
.normal = zAxis,
|
.normal = zAxis,
|
||||||
.corners = .{
|
.corners = .{
|
||||||
@ -322,7 +344,7 @@ const RotationModes = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const middleFaces = mergeFaces(visibleMiddle, &faces);
|
const middleFaces = mergeFaces(visibleMiddle, &faces);
|
||||||
for(middleFaces) |face| {
|
for(middleFaces) |*face| {
|
||||||
var xLower = @abs(xAxis)*@as(Vec3f, @splat(face.min[0]));
|
var xLower = @abs(xAxis)*@as(Vec3f, @splat(face.min[0]));
|
||||||
var xUpper = @abs(xAxis)*@as(Vec3f, @splat(face.max[0]));
|
var xUpper = @abs(xAxis)*@as(Vec3f, @splat(face.max[0]));
|
||||||
if(@reduce(.Add, xAxis) > 0) std.mem.swap(Vec3f, &xLower, &xUpper);
|
if(@reduce(.Add, xAxis) > 0) std.mem.swap(Vec3f, &xLower, &xUpper);
|
||||||
@ -330,6 +352,25 @@ const RotationModes = struct {
|
|||||||
var yUpper = @abs(yAxis)*@as(Vec3f, @splat(face.max[1]));
|
var yUpper = @abs(yAxis)*@as(Vec3f, @splat(face.max[1]));
|
||||||
if(@reduce(.Add, yAxis) > 0) std.mem.swap(Vec3f, &yLower, &yUpper);
|
if(@reduce(.Add, yAxis) > 0) std.mem.swap(Vec3f, &yLower, &yUpper);
|
||||||
const zValue = @as(Vec3f, @floatFromInt(zComponent))*@as(Vec3f, @splat(0.5));
|
const zValue = @as(Vec3f, @floatFromInt(zComponent))*@as(Vec3f, @splat(0.5));
|
||||||
|
if(neighbor != chunk.Neighbors.dirUp) {
|
||||||
|
if(neighbor == chunk.Neighbors.dirNegX or neighbor == chunk.Neighbors.dirPosY) {
|
||||||
|
face.min[1] = 1 - face.min[1];
|
||||||
|
face.max[1] = 1 - face.max[1];
|
||||||
|
const swap = face.min[1];
|
||||||
|
face.min[1] = face.max[1];
|
||||||
|
face.max[1] = swap;
|
||||||
|
} else if(neighbor == chunk.Neighbors.dirDown) {
|
||||||
|
face.min[0] = 1 - face.min[0];
|
||||||
|
face.max[0] = 1 - face.max[0];
|
||||||
|
const swap = face.min[0];
|
||||||
|
face.min[0] = face.max[0];
|
||||||
|
face.max[0] = swap;
|
||||||
|
} else {
|
||||||
|
face.min = Vec2f{1, 1} - face.min;
|
||||||
|
face.max = Vec2f{1, 1} - face.max;
|
||||||
|
std.mem.swap(Vec2f, &face.min, &face.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
quads.append(.{
|
quads.append(.{
|
||||||
.normal = zAxis,
|
.normal = zAxis,
|
||||||
.corners = .{
|
.corners = .{
|
||||||
@ -354,11 +395,49 @@ const RotationModes = struct {
|
|||||||
pub fn model(block: Block) u16 {
|
pub fn model(block: Block) u16 {
|
||||||
return blocks.meshes.modelIndexStart(block) + (block.data & 255);
|
return blocks.meshes.modelIndexStart(block) + (block.data & 255);
|
||||||
}
|
}
|
||||||
var data: u8 = 0;
|
|
||||||
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3d, _: Vec3f, _: Vec3i, currentData: *Block, blockPlacing: bool) bool {
|
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3d, _: Vec3f, _: Vec3i, currentData: *Block, blockPlacing: bool) bool {
|
||||||
if(blockPlacing) {
|
if(blockPlacing) {
|
||||||
currentData.data = data; // TODO: Set this to a full block and allow modifying the stairs with a chisel.
|
currentData.data = 0;
|
||||||
data +%= 1;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersectHalfUnitBox(start: Vec3f, invDir: Vec3f) ?f32 {
|
||||||
|
const t0 = start*invDir;
|
||||||
|
const t1 = (start + Vec3f{0.5, 0.5, 0.5})*invDir;
|
||||||
|
const entry = @reduce(.Max, @min(t0, t1));
|
||||||
|
const exit = @reduce(.Min, @max(t0, t1));
|
||||||
|
if(entry > exit or exit < 0) {
|
||||||
|
return null;
|
||||||
|
} else return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chisel(_: *main.game.World, _: Vec3i, relativePlayerPos: Vec3d, playerDir: Vec3f, currentData: *Block) bool {
|
||||||
|
const invDir = @as(Vec3f, @splat(1))/playerDir;
|
||||||
|
const relPos: Vec3f = @floatCast(-relativePlayerPos);
|
||||||
|
const data: u8 = @truncate(currentData.data);
|
||||||
|
var minT: f32 = std.math.floatMax(f32);
|
||||||
|
var minPos: @Vector(3, u1) = undefined;
|
||||||
|
for(0..8) |i| {
|
||||||
|
const subPos: @Vector(3, u1) = .{
|
||||||
|
@truncate(i >> 2),
|
||||||
|
@truncate(i >> 1),
|
||||||
|
@truncate(i),
|
||||||
|
};
|
||||||
|
if(hasSubBlock(data, subPos[0], subPos[1], subPos[2])) {
|
||||||
|
const relSubPos = relPos + @as(Vec3f, @floatFromInt(subPos))*@as(Vec3f, @splat(0.5));
|
||||||
|
if(intersectHalfUnitBox(relSubPos, invDir)) |t| {
|
||||||
|
if(t < minT) {
|
||||||
|
minT = t;
|
||||||
|
minPos = subPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(minT != std.math.floatMax(f32)) {
|
||||||
|
currentData.data = data | subBlockMask(minPos[0], minPos[1], minPos[2]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user