mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-04 03:37:59 -04:00
Add the player inventory(no gui yet), fix compile errors from last commit and fix a data race.
This commit is contained in:
parent
0f0b0b6ac4
commit
df36109ee5
@ -450,7 +450,7 @@ pub const meshing = struct {
|
|||||||
pub const ChunkMesh = struct {
|
pub const ChunkMesh = struct {
|
||||||
pos: ChunkPosition,
|
pos: ChunkPosition,
|
||||||
size: ChunkCoordinate,
|
size: ChunkCoordinate,
|
||||||
chunk: ?*Chunk,
|
chunk: std.atomic.Atomic(?*Chunk),
|
||||||
faces: std.ArrayList(u32),
|
faces: std.ArrayList(u32),
|
||||||
faceData: SSBO,
|
faceData: SSBO,
|
||||||
coreCount: u31 = 0,
|
coreCount: u31 = 0,
|
||||||
@ -465,7 +465,7 @@ pub const meshing = struct {
|
|||||||
.pos = pos,
|
.pos = pos,
|
||||||
.size = chunkSize*pos.voxelSize,
|
.size = chunkSize*pos.voxelSize,
|
||||||
.faces = std.ArrayList(u32).init(allocator),
|
.faces = std.ArrayList(u32).init(allocator),
|
||||||
.chunk = null,
|
.chunk = std.atomic.Atomic(?*Chunk).init(null),
|
||||||
.faceData = SSBO.init(),
|
.faceData = SSBO.init(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -473,7 +473,7 @@ pub const meshing = struct {
|
|||||||
pub fn deinit(self: *ChunkMesh) void {
|
pub fn deinit(self: *ChunkMesh) void {
|
||||||
self.faceData.deinit();
|
self.faceData.deinit();
|
||||||
self.faces.deinit();
|
self.faces.deinit();
|
||||||
if(self.chunk) |ch| {
|
if(self.chunk.load(.Monotonic)) |ch| {
|
||||||
renderer.RenderStructure.allocator.destroy(ch);
|
renderer.RenderStructure.allocator.destroy(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -544,10 +544,10 @@ pub const meshing = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self.chunk) |oldChunk| {
|
if(self.chunk.load(.Monotonic)) |oldChunk| {
|
||||||
renderer.RenderStructure.allocator.destroy(oldChunk);
|
renderer.RenderStructure.allocator.destroy(oldChunk);
|
||||||
}
|
}
|
||||||
self.chunk = chunk;
|
self.chunk.store(chunk, .Monotonic);
|
||||||
self.coreCount = @intCast(u31, self.faces.items.len);
|
self.coreCount = @intCast(u31, self.faces.items.len);
|
||||||
self.neighborStart = [_]u31{self.coreCount} ** 7;
|
self.neighborStart = [_]u31{self.coreCount} ** 7;
|
||||||
}
|
}
|
||||||
@ -625,7 +625,7 @@ pub const meshing = struct {
|
|||||||
self.mutex.lock();
|
self.mutex.lock();
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock();
|
||||||
if(!self.generated) return;
|
if(!self.generated) return;
|
||||||
const oldBlock = self.chunk.?.blocks[getIndex(x, y, z)];
|
const oldBlock = self.chunk.load(.Monotonic).?.blocks[getIndex(x, y, z)];
|
||||||
for(Neighbors.iterable) |neighbor| {
|
for(Neighbors.iterable) |neighbor| {
|
||||||
var neighborMesh = self;
|
var neighborMesh = self;
|
||||||
var nx = x + Neighbors.relX[neighbor];
|
var nx = x + Neighbors.relX[neighbor];
|
||||||
@ -640,7 +640,7 @@ pub const meshing = struct {
|
|||||||
nx &= chunkMask;
|
nx &= chunkMask;
|
||||||
ny &= chunkMask;
|
ny &= chunkMask;
|
||||||
nz &= chunkMask;
|
nz &= chunkMask;
|
||||||
const neighborBlock = neighborMesh.chunk.?.blocks[getIndex(nx, ny, nz)];
|
const neighborBlock = neighborMesh.chunk.load(.Monotonic).?.blocks[getIndex(nx, ny, nz)];
|
||||||
{
|
{
|
||||||
{ // The face of the changed block
|
{ // The face of the changed block
|
||||||
const newVisibility = canBeSeenThroughOtherBlock(newBlock, neighborBlock, neighbor);
|
const newVisibility = canBeSeenThroughOtherBlock(newBlock, neighborBlock, neighbor);
|
||||||
@ -701,7 +701,7 @@ pub const meshing = struct {
|
|||||||
}
|
}
|
||||||
if(neighborMesh != self) neighborMesh.uploadData();
|
if(neighborMesh != self) neighborMesh.uploadData();
|
||||||
}
|
}
|
||||||
self.chunk.?.blocks[getIndex(x, y, z)] = newBlock;
|
self.chunk.load(.Monotonic).?.blocks[getIndex(x, y, z)] = newBlock;
|
||||||
self.uploadData();
|
self.uploadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,7 +712,7 @@ pub const meshing = struct {
|
|||||||
|
|
||||||
pub fn uploadDataAndFinishNeighbors(self: *ChunkMesh) !void {
|
pub fn uploadDataAndFinishNeighbors(self: *ChunkMesh) !void {
|
||||||
std.debug.assert(!self.mutex.tryLock()); // The mutex should be locked when calling this function.
|
std.debug.assert(!self.mutex.tryLock()); // The mutex should be locked when calling this function.
|
||||||
if(self.chunk == null) return; // In the mean-time the mesh was discarded and recreated and all the data was lost.
|
const chunk = self.chunk.load(.Monotonic) orelse return; // In the mean-time the mesh was discarded and recreated and all the data was lost.
|
||||||
self.faces.shrinkRetainingCapacity(self.coreCount);
|
self.faces.shrinkRetainingCapacity(self.coreCount);
|
||||||
for(Neighbors.iterable) |neighbor| {
|
for(Neighbors.iterable) |neighbor| {
|
||||||
self.neighborStart[neighbor] = @intCast(u31, self.faces.items.len);
|
self.neighborStart[neighbor] = @intCast(u31, self.faces.items.len);
|
||||||
@ -748,8 +748,8 @@ pub const meshing = struct {
|
|||||||
var otherX = @intCast(u8, x+%Neighbors.relX[neighbor] & chunkMask);
|
var otherX = @intCast(u8, x+%Neighbors.relX[neighbor] & chunkMask);
|
||||||
var otherY = @intCast(u8, y+%Neighbors.relY[neighbor] & chunkMask);
|
var otherY = @intCast(u8, y+%Neighbors.relY[neighbor] & chunkMask);
|
||||||
var otherZ = @intCast(u8, z+%Neighbors.relZ[neighbor] & chunkMask);
|
var otherZ = @intCast(u8, z+%Neighbors.relZ[neighbor] & chunkMask);
|
||||||
var block = (&self.chunk.?.blocks)[getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
var block = (&chunk.blocks)[getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
||||||
var otherBlock = (&neighborMesh.chunk.?.blocks)[getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
var otherBlock = (&neighborMesh.chunk.load(.Monotonic).?.blocks)[getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
||||||
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
||||||
const normal: u32 = neighbor;
|
const normal: u32 = neighbor;
|
||||||
const position: u32 = @as(u32, otherX) | @as(u32, otherY)<<5 | @as(u32, otherZ)<<10 | normal<<24;
|
const position: u32 = @as(u32, otherX) | @as(u32, otherY)<<5 | @as(u32, otherZ)<<10 | normal<<24;
|
||||||
@ -810,8 +810,8 @@ pub const meshing = struct {
|
|||||||
var otherX = @intCast(u8, (x+%Neighbors.relX[neighbor]+%offsetX >> 1) & chunkMask);
|
var otherX = @intCast(u8, (x+%Neighbors.relX[neighbor]+%offsetX >> 1) & chunkMask);
|
||||||
var otherY = @intCast(u8, (y+%Neighbors.relY[neighbor]+%offsetY >> 1) & chunkMask);
|
var otherY = @intCast(u8, (y+%Neighbors.relY[neighbor]+%offsetY >> 1) & chunkMask);
|
||||||
var otherZ = @intCast(u8, (z+%Neighbors.relZ[neighbor]+%offsetZ >> 1) & chunkMask);
|
var otherZ = @intCast(u8, (z+%Neighbors.relZ[neighbor]+%offsetZ >> 1) & chunkMask);
|
||||||
var block = (&self.chunk.?.blocks)[getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
var block = (&chunk.blocks)[getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
||||||
var otherBlock = (&neighborMesh.chunk.?.blocks)[getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
var otherBlock = (&neighborMesh.chunk.load(.Monotonic).?.blocks)[getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
||||||
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
||||||
const normal: u32 = neighbor ^ 1;
|
const normal: u32 = neighbor ^ 1;
|
||||||
const position: u32 = @as(u32, x) | @as(u32, y)<<5 | @as(u32, z)<<10 | normal<<24;
|
const position: u32 = @as(u32, x) | @as(u32, y)<<5 | @as(u32, z)<<10 | normal<<24;
|
||||||
|
@ -2,6 +2,8 @@ const std = @import("std");
|
|||||||
|
|
||||||
const assets = @import("assets.zig");
|
const assets = @import("assets.zig");
|
||||||
const chunk = @import("chunk.zig");
|
const chunk = @import("chunk.zig");
|
||||||
|
const items = @import("items.zig");
|
||||||
|
const Inventory = items.Inventory;
|
||||||
const json = @import("json.zig");
|
const json = @import("json.zig");
|
||||||
const JsonElement = json.JsonElement;
|
const JsonElement = json.JsonElement;
|
||||||
const main = @import("main.zig");
|
const main = @import("main.zig");
|
||||||
@ -46,7 +48,8 @@ pub const Player = struct {
|
|||||||
var vel: Vec3d = Vec3d{0, 0, 0};
|
var vel: Vec3d = Vec3d{0, 0, 0};
|
||||||
pub var id: u32 = 0;
|
pub var id: u32 = 0;
|
||||||
pub var isFlying: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true);
|
pub var isFlying: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true);
|
||||||
var mutex: std.Thread.Mutex = std.Thread.Mutex{};
|
pub var mutex: std.Thread.Mutex = std.Thread.Mutex{};
|
||||||
|
pub var inventory__SEND_CHANGES_TO_SERVER: Inventory = undefined;
|
||||||
|
|
||||||
pub fn setPosBlocking(newPos: Vec3d) void {
|
pub fn setPosBlocking(newPos: Vec3d) void {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
@ -92,6 +95,7 @@ pub const World = struct {
|
|||||||
.name = "client",
|
.name = "client",
|
||||||
.milliTime = std.time.milliTimestamp(),
|
.milliTime = std.time.milliTimestamp(),
|
||||||
};
|
};
|
||||||
|
Player.inventory__SEND_CHANGES_TO_SERVER = try Inventory.init(renderer.RenderStructure.allocator, 32);
|
||||||
// TODO:
|
// TODO:
|
||||||
// super.itemEntityManager = new InterpolatedItemEntityManager(this);
|
// super.itemEntityManager = new InterpolatedItemEntityManager(this);
|
||||||
// player = new ClientPlayer(this, 0);
|
// player = new ClientPlayer(this, 0);
|
||||||
@ -100,6 +104,7 @@ pub const World = struct {
|
|||||||
|
|
||||||
pub fn deinit(self: *World) void {
|
pub fn deinit(self: *World) void {
|
||||||
self.conn.deinit();
|
self.conn.deinit();
|
||||||
|
Player.inventory__SEND_CHANGES_TO_SERVER.deinit(renderer.RenderStructure.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finishHandshake(self: *World, jsonObject: JsonElement) !void {
|
pub fn finishHandshake(self: *World, jsonObject: JsonElement) !void {
|
||||||
|
@ -660,6 +660,12 @@ pub const Image = struct {
|
|||||||
stb_image.stbi_image_free(data);
|
stb_image.stbi_image_free(data);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
pub fn setRGB(self: Image, x: usize, y: usize, rgb: Color) void {
|
||||||
|
std.debug.assert(x < self.width);
|
||||||
|
std.debug.assert(y < self.height);
|
||||||
|
const index = x + y*self.width;
|
||||||
|
self.imageData[index] = rgb;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Fog = struct {
|
pub const Fog = struct {
|
||||||
|
545
src/items.zig
545
src/items.zig
@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
const blocks = @import("blocks.zig");
|
const blocks = @import("blocks.zig");
|
||||||
const Block = blocks.Block;
|
const Block = blocks.Block;
|
||||||
const graphics = @import("graphics.zig");
|
const graphics = @import("graphics.zig");
|
||||||
|
const Color = graphics.Color;
|
||||||
const json = @import("json.zig");
|
const json = @import("json.zig");
|
||||||
const JsonElement = json.JsonElement;
|
const JsonElement = json.JsonElement;
|
||||||
const main = @import("main.zig");
|
const main = @import("main.zig");
|
||||||
@ -26,7 +27,7 @@ const Material = struct {
|
|||||||
/// How rough the texture should look.
|
/// How rough the texture should look.
|
||||||
roughness: f32 = undefined,
|
roughness: f32 = undefined,
|
||||||
/// The colors that are used to make tool textures.
|
/// The colors that are used to make tool textures.
|
||||||
colorPalette: []u32 = undefined,
|
colorPalette: []Color = undefined,
|
||||||
|
|
||||||
pub fn init(self: *Material, allocator: Allocator, jsonObject: JsonElement) !void {
|
pub fn init(self: *Material, allocator: Allocator, jsonObject: JsonElement) !void {
|
||||||
self.density = jsonObject.get(f32, "density", 1.0);
|
self.density = jsonObject.get(f32, "density", 1.0);
|
||||||
@ -34,9 +35,15 @@ const Material = struct {
|
|||||||
self.power = jsonObject.get(f32, "power", 1.0);
|
self.power = jsonObject.get(f32, "power", 1.0);
|
||||||
self.roughness = @max(0, jsonObject.get(f32, "roughness", 1.0));
|
self.roughness = @max(0, jsonObject.get(f32, "roughness", 1.0));
|
||||||
const colors = jsonObject.getChild("colors");
|
const colors = jsonObject.getChild("colors");
|
||||||
self.colorPalette = try allocator.alloc(u32, colors.JsonArray.items.len);
|
self.colorPalette = try allocator.alloc(Color, colors.JsonArray.items.len);
|
||||||
for(colors.JsonArray.items) |item, i| {
|
for(colors.JsonArray.items) |item, i| {
|
||||||
self.colorPalette[i] = item.as(u32, 0xff000000);
|
const colorInt = item.as(u32, 0xff000000);
|
||||||
|
self.colorPalette[i] = Color {
|
||||||
|
.r = @intCast(u8, colorInt>>16 & 0xff),
|
||||||
|
.g = @intCast(u8, colorInt>>8 & 0xff),
|
||||||
|
.b = @intCast(u8, colorInt>>0 & 0xff),
|
||||||
|
.a = @intCast(u8, colorInt>>24 & 0xff),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +164,7 @@ const TextureGenerator = struct {
|
|||||||
.items = std.ArrayList(*const BaseItem).init(allocator),
|
.items = std.ArrayList(*const BaseItem).init(allocator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn deinit(self: PixelData) void {
|
pub fn deinit(self: *PixelData) void {
|
||||||
self.items.clearAndFree();
|
self.items.clearAndFree();
|
||||||
}
|
}
|
||||||
pub fn add(self: *PixelData, item: *const BaseItem, neighbors: u8) !void {
|
pub fn add(self: *PixelData, item: *const BaseItem, neighbors: u8) !void {
|
||||||
@ -175,180 +182,182 @@ const TextureGenerator = struct {
|
|||||||
fn countNeighbors(relativeGrid: *[25]?*const BaseItem) u8 {
|
fn countNeighbors(relativeGrid: *[25]?*const BaseItem) u8 {
|
||||||
var neighbors: u8 = 0;
|
var neighbors: u8 = 0;
|
||||||
// direct neighbors count 1.5 times as much.
|
// direct neighbors count 1.5 times as much.
|
||||||
if (relativeGrid[7]) neighbors += 3;
|
if(relativeGrid[7] != null) neighbors += 3;
|
||||||
if (relativeGrid[11]) neighbors += 3;
|
if(relativeGrid[11] != null) neighbors += 3;
|
||||||
if (relativeGrid[13]) neighbors += 3;
|
if(relativeGrid[13] != null) neighbors += 3;
|
||||||
if (relativeGrid[17]) neighbors += 3;
|
if(relativeGrid[17] != null) neighbors += 3;
|
||||||
|
|
||||||
if (relativeGrid[6]) neighbors += 2;
|
if(relativeGrid[6] != null) neighbors += 2;
|
||||||
if (relativeGrid[8]) neighbors += 2;
|
if(relativeGrid[8] != null) neighbors += 2;
|
||||||
if (relativeGrid[16]) neighbors += 2;
|
if(relativeGrid[16] != null) neighbors += 2;
|
||||||
if (relativeGrid[18]) neighbors += 2;
|
if(relativeGrid[18] != null) neighbors += 2;
|
||||||
|
|
||||||
|
return neighbors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This part is responsible for associating each pixel with an item.
|
/// This part is responsible for associating each pixel with an item.
|
||||||
fn drawRegion(relativeGrid: *[25]?*const BaseItem, relativeNeighborCount: *[25]u8, x: u8, y: u8, pixels: *[16][16]PixelData) void {
|
fn drawRegion(relativeGrid: *[25]?*const BaseItem, relativeNeighborCount: *[25]u8, x: u8, y: u8, pixels: *[16][16]PixelData) !void {
|
||||||
if(relativeGrid[12]) |item| {
|
if(relativeGrid[12]) |item| {
|
||||||
// Count diagonal and straight neighbors:
|
// Count diagonal and straight neighbors:
|
||||||
var diagonalNeighbors: u8 = 0;
|
var diagonalNeighbors: u8 = 0;
|
||||||
var straightNeighbors: u8 = 0;
|
var straightNeighbors: u8 = 0;
|
||||||
if (relativeGrid[7]) straightNeighbors += 1;
|
if(relativeGrid[7] != null) straightNeighbors += 1;
|
||||||
if (relativeGrid[11]) straightNeighbors += 1;
|
if(relativeGrid[11] != null) straightNeighbors += 1;
|
||||||
if (relativeGrid[13]) straightNeighbors += 1;
|
if(relativeGrid[13] != null) straightNeighbors += 1;
|
||||||
if (relativeGrid[17]) straightNeighbors += 1;
|
if(relativeGrid[17] != null) straightNeighbors += 1;
|
||||||
|
|
||||||
if (relativeGrid[6]) diagonalNeighbors += 1;
|
if(relativeGrid[6] != null) diagonalNeighbors += 1;
|
||||||
if (relativeGrid[8]) diagonalNeighbors += 1;
|
if(relativeGrid[8] != null) diagonalNeighbors += 1;
|
||||||
if (relativeGrid[16]) diagonalNeighbors += 1;
|
if(relativeGrid[16] != null) diagonalNeighbors += 1;
|
||||||
if (relativeGrid[18]) diagonalNeighbors += 1;
|
if(relativeGrid[18] != null) diagonalNeighbors += 1;
|
||||||
|
|
||||||
const neighbors = diagonalNeighbors + straightNeighbors;
|
const neighbors = diagonalNeighbors + straightNeighbors;
|
||||||
|
|
||||||
pixels[x + 1][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 1][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
|
|
||||||
// Checkout straight neighbors:
|
// Checkout straight neighbors:
|
||||||
if(relativeGrid[7]) {
|
if(relativeGrid[7] != null) {
|
||||||
if(relativeNeighborCount[7] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[7] >= relativeNeighborCount[12]) {
|
||||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[1] and !relativeGrid[16] and straightNeighbors <= 1) {
|
if(relativeGrid[1] != null and relativeGrid[16] == null and straightNeighbors <= 1) {
|
||||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[3] and !relativeGrid[18] and straightNeighbors <= 1) {
|
if(relativeGrid[3] != null and relativeGrid[18] == null and straightNeighbors <= 1) {
|
||||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relativeGrid[11]) {
|
if(relativeGrid[11] != null) {
|
||||||
if(relativeNeighborCount[11] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[11] >= relativeNeighborCount[12]) {
|
||||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[5] and !relativeGrid[8] and straightNeighbors <= 1) {
|
if(relativeGrid[5] != null and relativeGrid[8] == null and straightNeighbors <= 1) {
|
||||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[15] and !relativeGrid[18] and straightNeighbors <= 1) {
|
if(relativeGrid[15] != null and relativeGrid[18] == null and straightNeighbors <= 1) {
|
||||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relativeGrid[13]) {
|
if(relativeGrid[13] != null) {
|
||||||
if(relativeNeighborCount[13] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[13] >= relativeNeighborCount[12]) {
|
||||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[9] and !relativeGrid[6] and straightNeighbors <= 1) {
|
if(relativeGrid[9] != null and relativeGrid[6] == null and straightNeighbors <= 1) {
|
||||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[19] and !relativeGrid[16] and straightNeighbors <= 1) {
|
if(relativeGrid[19] != null and relativeGrid[16] == null and straightNeighbors <= 1) {
|
||||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relativeGrid[17]) {
|
if(relativeGrid[17] != null) {
|
||||||
if(relativeNeighborCount[17] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[17] >= relativeNeighborCount[12]) {
|
||||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[21] and !relativeGrid[6] and straightNeighbors <= 1) {
|
if(relativeGrid[21] != null and relativeGrid[6] == null and straightNeighbors <= 1) {
|
||||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[23] and !relativeGrid[8] and straightNeighbors <= 1) {
|
if(relativeGrid[23] != null and relativeGrid[8] == null and straightNeighbors <= 1) {
|
||||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkout diagonal neighbors:
|
// Checkout diagonal neighbors:
|
||||||
if (relativeGrid[6]) {
|
if(relativeGrid[6] != null) {
|
||||||
if(relativeNeighborCount[6] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[6] >= relativeNeighborCount[12]) {
|
||||||
pixels[x][y].add(item, relativeNeighborCount[12]);
|
try pixels[x][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
if (relativeGrid[1] and !relativeGrid[7] and neighbors <= 2) {
|
if(relativeGrid[1] != null and relativeGrid[7] == null and neighbors <= 2) {
|
||||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[5] and !relativeGrid[11] and neighbors <= 2) {
|
if(relativeGrid[5] != null and relativeGrid[11] == null and neighbors <= 2) {
|
||||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relativeGrid[8]) {
|
if(relativeGrid[8] != null) {
|
||||||
if(relativeNeighborCount[8] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[8] >= relativeNeighborCount[12]) {
|
||||||
pixels[x + 3][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
if (relativeGrid[3] and !relativeGrid[7] and neighbors <= 2) {
|
if(relativeGrid[3] != null and relativeGrid[7] == null and neighbors <= 2) {
|
||||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[9] and !relativeGrid[13] and neighbors <= 2) {
|
if(relativeGrid[9] != null and relativeGrid[13] == null and neighbors <= 2) {
|
||||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relativeGrid[16]) {
|
if(relativeGrid[16] != null) {
|
||||||
if(relativeNeighborCount[16] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[16] >= relativeNeighborCount[12]) {
|
||||||
pixels[x][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
if (relativeGrid[21] and !relativeGrid[17] and neighbors <= 2) {
|
if(relativeGrid[21] != null and relativeGrid[17] == null and neighbors <= 2) {
|
||||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[15] and !relativeGrid[11] and neighbors <= 2) {
|
if(relativeGrid[15] != null and relativeGrid[11] == null and neighbors <= 2) {
|
||||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relativeGrid[18]) {
|
if(relativeGrid[18] != null) {
|
||||||
if(relativeNeighborCount[18] >= relativeNeighborCount[12]) {
|
if(relativeNeighborCount[18] >= relativeNeighborCount[12]) {
|
||||||
pixels[x + 3][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
if (relativeGrid[23] and !relativeGrid[17] and neighbors <= 2) {
|
if(relativeGrid[23] != null and relativeGrid[17] == null and neighbors <= 2) {
|
||||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if (relativeGrid[19] and !relativeGrid[13] and neighbors <= 2) {
|
if(relativeGrid[19] != null and relativeGrid[13] == null and neighbors <= 2) {
|
||||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make stuff more round when there is many incoming connections:
|
// Make stuff more round when there is many incoming connections:
|
||||||
if(diagonalNeighbors >= 3 or straightNeighbors == 4) {
|
if(diagonalNeighbors >= 3 or straightNeighbors == 4) {
|
||||||
pixels[x + 0][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 0][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 0][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 0][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 1][y + 0].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 0].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y + 0].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 0].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
// Check which of the neighbors was empty:
|
// Check which of the neighbors was empty:
|
||||||
if(relativeGrid[6] == null) {
|
if(relativeGrid[6] == null) {
|
||||||
pixels[x + 0][y + 0].add(item, relativeNeighborCount[12]);
|
try pixels[x + 0][y + 0].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y - 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y - 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x - 1][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x - 1][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if(relativeGrid[8] == null) {
|
if(relativeGrid[8] == null) {
|
||||||
pixels[x + 3][y + 0].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 0].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 1][y - 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y - 1].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 4][y + 2].add(item, relativeNeighborCount[12]);
|
try pixels[x + 4][y + 2].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if(relativeGrid[16] == null) {
|
if(relativeGrid[16] == null) {
|
||||||
pixels[x + 0][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 0][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 2][y + 4].add(item, relativeNeighborCount[12]);
|
try pixels[x + 2][y + 4].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x - 1][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x - 1][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
if(relativeGrid[18] == null) {
|
if(relativeGrid[18] == null) {
|
||||||
pixels[x + 3][y + 3].add(item, relativeNeighborCount[12]);
|
try pixels[x + 3][y + 3].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 1][y + 4].add(item, relativeNeighborCount[12]);
|
try pixels[x + 1][y + 4].add(item, relativeNeighborCount[12]);
|
||||||
pixels[x + 4][y + 1].add(item, relativeNeighborCount[12]);
|
try pixels[x + 4][y + 1].add(item, relativeNeighborCount[12]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generateHeightMap(itemGrid: *[16][16]?*BaseItem, seed: *u64) [17][17]f32 {
|
fn generateHeightMap(itemGrid: *[16][16]?*const BaseItem, seed: *u64) [17][17]f32 {
|
||||||
var heightMap: [17][17]f32 = undefined;
|
var heightMap: [17][17]f32 = undefined;
|
||||||
var x: u8 = 0;
|
var x: u8 = 0;
|
||||||
while(x < 17) : (x += 1) {
|
while(x < 17) : (x += 1) {
|
||||||
@ -366,7 +375,7 @@ const TextureGenerator = struct {
|
|||||||
while(dy <= 0) : (dy += 1) {
|
while(dy <= 0) : (dy += 1) {
|
||||||
if(y + dy < 0 or y + dy >= 16) continue;
|
if(y + dy < 0 or y + dy >= 16) continue;
|
||||||
const otherItem = itemGrid[@intCast(usize, x + dx)][@intCast(usize, y + dy)];
|
const otherItem = itemGrid[@intCast(usize, x + dx)][@intCast(usize, y + dy)];
|
||||||
heightMap[x][y] = if(otherItem) |item| 1 + (4*random.nextFloat(seed) - 2)*item.material.roughness else 0;
|
heightMap[x][y] = if(otherItem) |item| (if(item.material) |material| 1 + (4*random.nextFloat(seed) - 2)*material.roughness else 0) else 0;
|
||||||
if(otherItem != oneItem) {
|
if(otherItem != oneItem) {
|
||||||
hasDifferentItems = true;
|
hasDifferentItems = true;
|
||||||
}
|
}
|
||||||
@ -387,7 +396,7 @@ const TextureGenerator = struct {
|
|||||||
if(y + dy < 0 or y + dy >= 16) continue;
|
if(y + dy < 0 or y + dy >= 16) continue;
|
||||||
const otherItem = itemGrid[@intCast(usize, x + dx)][@intCast(usize, y + dy)];
|
const otherItem = itemGrid[@intCast(usize, x + dx)][@intCast(usize, y + dy)];
|
||||||
const dVec = Vec2f{@intToFloat(f32, dx) + 0.5, @intToFloat(f32, dy) + 0.5};
|
const dVec = Vec2f{@intToFloat(f32, dx) + 0.5, @intToFloat(f32, dy) + 0.5};
|
||||||
heightMap[x][y] += if(otherItem) 1.0/vec.dot(dVec, dVec) else 0;
|
heightMap[x][y] += if(otherItem != null) 1.0/vec.dot(dVec, dVec) else 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,7 +404,7 @@ const TextureGenerator = struct {
|
|||||||
return heightMap;
|
return heightMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(tool: *Tool) void {
|
pub fn generate(tool: *Tool) !void {
|
||||||
const img = tool.texture;
|
const img = tool.texture;
|
||||||
var pixelMaterials: [16][16]PixelData = undefined;
|
var pixelMaterials: [16][16]PixelData = undefined;
|
||||||
var x: u8 = 0;
|
var x: u8 = 0;
|
||||||
@ -462,7 +471,7 @@ const TextureGenerator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const index = x + 5*y;
|
const index = x + 5*y;
|
||||||
drawRegion(&offsetGrid, &offsetNeighborCount, GRID_CENTERS_X[index] - 2, GRID_CENTERS_Y[index] - 2, pixelMaterials);
|
try drawRegion(&offsetGrid, &offsetNeighborCount, GRID_CENTERS_X[index] - 2, GRID_CENTERS_Y[index] - 2, &pixelMaterials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +482,9 @@ const TextureGenerator = struct {
|
|||||||
while(y < 16) : (y += 1) {
|
while(y < 16) : (y += 1) {
|
||||||
if(pixelMaterials[x][y].items.items.len != 0) {
|
if(pixelMaterials[x][y].items.items.len != 0) {
|
||||||
// Choose a random material at conflict zones:
|
// Choose a random material at conflict zones:
|
||||||
itemGrid[x][y] = pixelMaterials[x][y].items.items[random.nextIntBounded(u8, &seed, pixelMaterials[x][y].items.items.len)];
|
itemGrid[x][y] = pixelMaterials[x][y].items.items[random.nextIntBounded(u8, &seed, @intCast(u8, pixelMaterials[x][y].items.items.len))];
|
||||||
|
} else {
|
||||||
|
itemGrid[x][y] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,7 +500,7 @@ const TextureGenerator = struct {
|
|||||||
// Calculate the lighting based on the nearest free space:
|
// Calculate the lighting based on the nearest free space:
|
||||||
const lightTL = heightMap[x][y] - heightMap[x + 1][y + 1];
|
const lightTL = heightMap[x][y] - heightMap[x + 1][y + 1];
|
||||||
const lightTR = heightMap[x + 1][y] - heightMap[x][y + 1];
|
const lightTR = heightMap[x + 1][y] - heightMap[x][y + 1];
|
||||||
const light = 2 - @floatToInt(u32, @round((lightTL * 2 + lightTR) / 6));
|
var light = 2 - @floatToInt(u32, @round((lightTL * 2 + lightTR) / 6));
|
||||||
light = @max(@min(light, 4), 0);
|
light = @max(@min(light, 4), 0);
|
||||||
img.setRGB(x, y, material.colorPalette[light]);
|
img.setRGB(x, y, material.colorPalette[light]);
|
||||||
}
|
}
|
||||||
@ -513,7 +524,7 @@ const ToolPhysics = struct {
|
|||||||
while(y > 0) : (y -= 5) {
|
while(y > 0) : (y -= 5) {
|
||||||
var x: u32 = 0;
|
var x: u32 = 0;
|
||||||
while(x < 5) : (x += 5) {
|
while(x < 5) : (x += 5) {
|
||||||
if(tool.craftingGrid[y + x]) {
|
if(tool.craftingGrid[y + x] != null) {
|
||||||
break :outer;
|
break :outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -523,21 +534,21 @@ const ToolPhysics = struct {
|
|||||||
// TODO: Add left-hander setting that mirrors the x axis of the tools and the crafting grid
|
// TODO: Add left-hander setting that mirrors the x axis of the tools and the crafting grid
|
||||||
var x: u32 = 4;
|
var x: u32 = 4;
|
||||||
while(true) {
|
while(true) {
|
||||||
if(tool.craftingGrid[y + x]) {
|
if(tool.craftingGrid[y + x] != null) {
|
||||||
tool.handlePosition.x = TextureGenerator.GRID_CENTERS_X[x + y] - 0.5;
|
tool.handlePosition[0] = @intToFloat(f32, TextureGenerator.GRID_CENTERS_X[x + y]) - 0.5;
|
||||||
tool.handlePosition.y = TextureGenerator.GRID_CENTERS_Y[x + y] - 0.5;
|
tool.handlePosition[1] = @intToFloat(f32, TextureGenerator.GRID_CENTERS_Y[x + y]) - 0.5;
|
||||||
// Count the neighbors to determine whether it's a good handle:
|
// Count the neighbors to determine whether it's a good handle:
|
||||||
var neighbors: u32 = 0;
|
var neighbors: u32 = 0;
|
||||||
if(x != 0 and tool.craftingGrid[y + x - 1])
|
if(x != 0 and tool.craftingGrid[y + x - 1] != null)
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
if(x != 4 and tool.craftingGrid[y + x + 1])
|
if(x != 4 and tool.craftingGrid[y + x + 1] != null)
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
if(y != 0) {
|
if(y != 0) {
|
||||||
if(tool.craftingGrid[y - 5 + x])
|
if(tool.craftingGrid[y - 5 + x] != null)
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
if(x != 0 and tool.craftingGrid[y - 5 + x - 1])
|
if(x != 0 and tool.craftingGrid[y - 5 + x - 1] != null)
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
if(x != 4 and tool.craftingGrid[y - 5 + x + 1])
|
if(x != 4 and tool.craftingGrid[y - 5 + x + 1] != null)
|
||||||
neighbors += 1;
|
neighbors += 1;
|
||||||
}
|
}
|
||||||
if(neighbors <= 1) {
|
if(neighbors <= 1) {
|
||||||
@ -563,8 +574,8 @@ const ToolPhysics = struct {
|
|||||||
if(tool.materialGrid[x][y]) |item| {
|
if(tool.materialGrid[x][y]) |item| {
|
||||||
if(item.material) |material| {
|
if(item.material) |material| {
|
||||||
const localMass = material.density;
|
const localMass = material.density;
|
||||||
centerOfMass.x += localMass*(@intToFloat(f32, x) + 0.5);
|
centerOfMass[0] += localMass*(@intToFloat(f32, x) + 0.5);
|
||||||
centerOfMass.y += localMass*(@intToFloat(f32, y) + 0.5);
|
centerOfMass[1] += localMass*(@intToFloat(f32, y) + 0.5);
|
||||||
mass += localMass;
|
mass += localMass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -582,8 +593,8 @@ const ToolPhysics = struct {
|
|||||||
if(tool.materialGrid[x][y]) |item| {
|
if(tool.materialGrid[x][y]) |item| {
|
||||||
if(item.material) |material| {
|
if(item.material) |material| {
|
||||||
const localMass = material.density;
|
const localMass = material.density;
|
||||||
const dx = @intToFloat(f32, x) + 0.5 - tool.centerOfMass.x;
|
const dx = @intToFloat(f32, x) + 0.5 - tool.centerOfMass[0];
|
||||||
const dy = @intToFloat(f32, y) + 0.5 - tool.centerOfMass.y;
|
const dy = @intToFloat(f32, y) + 0.5 - tool.centerOfMass[1];
|
||||||
inertia += localMass*(dx*dx + dy*dy);
|
inertia += localMass*(dx*dx + dy*dy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -591,21 +602,21 @@ const ToolPhysics = struct {
|
|||||||
}
|
}
|
||||||
tool.inertiaCenterOfMass = inertia;
|
tool.inertiaCenterOfMass = inertia;
|
||||||
// Using the parallel axis theorem the inertia relative to the handle can be derived:
|
// Using the parallel axis theorem the inertia relative to the handle can be derived:
|
||||||
tool.inertiaHandle = inertia + mass * tool.centerOfMass.distance(tool.handlePosition);
|
tool.inertiaHandle = inertia + mass*vec.length(tool.centerOfMass - tool.handlePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the sharpness of a point on the tool.
|
/// Determines the sharpness of a point on the tool.
|
||||||
fn determineSharpness(tool: *Tool, point: *Vec3i, initialAngle: f32) void {
|
fn determineSharpness(tool: *Tool, point: *Vec3i, initialAngle: f32) void {
|
||||||
const center: Vec2f = tool.handlePosition - vec.normalize(tool.centerOfMass - tool.handlePosition)*16; // Going 16 pixels away from the handle to simulate arm length.
|
const center: Vec2f = tool.handlePosition - vec.normalize(tool.centerOfMass - tool.handlePosition)*@splat(2, @as(f32, 16)); // Going 16 pixels away from the handle to simulate arm length.
|
||||||
// A region is smooth if there is a lot of pixel within similar angle/distance:
|
// A region is smooth if there is a lot of pixel within similar angle/distance:
|
||||||
const originalAngle = std.math.atan2(f32, @intToFloat(f32, point.y) + 0.5 - center.y, @intToFloat(f32, point.x) + 0.5 - center.x) - initialAngle;
|
const originalAngle = std.math.atan2(f32, @intToFloat(f32, point.*[1]) + 0.5 - center[1], @intToFloat(f32, point.*[0]) + 0.5 - center[0]) - initialAngle;
|
||||||
const originalDistance = @cos(originalAngle)*vec.length(center - Vec2f{@intToFloat(f32, point.x) + 0.5, @intToFloat(f32, point.y) + 0.5});
|
const originalDistance = @cos(originalAngle)*vec.length(center - Vec2f{@intToFloat(f32, point.*[0]) + 0.5, @intToFloat(f32, point.*[1]) + 0.5});
|
||||||
var numOfSmoothPixels: u32 = 0;
|
var numOfSmoothPixels: u31 = 0;
|
||||||
var x: f32 = 0;
|
var x: f32 = 0;
|
||||||
while(x < 16) : (x += 1) {
|
while(x < 16) : (x += 1) {
|
||||||
var y: f32 = 0;
|
var y: f32 = 0;
|
||||||
while(y < 16) : (y += 1) {
|
while(y < 16) : (y += 1) {
|
||||||
const angle = std.math.atan2(f32, y + 0.5 - center.y, x + 0.5 - center.x) - initialAngle;
|
const angle = std.math.atan2(f32, y + 0.5 - center[1], x + 0.5 - center[0]) - initialAngle;
|
||||||
const distance = @cos(angle)*vec.length(center - Vec2f{x + 0.5, y + 0.5});
|
const distance = @cos(angle)*vec.length(center - Vec2f{x + 0.5, y + 0.5});
|
||||||
const deltaAngle = @fabs(angle - originalAngle);
|
const deltaAngle = @fabs(angle - originalAngle);
|
||||||
const deltaDist = @fabs(distance - originalDistance);
|
const deltaDist = @fabs(distance - originalDistance);
|
||||||
@ -614,7 +625,7 @@ const ToolPhysics = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
point.z = numOfSmoothPixels;
|
point.*[2] = numOfSmoothPixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines where the tool would collide with the terrain.
|
/// Determines where the tool would collide with the terrain.
|
||||||
@ -622,32 +633,32 @@ const ToolPhysics = struct {
|
|||||||
fn determineCollisionPoints(tool: *Tool, leftCollisionPoint: *Vec3i, rightCollisionPoint: *Vec3i, frontCollisionPoint: *Vec3i, factor: f32) void {
|
fn determineCollisionPoints(tool: *Tool, leftCollisionPoint: *Vec3i, rightCollisionPoint: *Vec3i, frontCollisionPoint: *Vec3i, factor: f32) void {
|
||||||
// For finding that point the center of rotation is assumed to be 1 arm(16 pixel) begind the handle.
|
// For finding that point the center of rotation is assumed to be 1 arm(16 pixel) begind the handle.
|
||||||
// Additionally the handle is assumed to go towards the center of mass.
|
// Additionally the handle is assumed to go towards the center of mass.
|
||||||
const center: Vec2f = tool.handlePosition - vec.normalize(tool.centerOfMass - tool.handlePosition)*factor; // Going some distance away from the handle to simulate arm length.
|
const center: Vec2f = tool.handlePosition - vec.normalize(tool.centerOfMass - tool.handlePosition)*@splat(2, factor); // Going some distance away from the handle to simulate arm length.
|
||||||
// Angle of the handle.
|
// Angle of the handle.
|
||||||
const initialAngle = std.math.atan2(f32, tool.handlePosition.y - center.y, tool.handlePosition.x - center.x);
|
const initialAngle = std.math.atan2(f32, tool.handlePosition[1] - center[1], tool.handlePosition[0] - center[0]);
|
||||||
var leftCollisionAngle: f32 = 0;
|
var leftCollisionAngle: f32 = 0;
|
||||||
var rightCollisionAngle: f32 = 0;
|
var rightCollisionAngle: f32 = 0;
|
||||||
var frontCollisionDistance: f32 = 0;
|
var frontCollisionDistance: f32 = 0;
|
||||||
var x: i32 = 0;
|
var x: u8 = 0;
|
||||||
while(x < 16) : (x += 1) {
|
while(x < 16) : (x += 1) {
|
||||||
var y: i32 = 0;
|
var y: u8 = 0;
|
||||||
while(y < 16) : (y += 1) {
|
while(y < 16) : (y += 1) {
|
||||||
if(!tool.materialGrid[x][y]) continue;
|
if(tool.materialGrid[x][y] == null) continue;
|
||||||
const x_float = @intToFloat(f32, x);
|
const x_float = @intToFloat(f32, x);
|
||||||
const y_float = @intToFloat(f32, y);
|
const y_float = @intToFloat(f32, y);
|
||||||
const angle = std.math.atan2(f32, y_float + 0.5 - center.y, x_float + 0.5 - center.x) - initialAngle;
|
const angle = std.math.atan2(f32, y_float + 0.5 - center[1], x_float + 0.5 - center[0]) - initialAngle;
|
||||||
const distance = @cos(angle)*vec.length(center - Vec2f{x_float + 0.5, y_float + 0.5});
|
const distance = @cos(angle)*vec.length(center - Vec2f{x_float + 0.5, y_float + 0.5});
|
||||||
if(angle < leftCollisionAngle) {
|
if(angle < leftCollisionAngle) {
|
||||||
leftCollisionAngle = angle;
|
leftCollisionAngle = angle;
|
||||||
leftCollisionPoint = Vec3i{x, y, 0};
|
leftCollisionPoint.* = Vec3i{x, y, 0};
|
||||||
}
|
}
|
||||||
if(angle > rightCollisionAngle) {
|
if(angle > rightCollisionAngle) {
|
||||||
rightCollisionAngle = angle;
|
rightCollisionAngle = angle;
|
||||||
rightCollisionPoint = Vec3i{x, y, 0};
|
rightCollisionPoint.* = Vec3i{x, y, 0};
|
||||||
}
|
}
|
||||||
if(distance > frontCollisionDistance) {
|
if(distance > frontCollisionDistance) {
|
||||||
frontCollisionDistance = distance;
|
frontCollisionDistance = distance;
|
||||||
frontCollisionPoint = Vec3i{x, y, 0};
|
frontCollisionPoint.* = Vec3i{x, y, 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -673,7 +684,7 @@ const ToolPhysics = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Smaller tools are faster to swing. To balance that smaller tools get a lower durability.
|
// Smaller tools are faster to swing. To balance that smaller tools get a lower durability.
|
||||||
tool.maxDurability = @max(1, std.math.pow(f32, durability/4, 1.5));
|
tool.maxDurability = @floatToInt(u32, @max(1, std.math.pow(f32, durability/4, 1.5)));
|
||||||
tool.durability = tool.maxDurability;
|
tool.durability = tool.maxDurability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,7 +696,7 @@ const ToolPhysics = struct {
|
|||||||
// But when the pickaxe does get heavier 2 things happen:
|
// But when the pickaxe does get heavier 2 things happen:
|
||||||
// 1. The player needs to lift a bigger weight, so the tool speed gets reduced(calculated elsewhere).
|
// 1. The player needs to lift a bigger weight, so the tool speed gets reduced(calculated elsewhere).
|
||||||
// 2. When travelling down the tool also gets additional energy from gravity, so the force is increased by m·g.
|
// 2. When travelling down the tool also gets additional energy from gravity, so the force is increased by m·g.
|
||||||
impactEnergy *= tool.materialGrid[collisionPoint.x][collisionPoint.y].?.material.?.power + tool.mass/256;
|
impactEnergy *= tool.materialGrid[@intCast(usize, collisionPoint[0])][@intCast(usize, collisionPoint[1])].?.material.?.power + tool.mass/256;
|
||||||
|
|
||||||
return impactEnergy; // TODO: Balancing
|
return impactEnergy; // TODO: Balancing
|
||||||
}
|
}
|
||||||
@ -701,27 +712,26 @@ const ToolPhysics = struct {
|
|||||||
while(x < 2) : (x += 1) {
|
while(x < 2) : (x += 1) {
|
||||||
var y: i32 = -1;
|
var y: i32 = -1;
|
||||||
while(y <= 2) : (y += 1) {
|
while(y <= 2) : (y += 1) {
|
||||||
if(x + collisionPointLower.x >= 0 and x + collisionPointLower.x < 16) {
|
if(x + collisionPointLower[0] >= 0 and x + collisionPointLower[0] < 16) {
|
||||||
if(y + collisionPointLower.y >= 0 and y + collisionPointLower.y < 16) {
|
if(y + collisionPointLower[1] >= 0 and y + collisionPointLower[1] < 16) {
|
||||||
if(tool.materialGrid[x + collisionPointLower.x][y + collisionPointLower.y])
|
if(tool.materialGrid[@intCast(usize, x + collisionPointLower[0])][@intCast(usize, y + collisionPointLower[1])] != null)
|
||||||
neighborsLower += 1;
|
neighborsLower += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var neighborsUpper: u32 = 0;
|
var neighborsUpper: u32 = 0;
|
||||||
var dirUpper: Vec2i = Vec2i{0};
|
var dirUpper: Vec2i = Vec2i{0, 0};
|
||||||
// Vector2i dirUpper = new Vector2i();
|
|
||||||
x = -1;
|
x = -1;
|
||||||
while(x < 2) : (x += 1) {
|
while(x < 2) : (x += 1) {
|
||||||
var y: i32 = -1;
|
var y: i32 = -1;
|
||||||
while(y <= 2) : (y += 1) {
|
while(y <= 2) : (y += 1) {
|
||||||
if(x + collisionPointUpper.x >= 0 and x + collisionPointUpper.x < 16) {
|
if(x + collisionPointUpper[0] >= 0 and x + collisionPointUpper[0] < 16) {
|
||||||
if(y + collisionPointUpper.y >= 0 and y + collisionPointUpper.y < 16) {
|
if(y + collisionPointUpper[1] >= 0 and y + collisionPointUpper[1] < 16) {
|
||||||
if(tool.materialGrid[x + collisionPointUpper.x][y + collisionPointUpper.y]) {
|
if(tool.materialGrid[@intCast(usize, x + collisionPointUpper[0])][@intCast(usize, y + collisionPointUpper[1])] != null) {
|
||||||
neighborsUpper += 1;
|
neighborsUpper += 1;
|
||||||
dirUpper.x += x;
|
dirUpper[0] += x;
|
||||||
dirUpper.y += y;
|
dirUpper[1] += y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -730,7 +740,7 @@ const ToolPhysics = struct {
|
|||||||
if(neighborsLower > 3 and neighborsUpper > 3) return 0;
|
if(neighborsLower > 3 and neighborsUpper > 3) return 0;
|
||||||
|
|
||||||
// A pickaxe never points upwards:
|
// A pickaxe never points upwards:
|
||||||
if (neighborsUpper == 3 and dirUpper.y == 2) {
|
if(neighborsUpper == 3 and dirUpper[1] == 2) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,8 +750,8 @@ const ToolPhysics = struct {
|
|||||||
/// Determines how good an axe this side of the tool would make.
|
/// Determines how good an axe this side of the tool would make.
|
||||||
fn evaluateAxePower(tool: *Tool, collisionPointLower: Vec3i, collisionPointUpper: Vec3i) f32 {
|
fn evaluateAxePower(tool: *Tool, collisionPointLower: Vec3i, collisionPointUpper: Vec3i) f32 {
|
||||||
// Axes are used for breaking up wood. This requires a larger area (= smooth tip) rather than a sharp tip.
|
// Axes are used for breaking up wood. This requires a larger area (= smooth tip) rather than a sharp tip.
|
||||||
const collisionPointLowerFloat = Vec2f{@intToFloat(f32, collisionPointLower.x), @intToFloat(f32, collisionPointLower.y)};
|
const collisionPointLowerFloat = Vec2f{@intToFloat(f32, collisionPointLower[0]), @intToFloat(f32, collisionPointLower[1])};
|
||||||
const collisionPointUpperFloat = Vec2f{@intToFloat(f32, collisionPointUpper.x), @intToFloat(f32, collisionPointUpper.y)};
|
const collisionPointUpperFloat = Vec2f{@intToFloat(f32, collisionPointUpper[0]), @intToFloat(f32, collisionPointUpper[1])};
|
||||||
const areaFactor = 0.25 + vec.length(collisionPointLowerFloat - collisionPointUpperFloat)/4;
|
const areaFactor = 0.25 + vec.length(collisionPointLowerFloat - collisionPointUpperFloat)/4;
|
||||||
|
|
||||||
return areaFactor*calculateImpactEnergy(tool, collisionPointLower)/8;
|
return areaFactor*calculateImpactEnergy(tool, collisionPointLower)/8;
|
||||||
@ -764,7 +774,7 @@ const ToolPhysics = struct {
|
|||||||
var y: u8 = 0;
|
var y: u8 = 0;
|
||||||
while(y < 16) : (y += 1) {
|
while(y < 16) : (y += 1) {
|
||||||
sandPiles[x][y] = std.math.maxInt(u8);
|
sandPiles[x][y] = std.math.maxInt(u8);
|
||||||
if (!tool.materialGrid[x][y]) {
|
if(tool.materialGrid[x][y] == null) {
|
||||||
sandPiles[x][y] = 0;
|
sandPiles[x][y] = 0;
|
||||||
try stack.append(Entry{.x=x, .y=y});
|
try stack.append(Entry{.x=x, .y=y});
|
||||||
} else if(x == 0 or x == 15 or y == 0 or y == 15) {
|
} else if(x == 0 or x == 15 or y == 0 or y == 15) {
|
||||||
@ -776,28 +786,28 @@ const ToolPhysics = struct {
|
|||||||
while(stack.popOrNull()) |entry| {
|
while(stack.popOrNull()) |entry| {
|
||||||
x = entry.x;
|
x = entry.x;
|
||||||
const y = entry.y;
|
const y = entry.y;
|
||||||
if(x != 0 and y != 0 and tool.materialGrid[x - 1][y - 1]) {
|
if(x != 0 and y != 0 and tool.materialGrid[x - 1][y - 1] != null) {
|
||||||
if(sandPiles[x - 1][y - 1] > sandPiles[x][y] + 1) {
|
if(sandPiles[x - 1][y - 1] > sandPiles[x][y] + 1) {
|
||||||
sandPiles[x - 1][y - 1] = sandPiles[x][y] + 1;
|
sandPiles[x - 1][y - 1] = sandPiles[x][y] + 1;
|
||||||
stack.append(Entry{.x=x-1, .y=y-1});
|
try stack.append(Entry{.x=x-1, .y=y-1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(x != 0 and y != 15 and tool.materialGrid[x - 1][y + 1]) {
|
if(x != 0 and y != 15 and tool.materialGrid[x - 1][y + 1] != null) {
|
||||||
if(sandPiles[x - 1][y + 1] > sandPiles[x][y] + 1) {
|
if(sandPiles[x - 1][y + 1] > sandPiles[x][y] + 1) {
|
||||||
sandPiles[x - 1][y + 1] = sandPiles[x][y] + 1;
|
sandPiles[x - 1][y + 1] = sandPiles[x][y] + 1;
|
||||||
stack.append(Entry{.x=x-1, .y=y+1});
|
try stack.append(Entry{.x=x-1, .y=y+1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(x != 15 and y != 0 and tool.materialGrid[x + 1][y - 1]) {
|
if(x != 15 and y != 0 and tool.materialGrid[x + 1][y - 1] != null) {
|
||||||
if(sandPiles[x + 1][y - 1] > sandPiles[x][y] + 1) {
|
if(sandPiles[x + 1][y - 1] > sandPiles[x][y] + 1) {
|
||||||
sandPiles[x + 1][y - 1] = sandPiles[x][y] + 1;
|
sandPiles[x + 1][y - 1] = sandPiles[x][y] + 1;
|
||||||
stack.append(Entry{.x=x+1, .y=y-1});
|
try stack.append(Entry{.x=x+1, .y=y-1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(x != 15 and y != 15 and tool.materialGrid[x + 1][y + 1]) {
|
if(x != 15 and y != 15 and tool.materialGrid[x + 1][y + 1] != null) {
|
||||||
if(sandPiles[x + 1][y + 1] > sandPiles[x][y] + 1) {
|
if(sandPiles[x + 1][y + 1] > sandPiles[x][y] + 1) {
|
||||||
sandPiles[x + 1][y + 1] = sandPiles[x][y] + 1;
|
sandPiles[x + 1][y + 1] = sandPiles[x][y] + 1;
|
||||||
stack.append(Entry{.x=x+1, .y=y+1});
|
try stack.append(Entry{.x=x+1, .y=y+1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -807,7 +817,7 @@ const ToolPhysics = struct {
|
|||||||
while(x < 16) : (x += 1) {
|
while(x < 16) : (x += 1) {
|
||||||
var y: u8 = 0;
|
var y: u8 = 0;
|
||||||
while(y < 16) : (y += 1) {
|
while(y < 16) : (y += 1) {
|
||||||
volume += sandPiles[x][y];
|
volume += @intToFloat(f32, sandPiles[x][y]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
volume /= 256; // TODO: Balancing
|
volume /= 256; // TODO: Balancing
|
||||||
@ -816,28 +826,28 @@ const ToolPhysics = struct {
|
|||||||
|
|
||||||
|
|
||||||
/// Determines all the basic properties of the tool.
|
/// Determines all the basic properties of the tool.
|
||||||
pub fn evaluateTool(tool: *Tool) void {
|
pub fn evaluateTool(tool: *Tool) !void {
|
||||||
const hasGoodHandle = findHandle(tool);
|
const hasGoodHandle = findHandle(tool);
|
||||||
calculateDurability(tool);
|
calculateDurability(tool);
|
||||||
determineInertia(tool);
|
determineInertia(tool);
|
||||||
var leftCollisionPointLower = Vec3i{};
|
var leftCollisionPointLower = Vec3i{0, 0, 0};
|
||||||
var rightCollisionPointLower = Vec3i{};
|
var rightCollisionPointLower = Vec3i{0, 0, 0};
|
||||||
var frontCollisionPointLower = Vec3i{};
|
var frontCollisionPointLower = Vec3i{0, 0, 0};
|
||||||
var leftCollisionPointUpper = Vec3i{};
|
var leftCollisionPointUpper = Vec3i{0, 0, 0};
|
||||||
var rightCollisionPointUpper = Vec3i{};
|
var rightCollisionPointUpper = Vec3i{0, 0, 0};
|
||||||
var frontCollisionPointUpper = Vec3i{};
|
var frontCollisionPointUpper = Vec3i{0, 0, 0};
|
||||||
determineCollisionPoints(tool, &leftCollisionPointLower, &rightCollisionPointLower, &frontCollisionPointLower, 16);
|
determineCollisionPoints(tool, &leftCollisionPointLower, &rightCollisionPointLower, &frontCollisionPointLower, 16);
|
||||||
determineCollisionPoints(tool, &rightCollisionPointUpper, &leftCollisionPointUpper, &frontCollisionPointUpper, -20);
|
determineCollisionPoints(tool, &rightCollisionPointUpper, &leftCollisionPointUpper, &frontCollisionPointUpper, -20);
|
||||||
|
|
||||||
const leftPP = evaluatePickaxePower(tool, &leftCollisionPointLower, &leftCollisionPointUpper);
|
const leftPP = evaluatePickaxePower(tool, leftCollisionPointLower, leftCollisionPointUpper);
|
||||||
const rightPP = evaluatePickaxePower(tool, &rightCollisionPointLower, &rightCollisionPointUpper);
|
const rightPP = evaluatePickaxePower(tool, rightCollisionPointLower, rightCollisionPointUpper);
|
||||||
tool.pickaxePower = @max(leftPP, rightPP); // TODO: Adjust the swing direction.
|
tool.pickaxePower = @max(leftPP, rightPP); // TODO: Adjust the swing direction.
|
||||||
|
|
||||||
const leftAP = evaluateAxePower(tool, &leftCollisionPointLower, &leftCollisionPointUpper);
|
const leftAP = evaluateAxePower(tool, leftCollisionPointLower, leftCollisionPointUpper);
|
||||||
const rightAP = evaluateAxePower(tool, &rightCollisionPointLower, &rightCollisionPointUpper);
|
const rightAP = evaluateAxePower(tool, rightCollisionPointLower, rightCollisionPointUpper);
|
||||||
tool.axePower = @max(leftAP, rightAP); // TODO: Adjust the swing direction.
|
tool.axePower = @max(leftAP, rightAP); // TODO: Adjust the swing direction.
|
||||||
|
|
||||||
tool.shovelPower = evaluateShovelPower(tool, &frontCollisionPointLower);
|
tool.shovelPower = try evaluateShovelPower(tool, frontCollisionPointLower);
|
||||||
|
|
||||||
// It takes longer to swing a heavy tool.
|
// It takes longer to swing a heavy tool.
|
||||||
tool.swingTime = (tool.mass + tool.inertiaHandle/8)/256; // TODO: Balancing
|
tool.swingTime = (tool.mass + tool.inertiaHandle/8)/256; // TODO: Balancing
|
||||||
@ -884,31 +894,31 @@ const Tool = struct {
|
|||||||
/// Moment of inertia relative to the center of mass.
|
/// Moment of inertia relative to the center of mass.
|
||||||
inertiaCenterOfMass: f32,
|
inertiaCenterOfMass: f32,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator) !*Tool {
|
pub fn init() !*Tool {
|
||||||
var self = try allocator.create(Tool);
|
var self = try main.globalAllocator.create(Tool);
|
||||||
self.texture = try graphics.Image.init(allocator, 16, 16);
|
self.texture = try graphics.Image.init(main.globalAllocator, 16, 16);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Tool, allocator: Allocator) void {
|
pub fn deinit(self: *const Tool) void {
|
||||||
allocator.destroy(self);
|
main.globalAllocator.destroy(self);
|
||||||
self.texture.deinit(allocator);
|
self.texture.deinit(main.globalAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initFromCraftingGrid(allocator: Allocator, craftingGrid: [25]?*const BaseItem, seed: u32) !*Tool {
|
pub fn initFromCraftingGrid(craftingGrid: [25]?*const BaseItem, seed: u32) !*Tool {
|
||||||
var self = try init(allocator);
|
var self = try init();
|
||||||
self.seed = seed;
|
self.seed = seed;
|
||||||
self.craftingGrid = craftingGrid;
|
self.craftingGrid = craftingGrid;
|
||||||
// Produce the tool and its textures:
|
// Produce the tool and its textures:
|
||||||
// The material grid, which comes from texture generation, is needed on both server and client, to generate the tool properties.
|
// The material grid, which comes from texture generation, is needed on both server and client, to generate the tool properties.
|
||||||
TextureGenerator.generate(self);
|
try TextureGenerator.generate(self);
|
||||||
ToolPhysics.evaluateTool(self);
|
try ToolPhysics.evaluateTool(self);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initFromJson(allocator: Allocator, jsonObject: JsonElement) !*Tool {
|
pub fn initFromJson(jsonObject: JsonElement) !*Tool {
|
||||||
var self = try initFromCraftingGrid(allocator, extractItemsFromJson(jsonObject.getChild("grid")), jsonObject.get(u32, "seed", 0));
|
var self = try initFromCraftingGrid(extractItemsFromJson(jsonObject.getChild("grid")), jsonObject.get(u32, "seed", 0));
|
||||||
self.durability = jsonObject.get(i32, "durability", self.maxDurability);
|
self.durability = jsonObject.get(u32, "durability", self.maxDurability);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +930,7 @@ const Tool = struct {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(self: *Tool, allocator: Allocator) !JsonElement {
|
pub fn save(self: *const Tool, allocator: Allocator) !JsonElement {
|
||||||
var jsonObject = try JsonElement.initObject(allocator);
|
var jsonObject = try JsonElement.initObject(allocator);
|
||||||
var jsonArray = try JsonElement.initArray(allocator);
|
var jsonArray = try JsonElement.initArray(allocator);
|
||||||
for(self.craftingGrid) |nullItem| {
|
for(self.craftingGrid) |nullItem| {
|
||||||
@ -964,23 +974,28 @@ const Tool = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Item = union(u8) {
|
pub const Item = union(enum) {
|
||||||
baseItem: *const BaseItem,
|
baseItem: *const BaseItem,
|
||||||
tool: *const Tool,
|
tool: *const Tool,
|
||||||
|
|
||||||
pub fn init(self: *Item, allocator: Allocator) !void {
|
pub fn init(jsonObject: JsonElement) !Item {
|
||||||
_ = allocator;
|
if(reverseIndices.get(jsonObject.get([]const u8, "item", "null"))) |baseItem| {
|
||||||
_ = self;
|
std.debug.print("{*}", .{baseItem.id.ptr});
|
||||||
|
return Item{.baseItem = baseItem};
|
||||||
|
} else {
|
||||||
|
var toolJson = jsonObject.getChild("tool");
|
||||||
|
if(toolJson != .JsonObject) return error.ItemNotFound;
|
||||||
|
return Item{.tool = try Tool.initFromJson(toolJson)};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Item, allocator: Allocator) void {
|
pub fn deinit(self: Item) void {
|
||||||
switch(self) {
|
switch(self) {
|
||||||
.baseItem => {
|
.baseItem => {
|
||||||
|
|
||||||
},
|
},
|
||||||
.tool => |_tool| {
|
.tool => |_tool| {
|
||||||
_tool.deinit(allocator);
|
_tool.deinit();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1002,7 +1017,7 @@ pub const Item = union(u8) {
|
|||||||
try jsonObject.put("item", _baseItem.id);
|
try jsonObject.put("item", _baseItem.id);
|
||||||
},
|
},
|
||||||
.tool => |_tool| {
|
.tool => |_tool| {
|
||||||
json.put("tool", _tool.toJson(allocator));
|
try jsonObject.put("tool", try _tool.save(allocator));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1020,27 +1035,28 @@ pub const ItemStack = struct {
|
|||||||
supplier.clear();
|
supplier.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filled(self: *ItemStack) bool {
|
pub fn filled(self: *const ItemStack) bool {
|
||||||
if(self.item) |item| {
|
if(self.item) |item| {
|
||||||
return self.amount >= item.stackSize();
|
return self.amount >= item.stackSize();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty(self: *ItemStack) bool {
|
pub fn empty(self: *const ItemStack) bool {
|
||||||
return self.amount == 0;
|
return self.amount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of items actually added/removed.
|
/// Returns the number of items actually added/removed.
|
||||||
pub fn add(self: *ItemStack, number: i32) i32 {
|
pub fn add(self: *ItemStack, number: anytype) @TypeOf(number) {
|
||||||
std.debug.assert(self.item);
|
std.debug.assert(self.item != null);
|
||||||
const newAmount = self.amount + number;
|
var newAmount = self.amount + number;
|
||||||
var returnValue: i32 = 0;
|
var returnValue = number;
|
||||||
if(newAmount < 0) {
|
if(newAmount < 0) {
|
||||||
returnValue = number - newAmount;
|
|
||||||
newAmount = 0;
|
newAmount = 0;
|
||||||
|
returnValue = newAmount - self.amount;
|
||||||
} else if(newAmount > self.item.?.stackSize()) {
|
} else if(newAmount > self.item.?.stackSize()) {
|
||||||
returnValue = number - newAmount + self.item.?.stackSize();
|
|
||||||
newAmount = self.item.?.stackSize();
|
newAmount = self.item.?.stackSize();
|
||||||
|
returnValue = newAmount - self.amount;
|
||||||
}
|
}
|
||||||
self.amount = @intCast(u16, newAmount);
|
self.amount = @intCast(u16, newAmount);
|
||||||
if(self.empty()) {
|
if(self.empty()) {
|
||||||
@ -1050,7 +1066,7 @@ pub const ItemStack = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// whether the given number of items can be added to this stack.
|
/// whether the given number of items can be added to this stack.
|
||||||
pub fn canAddAll(self: *ItemStack, number: u16) bool {
|
pub fn canAddAll(self: *const ItemStack, number: u16) bool {
|
||||||
std.debug.assert(self.item);
|
std.debug.assert(self.item);
|
||||||
return @as(u32, self.amount) + number <= self.item.?.stackSize();
|
return @as(u32, self.amount) + number <= self.item.?.stackSize();
|
||||||
}
|
}
|
||||||
@ -1063,11 +1079,11 @@ pub const ItemStack = struct {
|
|||||||
self.amount = 0;
|
self.amount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store(self: *ItemStack, allocator: Allocator) !JsonElement {
|
pub fn store(self: *const ItemStack, allocator: Allocator) !JsonElement {
|
||||||
var result = try JsonElement.initObject(allocator);
|
var result = try JsonElement.initObject(allocator);
|
||||||
if(self.item) |item| {
|
if(self.item) |item| {
|
||||||
item.insertToJson(allocator, result);
|
try item.insertIntoJson(allocator, result);
|
||||||
result.put("amount", self.amount);
|
try result.put("amount", self.amount);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1085,27 +1101,123 @@ pub const ItemStack = struct {
|
|||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Inventory = struct {
|
||||||
|
items: []ItemStack,
|
||||||
|
|
||||||
|
pub fn init(allocator: Allocator, size: usize) !Inventory {
|
||||||
|
const self = Inventory{
|
||||||
|
.items = try allocator.alloc(ItemStack, size),
|
||||||
|
};
|
||||||
|
for(self.items) |*item| {
|
||||||
|
item.* = ItemStack{};
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: Inventory, allocator: Allocator) void {
|
||||||
|
for(self.items) |*item| {
|
||||||
|
item.clear();
|
||||||
|
}
|
||||||
|
allocator.free(self.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the amount of items that didn't fit in the inventory.
|
||||||
|
pub fn addItem(self: Inventory, item: Item, _amount: u16) u16 {
|
||||||
|
var amount = _amount;
|
||||||
|
for(self.items) |*stack| {
|
||||||
|
if(!stack.empty() and std.meta.eql(stack.item, item) and !stack.filled()) {
|
||||||
|
amount -= stack.add(amount);
|
||||||
|
if(amount == 0) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(self.items) |*stack| {
|
||||||
|
if(stack.empty()) {
|
||||||
|
stack.item = item;
|
||||||
|
amount -= stack.add(amount);
|
||||||
|
if(amount == 0) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn canCollect(self: Inventory, item: Item) bool {
|
||||||
|
for(self.items) |*stack| {
|
||||||
|
if(stack.empty()) return true;
|
||||||
|
if(stack.item == item and !stack.filled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check if/how this is needed:
|
||||||
|
// public int getBlock(int slot) {
|
||||||
|
// return items[slot].getBlock();
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn getItem(self: Inventory, slot: usize) ?Item {
|
||||||
|
return self.items[slot].item;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getStack(self: Inventory, slot: usize) *ItemStack {
|
||||||
|
return &self.items[slot];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getAmount(self: Inventory, slot: usize) u16 {
|
||||||
|
return self.items[slot].amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(self: Inventory, allocator: Allocator) !JsonElement {
|
||||||
|
var jsonObject = try JsonElement.initObject(allocator);
|
||||||
|
try jsonObject.put("capacity", self.items.len);
|
||||||
|
for(self.items) |stack, i| {
|
||||||
|
if(!stack.empty()) {
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
try jsonObject.put(buf[0..std.fmt.formatIntBuf(&buf, i, 10, .lower, .{})], try stack.store(allocator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loadFromJson(self: Inventory, allocator: Allocator, jsonObject: JsonElement) void {
|
||||||
|
for(self.items) |*stack, i| {
|
||||||
|
stack.clear();
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
var stackJson = jsonObject.getChild(buf[0..std.fmt.formatIntBuf(buf, i, 10, .lower, .{})]);
|
||||||
|
if(stackJson == .JsonObject) {
|
||||||
|
stack.item = try Item.init(allocator, jsonObject);
|
||||||
|
stack.amount = stackJson.get(u16, "amount", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var arena: std.heap.ArenaAllocator = undefined;
|
var arena: std.heap.ArenaAllocator = undefined;
|
||||||
var reverseIndices: std.StringHashMap(*BaseItem) = undefined;
|
var reverseIndices: std.StringHashMap(*BaseItem) = undefined;
|
||||||
var itemList: std.ArrayList(BaseItem) = undefined;
|
var itemList: [65536]BaseItem = undefined;
|
||||||
|
var itemListSize: u16 = 0;
|
||||||
|
|
||||||
|
|
||||||
pub fn globalInit() void {
|
pub fn globalInit() void {
|
||||||
arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
reverseIndices = std.StringHashMap(*BaseItem).init(arena.allocator());
|
reverseIndices = std.StringHashMap(*BaseItem).init(arena.allocator());
|
||||||
itemList = std.ArrayList(BaseItem).init(arena.allocator());
|
itemListSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(_: []const u8, id: []const u8, jsonObject: JsonElement) !void {
|
pub fn register(_: []const u8, id: []const u8, jsonObject: JsonElement) !void {
|
||||||
|
std.log.info("{s}", .{id});
|
||||||
if(reverseIndices.contains(id)) {
|
if(reverseIndices.contains(id)) {
|
||||||
std.log.warn("Registered block with id {s} twice!", .{id});
|
std.log.warn("Registered block with id {s} twice!", .{id});
|
||||||
}
|
}
|
||||||
try (try itemList.addOne()).init(arena.allocator(), id, jsonObject);
|
var newItem = &itemList[itemListSize];
|
||||||
|
try newItem.init(arena.allocator(), id, jsonObject);
|
||||||
|
try reverseIndices.put(newItem.id, newItem);
|
||||||
|
itemListSize += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset() void {
|
pub fn reset() void {
|
||||||
reverseIndices.clearAndFree();
|
reverseIndices.clearAndFree();
|
||||||
itemList.clearAndFree();
|
itemListSize = 0;
|
||||||
// TODO: Use arena.reset() instead.
|
// TODO: Use arena.reset() instead.
|
||||||
arena.deinit();
|
arena.deinit();
|
||||||
arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
@ -1113,6 +1225,5 @@ pub fn reset() void {
|
|||||||
|
|
||||||
pub fn deinit() void {
|
pub fn deinit() void {
|
||||||
reverseIndices.clearAndFree();
|
reverseIndices.clearAndFree();
|
||||||
itemList.clearAndFree();
|
|
||||||
arena.deinit();
|
arena.deinit();
|
||||||
}
|
}
|
13
src/json.zig
13
src/json.zig
@ -136,7 +136,7 @@ pub const JsonElement = union(JsonType) {
|
|||||||
.Null => return JsonElement{.JsonNull={}},
|
.Null => return JsonElement{.JsonNull={}},
|
||||||
.Bool => return JsonElement{.JsonBool=value},
|
.Bool => return JsonElement{.JsonBool=value},
|
||||||
.Int, .ComptimeInt => return JsonElement{.JsonInt=@intCast(i64, value)},
|
.Int, .ComptimeInt => return JsonElement{.JsonInt=@intCast(i64, value)},
|
||||||
.Float, .ComptimeFloat => return JsonElement{.JsonInt=@floatCast(f64, value)},
|
.Float, .ComptimeFloat => return JsonElement{.JsonFloat=@floatCast(f64, value)},
|
||||||
.Union => {
|
.Union => {
|
||||||
if(@TypeOf(value) == JsonElement) {
|
if(@TypeOf(value) == JsonElement) {
|
||||||
return value;
|
return value;
|
||||||
@ -144,6 +144,14 @@ pub const JsonElement = union(JsonType) {
|
|||||||
@compileError("Unknown value type.");
|
@compileError("Unknown value type.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.Pointer => |ptr| {
|
||||||
|
if(ptr.child == u8 and ptr.size == .Slice) {
|
||||||
|
std.log.info("String: {s}", .{value});
|
||||||
|
return JsonElement{.JsonString=value};
|
||||||
|
} else {
|
||||||
|
@compileError("Unknown value type.");
|
||||||
|
}
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
@compileError("Unknown value type.");
|
@compileError("Unknown value type.");
|
||||||
},
|
},
|
||||||
@ -152,7 +160,7 @@ pub const JsonElement = union(JsonType) {
|
|||||||
|
|
||||||
pub fn put(self: *const JsonElement, key: []const u8, value: anytype) !void {
|
pub fn put(self: *const JsonElement, key: []const u8, value: anytype) !void {
|
||||||
const result = createElementFromRandomType(value);
|
const result = createElementFromRandomType(value);
|
||||||
try self.JsonObject.put(key, result);
|
try self.JsonObject.put(try self.JsonObject.allocator.dupe(u8, key), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn free(self: *const JsonElement, allocator: Allocator) void {
|
pub fn free(self: *const JsonElement, allocator: Allocator) void {
|
||||||
@ -185,7 +193,6 @@ pub const JsonElement = union(JsonType) {
|
|||||||
return self.* == JsonType.JsonNull;
|
return self.* == JsonType.JsonNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: toString()
|
|
||||||
fn escape(string: []const u8, allocator: Allocator) ![]const u8 {
|
fn escape(string: []const u8, allocator: Allocator) ![]const u8 {
|
||||||
var out = std.ArrayList(u8).init(allocator);
|
var out = std.ArrayList(u8).init(allocator);
|
||||||
for(string) |char| {
|
for(string) |char| {
|
||||||
|
@ -22,6 +22,7 @@ pub const c = @cImport ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
pub threadlocal var threadAllocator: std.mem.Allocator = undefined;
|
pub threadlocal var threadAllocator: std.mem.Allocator = undefined;
|
||||||
|
pub var globalAllocator: std.mem.Allocator = undefined;
|
||||||
pub var threadPool: utils.ThreadPool = undefined;
|
pub var threadPool: utils.ThreadPool = undefined;
|
||||||
|
|
||||||
var logFile: std.fs.File = undefined;
|
var logFile: std.fs.File = undefined;
|
||||||
@ -218,6 +219,11 @@ pub fn main() !void {
|
|||||||
defer if(gpa.deinit()) {
|
defer if(gpa.deinit()) {
|
||||||
@panic("Memory leak");
|
@panic("Memory leak");
|
||||||
};
|
};
|
||||||
|
var global_gpa = std.heap.GeneralPurposeAllocator(.{.thread_safe=true}){};
|
||||||
|
globalAllocator = global_gpa.allocator();
|
||||||
|
defer if(global_gpa.deinit()) {
|
||||||
|
@panic("Memory leak");
|
||||||
|
};
|
||||||
|
|
||||||
// init logging.
|
// init logging.
|
||||||
try std.fs.cwd().makePath("logs");
|
try std.fs.cwd().makePath("logs");
|
||||||
|
@ -5,15 +5,19 @@ const assets = @import("assets.zig");
|
|||||||
const Block = @import("blocks.zig").Block;
|
const Block = @import("blocks.zig").Block;
|
||||||
const chunk = @import("chunk.zig");
|
const chunk = @import("chunk.zig");
|
||||||
const entity = @import("entity.zig");
|
const entity = @import("entity.zig");
|
||||||
|
const items = @import("items.zig");
|
||||||
|
const Inventory = items.Inventory;
|
||||||
|
const ItemStack = items.ItemStack;
|
||||||
|
const json = @import("json.zig");
|
||||||
const main = @import("main.zig");
|
const main = @import("main.zig");
|
||||||
const game = @import("game.zig");
|
const game = @import("game.zig");
|
||||||
const settings = @import("settings.zig");
|
const settings = @import("settings.zig");
|
||||||
const json = @import("json.zig");
|
|
||||||
const JsonElement = json.JsonElement;
|
const JsonElement = json.JsonElement;
|
||||||
const renderer = @import("renderer.zig");
|
const renderer = @import("renderer.zig");
|
||||||
const utils = @import("utils.zig");
|
const utils = @import("utils.zig");
|
||||||
const vec = @import("vec.zig");
|
const vec = @import("vec.zig");
|
||||||
const Vec3d = vec.Vec3d;
|
const Vec3d = vec.Vec3d;
|
||||||
|
const Vec3f = vec.Vec3f;
|
||||||
|
|
||||||
//TODO: Might want to use SSL or something similar to encode the message
|
//TODO: Might want to use SSL or something similar to encode the message
|
||||||
|
|
||||||
@ -977,7 +981,7 @@ pub const Protocols: struct {
|
|||||||
const type_itemStackDrop: u8 = 6;
|
const type_itemStackDrop: u8 = 6;
|
||||||
const type_itemStackCollect: u8 = 7;
|
const type_itemStackCollect: u8 = 7;
|
||||||
const type_timeAndBiome: u8 = 8;
|
const type_timeAndBiome: u8 = 8;
|
||||||
fn receive(_: *Connection, data: []const u8) !void {
|
fn receive(conn: *Connection, data: []const u8) !void {
|
||||||
switch(data[0]) {
|
switch(data[0]) {
|
||||||
type_renderDistance => {
|
type_renderDistance => {
|
||||||
const renderDistance = std.mem.readIntBig(i32, data[1..5]);
|
const renderDistance = std.mem.readIntBig(i32, data[1..5]);
|
||||||
@ -1047,18 +1051,18 @@ pub const Protocols: struct {
|
|||||||
// );
|
// );
|
||||||
},
|
},
|
||||||
type_itemStackCollect => {
|
type_itemStackCollect => {
|
||||||
// TODO:
|
const jsonObject = json.parseFromString(main.threadAllocator, data[1..]);
|
||||||
// JsonObject json = JsonParser.parseObjectFromString(new String(data, offset + 1, length - 1, StandardCharsets.UTF_8));
|
defer jsonObject.free(main.threadAllocator);
|
||||||
// Item item = Item.load(json, Cubyz.world.registries);
|
const item = try items.Item.init(jsonObject);
|
||||||
// if (item == null) {
|
game.Player.mutex.lock();
|
||||||
// break;
|
defer game.Player.mutex.unlock();
|
||||||
// }
|
const remaining = game.Player.inventory__SEND_CHANGES_TO_SERVER.addItem(item, jsonObject.get(u16, "amount", 0));
|
||||||
// int remaining = Cubyz.player.getInventory_AND_DONT_FORGET_TO_SEND_CHANGES_TO_THE_SERVER().addItem(item, json.getInt("amount", 1));
|
|
||||||
// sendInventory_full(Cubyz.world.serverConnection, Cubyz.player.getInventory_AND_DONT_FORGET_TO_SEND_CHANGES_TO_THE_SERVER());
|
try sendInventory_full(conn, game.Player.inventory__SEND_CHANGES_TO_SERVER);
|
||||||
// if(remaining != 0) {
|
if(remaining != 0) {
|
||||||
// // Couldn't collect everything → drop it again.
|
// Couldn't collect everything → drop it again.
|
||||||
// itemStackDrop(Cubyz.world.serverConnection, new ItemStack(item, remaining), Cubyz.player.getPosition(), Camera.getDirection(), 0);
|
try itemStackDrop(conn, ItemStack{.item=item, .amount=remaining}, game.Player.getPosBlocking(), Vec3f{0, 0, 0}, 0);
|
||||||
// }
|
}
|
||||||
},
|
},
|
||||||
type_timeAndBiome => {
|
type_timeAndBiome => {
|
||||||
if(game.world) |world| {
|
if(game.world) |world| {
|
||||||
@ -1134,10 +1138,14 @@ pub const Protocols: struct {
|
|||||||
try conn.sendImportant(id, &data);
|
try conn.sendImportant(id, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// public void sendInventory_full(ServerConnection conn, Inventory inv) {
|
pub fn sendInventory_full(conn: *Connection, inv: Inventory) !void {
|
||||||
// addHeaderAndSendImportant(conn, INVENTORY_FULL, inv.save().toString().getBytes(StandardCharsets.UTF_8));
|
const jsonObject = try inv.save(main.threadAllocator);
|
||||||
// }
|
defer jsonObject.free(main.threadAllocator);
|
||||||
|
const string = try jsonObject.toString(main.threadAllocator);
|
||||||
|
defer main.threadAllocator.free(string);
|
||||||
|
try addHeaderAndSendImportant(conn, type_inventoryFull, string);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clearInventory(conn: *Connection) !void {
|
pub fn clearInventory(conn: *Connection) !void {
|
||||||
var data: [1]u8 = undefined;
|
var data: [1]u8 = undefined;
|
||||||
@ -1145,23 +1153,28 @@ pub const Protocols: struct {
|
|||||||
try conn.sendImportant(id, &data);
|
try conn.sendImportant(id, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
pub fn itemStackDrop(conn: *Connection, stack: ItemStack, pos: Vec3d, dir: Vec3f, vel: f32) !void {
|
||||||
// public void itemStackDrop(ServerConnection conn, ItemStack stack, Vector3d pos, Vector3f dir, float vel) {
|
var jsonObject = try stack.store(main.threadAllocator);
|
||||||
// JsonObject json = stack.store();
|
defer jsonObject.free(main.threadAllocator);
|
||||||
// json.put("x", pos.x);
|
try jsonObject.put("x", pos[0]);
|
||||||
// json.put("y", pos.y);
|
try jsonObject.put("y", pos[1]);
|
||||||
// json.put("z", pos.z);
|
try jsonObject.put("z", pos[2]);
|
||||||
// json.put("dirX", dir.x);
|
try jsonObject.put("dirX", dir[0]);
|
||||||
// json.put("dirY", dir.y);
|
try jsonObject.put("dirY", dir[1]);
|
||||||
// json.put("dirZ", dir.z);
|
try jsonObject.put("dirZ", dir[2]);
|
||||||
// json.put("vel", vel);
|
try jsonObject.put("vel", vel);
|
||||||
// addHeaderAndSendImportant(conn, ITEM_STACK_DROP, json.toString().getBytes(StandardCharsets.UTF_8));
|
const string = try jsonObject.toString(main.threadAllocator);
|
||||||
// }
|
defer main.threadAllocator.free(string);
|
||||||
|
try addHeaderAndSendImportant(conn, type_itemStackDrop, string);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
pub fn itemStackCollect(conn: *Connection, stack: ItemStack) !void {
|
||||||
// public void itemStackCollect(User user, ItemStack stack) {
|
var jsonObject = try stack.store(main.threadAllocator);
|
||||||
// addHeaderAndSendImportant(user, ITEM_STACK_COLLECT, stack.store().toString().getBytes(StandardCharsets.UTF_8));
|
defer jsonObject.free(main.threadAllocator);
|
||||||
// }
|
const string = try jsonObject.toString(main.threadAllocator);
|
||||||
|
defer main.threadAllocator.free(string);
|
||||||
|
try addHeaderAndSendImportant(conn, type_itemStackCollect, string);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// public void sendTimeAndBiome(User user, ServerWorld world) {
|
// public void sendTimeAndBiome(User user, ServerWorld world) {
|
||||||
|
@ -10,16 +10,16 @@ pub fn scrambleSeed(seed: *u64) void {
|
|||||||
seed.* = (seed.* ^ multiplier) & mask;
|
seed.* = (seed.* ^ multiplier) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nextWithBitSize(T: type, seed: *u64, bitSize: u6) T {
|
fn nextWithBitSize(comptime T: type, seed: *u64, bitSize: u6) T {
|
||||||
seed.* = ((seed.*)*multiplier + addend) & mask;
|
seed.* = ((seed.*)*multiplier + addend) & mask;
|
||||||
return @intCast(T, (seed >> (48 - bitSize)) & std.math.maxInt(T));
|
return @intCast(T, (seed.* >> (48 - bitSize)) & std.math.maxInt(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(T: type, seed: *u64) T {
|
fn next(comptime T: type, seed: *u64) T {
|
||||||
nextWithBitSize(T, seed, @bitSizeOf(T));
|
return nextWithBitSize(T, seed, @bitSizeOf(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nextInt(T: type, seed: *u64) T {
|
pub fn nextInt(comptime T: type, seed: *u64) T {
|
||||||
if(@bitSizeOf(T) > 48) {
|
if(@bitSizeOf(T) > 48) {
|
||||||
@compileError("Did not yet implement support for bigger numbers.");
|
@compileError("Did not yet implement support for bigger numbers.");
|
||||||
} else {
|
} else {
|
||||||
@ -27,8 +27,8 @@ pub fn nextInt(T: type, seed: *u64) T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nextIntBounded(T: type, seed: *u64, bound: T) T {
|
pub fn nextIntBounded(comptime T: type, seed: *u64, bound: T) T {
|
||||||
var bitSize = std.math.log2_int_ceil(bound);
|
var bitSize = std.math.log2_int_ceil(T, bound);
|
||||||
var result = nextWithBitSize(T, seed, bitSize);
|
var result = nextWithBitSize(T, seed, bitSize);
|
||||||
while(result >= bound) {
|
while(result >= bound) {
|
||||||
result = nextWithBitSize(T, seed, bitSize);
|
result = nextWithBitSize(T, seed, bitSize);
|
||||||
|
@ -877,7 +877,7 @@ pub const RenderStructure = struct {
|
|||||||
|
|
||||||
pub fn getBlock(x: chunk.ChunkCoordinate, y: chunk.ChunkCoordinate, z: chunk.ChunkCoordinate) ?blocks.Block {
|
pub fn getBlock(x: chunk.ChunkCoordinate, y: chunk.ChunkCoordinate, z: chunk.ChunkCoordinate) ?blocks.Block {
|
||||||
const node = RenderStructure._getNode(.{.wx = x, .wy = y, .wz = z, .voxelSize=1}) orelse return null;
|
const node = RenderStructure._getNode(.{.wx = x, .wy = y, .wz = z, .voxelSize=1}) orelse return null;
|
||||||
const block = (node.mesh.chunk orelse return null).getBlock(x & chunk.chunkMask, y & chunk.chunkMask, z & chunk.chunkMask);
|
const block = (node.mesh.chunk.load(.Monotonic) orelse return null).getBlock(x & chunk.chunkMask, y & chunk.chunkMask, z & chunk.chunkMask);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ pub fn length(self: anytype) @typeInfo(@TypeOf(self)).Vector.child {
|
|||||||
return @sqrt(@reduce(.Add, self*self));
|
return @sqrt(@reduce(.Add, self*self));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normalize(self: anytype) @typeInfo(@TypeOf(self)).Vector.child {
|
pub fn normalize(self: anytype) @TypeOf(self) {
|
||||||
return self/length(self);
|
return self/@splat(@typeInfo(@TypeOf(self)).Vector.len, length(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cross(self: anytype, other: @TypeOf(self)) @TypeOf(self) {
|
pub fn cross(self: anytype, other: @TypeOf(self)) @TypeOf(self) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user