mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -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 {
|
||||
pos: ChunkPosition,
|
||||
size: ChunkCoordinate,
|
||||
chunk: ?*Chunk,
|
||||
chunk: std.atomic.Atomic(?*Chunk),
|
||||
faces: std.ArrayList(u32),
|
||||
faceData: SSBO,
|
||||
coreCount: u31 = 0,
|
||||
@ -465,7 +465,7 @@ pub const meshing = struct {
|
||||
.pos = pos,
|
||||
.size = chunkSize*pos.voxelSize,
|
||||
.faces = std.ArrayList(u32).init(allocator),
|
||||
.chunk = null,
|
||||
.chunk = std.atomic.Atomic(?*Chunk).init(null),
|
||||
.faceData = SSBO.init(),
|
||||
};
|
||||
}
|
||||
@ -473,7 +473,7 @@ pub const meshing = struct {
|
||||
pub fn deinit(self: *ChunkMesh) void {
|
||||
self.faceData.deinit();
|
||||
self.faces.deinit();
|
||||
if(self.chunk) |ch| {
|
||||
if(self.chunk.load(.Monotonic)) |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);
|
||||
}
|
||||
self.chunk = chunk;
|
||||
self.chunk.store(chunk, .Monotonic);
|
||||
self.coreCount = @intCast(u31, self.faces.items.len);
|
||||
self.neighborStart = [_]u31{self.coreCount} ** 7;
|
||||
}
|
||||
@ -625,7 +625,7 @@ pub const meshing = struct {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
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| {
|
||||
var neighborMesh = self;
|
||||
var nx = x + Neighbors.relX[neighbor];
|
||||
@ -640,7 +640,7 @@ pub const meshing = struct {
|
||||
nx &= chunkMask;
|
||||
ny &= 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
|
||||
const newVisibility = canBeSeenThroughOtherBlock(newBlock, neighborBlock, neighbor);
|
||||
@ -701,7 +701,7 @@ pub const meshing = struct {
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@ -712,7 +712,7 @@ pub const meshing = struct {
|
||||
|
||||
pub fn uploadDataAndFinishNeighbors(self: *ChunkMesh) !void {
|
||||
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);
|
||||
for(Neighbors.iterable) |neighbor| {
|
||||
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 otherY = @intCast(u8, y+%Neighbors.relY[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 otherBlock = (&neighborMesh.chunk.?.blocks)[getIndex(otherX, otherY, otherZ)]; // ← 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.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)) {
|
||||
const normal: u32 = neighbor;
|
||||
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 otherY = @intCast(u8, (y+%Neighbors.relY[neighbor]+%offsetY >> 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 otherBlock = (&neighborMesh.chunk.?.blocks)[getIndex(otherX, otherY, otherZ)]; // ← 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.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)) {
|
||||
const normal: u32 = neighbor ^ 1;
|
||||
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 chunk = @import("chunk.zig");
|
||||
const items = @import("items.zig");
|
||||
const Inventory = items.Inventory;
|
||||
const json = @import("json.zig");
|
||||
const JsonElement = json.JsonElement;
|
||||
const main = @import("main.zig");
|
||||
@ -46,7 +48,8 @@ pub const Player = struct {
|
||||
var vel: Vec3d = Vec3d{0, 0, 0};
|
||||
pub var id: u32 = 0;
|
||||
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 {
|
||||
mutex.lock();
|
||||
@ -92,6 +95,7 @@ pub const World = struct {
|
||||
.name = "client",
|
||||
.milliTime = std.time.milliTimestamp(),
|
||||
};
|
||||
Player.inventory__SEND_CHANGES_TO_SERVER = try Inventory.init(renderer.RenderStructure.allocator, 32);
|
||||
// TODO:
|
||||
// super.itemEntityManager = new InterpolatedItemEntityManager(this);
|
||||
// player = new ClientPlayer(this, 0);
|
||||
@ -100,6 +104,7 @@ pub const World = struct {
|
||||
|
||||
pub fn deinit(self: *World) void {
|
||||
self.conn.deinit();
|
||||
Player.inventory__SEND_CHANGES_TO_SERVER.deinit(renderer.RenderStructure.allocator);
|
||||
}
|
||||
|
||||
pub fn finishHandshake(self: *World, jsonObject: JsonElement) !void {
|
||||
|
@ -660,6 +660,12 @@ pub const Image = struct {
|
||||
stb_image.stbi_image_free(data);
|
||||
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 {
|
||||
|
545
src/items.zig
545
src/items.zig
@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator;
|
||||
const blocks = @import("blocks.zig");
|
||||
const Block = blocks.Block;
|
||||
const graphics = @import("graphics.zig");
|
||||
const Color = graphics.Color;
|
||||
const json = @import("json.zig");
|
||||
const JsonElement = json.JsonElement;
|
||||
const main = @import("main.zig");
|
||||
@ -26,7 +27,7 @@ const Material = struct {
|
||||
/// How rough the texture should look.
|
||||
roughness: f32 = undefined,
|
||||
/// 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 {
|
||||
self.density = jsonObject.get(f32, "density", 1.0);
|
||||
@ -34,9 +35,15 @@ const Material = struct {
|
||||
self.power = jsonObject.get(f32, "power", 1.0);
|
||||
self.roughness = @max(0, jsonObject.get(f32, "roughness", 1.0));
|
||||
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| {
|
||||
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),
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: PixelData) void {
|
||||
pub fn deinit(self: *PixelData) void {
|
||||
self.items.clearAndFree();
|
||||
}
|
||||
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 {
|
||||
var neighbors: u8 = 0;
|
||||
// direct neighbors count 1.5 times as much.
|
||||
if (relativeGrid[7]) neighbors += 3;
|
||||
if (relativeGrid[11]) neighbors += 3;
|
||||
if (relativeGrid[13]) neighbors += 3;
|
||||
if (relativeGrid[17]) neighbors += 3;
|
||||
if(relativeGrid[7] != null) neighbors += 3;
|
||||
if(relativeGrid[11] != null) neighbors += 3;
|
||||
if(relativeGrid[13] != null) neighbors += 3;
|
||||
if(relativeGrid[17] != null) neighbors += 3;
|
||||
|
||||
if (relativeGrid[6]) neighbors += 2;
|
||||
if (relativeGrid[8]) neighbors += 2;
|
||||
if (relativeGrid[16]) neighbors += 2;
|
||||
if (relativeGrid[18]) neighbors += 2;
|
||||
if(relativeGrid[6] != null) neighbors += 2;
|
||||
if(relativeGrid[8] != null) neighbors += 2;
|
||||
if(relativeGrid[16] != null) neighbors += 2;
|
||||
if(relativeGrid[18] != null) neighbors += 2;
|
||||
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
/// 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| {
|
||||
// Count diagonal and straight neighbors:
|
||||
var diagonalNeighbors: u8 = 0;
|
||||
var straightNeighbors: u8 = 0;
|
||||
if (relativeGrid[7]) straightNeighbors += 1;
|
||||
if (relativeGrid[11]) straightNeighbors += 1;
|
||||
if (relativeGrid[13]) straightNeighbors += 1;
|
||||
if (relativeGrid[17]) straightNeighbors += 1;
|
||||
if(relativeGrid[7] != null) straightNeighbors += 1;
|
||||
if(relativeGrid[11] != null) straightNeighbors += 1;
|
||||
if(relativeGrid[13] != null) straightNeighbors += 1;
|
||||
if(relativeGrid[17] != null) straightNeighbors += 1;
|
||||
|
||||
if (relativeGrid[6]) diagonalNeighbors += 1;
|
||||
if (relativeGrid[8]) diagonalNeighbors += 1;
|
||||
if (relativeGrid[16]) diagonalNeighbors += 1;
|
||||
if (relativeGrid[18]) diagonalNeighbors += 1;
|
||||
if(relativeGrid[6] != null) diagonalNeighbors += 1;
|
||||
if(relativeGrid[8] != null) diagonalNeighbors += 1;
|
||||
if(relativeGrid[16] != null) diagonalNeighbors += 1;
|
||||
if(relativeGrid[18] != null) diagonalNeighbors += 1;
|
||||
|
||||
const neighbors = diagonalNeighbors + straightNeighbors;
|
||||
|
||||
pixels[x + 1][y + 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 1][y + 2].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y + 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y + 2].add(item, relativeNeighborCount[12]);
|
||||
|
||||
// Checkout straight neighbors:
|
||||
if(relativeGrid[7]) {
|
||||
if(relativeGrid[7] != null) {
|
||||
if(relativeNeighborCount[7] >= relativeNeighborCount[12]) {
|
||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[1] and !relativeGrid[16] and straightNeighbors <= 1) {
|
||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[1] != null and relativeGrid[16] == null and straightNeighbors <= 1) {
|
||||
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[3] and !relativeGrid[18] and straightNeighbors <= 1) {
|
||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[3] != null and relativeGrid[18] == null and straightNeighbors <= 1) {
|
||||
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
if (relativeGrid[11]) {
|
||||
if(relativeGrid[11] != null) {
|
||||
if(relativeNeighborCount[11] >= relativeNeighborCount[12]) {
|
||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[5] and !relativeGrid[8] and straightNeighbors <= 1) {
|
||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[5] != null and relativeGrid[8] == null and straightNeighbors <= 1) {
|
||||
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[15] and !relativeGrid[18] and straightNeighbors <= 1) {
|
||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[15] != null and relativeGrid[18] == null and straightNeighbors <= 1) {
|
||||
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
if (relativeGrid[13]) {
|
||||
if(relativeGrid[13] != null) {
|
||||
if(relativeNeighborCount[13] >= relativeNeighborCount[12]) {
|
||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[9] and !relativeGrid[6] and straightNeighbors <= 1) {
|
||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[9] != null and relativeGrid[6] == null and straightNeighbors <= 1) {
|
||||
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[19] and !relativeGrid[16] and straightNeighbors <= 1) {
|
||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[19] != null and relativeGrid[16] == null and straightNeighbors <= 1) {
|
||||
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
if (relativeGrid[17]) {
|
||||
if(relativeGrid[17] != null) {
|
||||
if(relativeNeighborCount[17] >= relativeNeighborCount[12]) {
|
||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][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) {
|
||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[21] != null and relativeGrid[6] == null and straightNeighbors <= 1) {
|
||||
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[23] and !relativeGrid[8] and straightNeighbors <= 1) {
|
||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[23] != null and relativeGrid[8] == null and straightNeighbors <= 1) {
|
||||
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
|
||||
// Checkout diagonal neighbors:
|
||||
if (relativeGrid[6]) {
|
||||
if(relativeGrid[6] != null) {
|
||||
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]);
|
||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
if (relativeGrid[1] and !relativeGrid[7] and neighbors <= 2) {
|
||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[1] != null and relativeGrid[7] == null and neighbors <= 2) {
|
||||
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[5] and !relativeGrid[11] and neighbors <= 2) {
|
||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[5] != null and relativeGrid[11] == null and neighbors <= 2) {
|
||||
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
if (relativeGrid[8]) {
|
||||
if(relativeGrid[8] != null) {
|
||||
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]);
|
||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
if (relativeGrid[3] and !relativeGrid[7] and neighbors <= 2) {
|
||||
pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[3] != null and relativeGrid[7] == null and neighbors <= 2) {
|
||||
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[9] and !relativeGrid[13] and neighbors <= 2) {
|
||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[9] != null and relativeGrid[13] == null and neighbors <= 2) {
|
||||
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
if (relativeGrid[16]) {
|
||||
if(relativeGrid[16] != null) {
|
||||
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]);
|
||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
if (relativeGrid[21] and !relativeGrid[17] and neighbors <= 2) {
|
||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[21] != null and relativeGrid[17] == null and neighbors <= 2) {
|
||||
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[15] and !relativeGrid[11] and neighbors <= 2) {
|
||||
pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[15] != null and relativeGrid[11] == null and neighbors <= 2) {
|
||||
try pixels[x + 2][y].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
if (relativeGrid[18]) {
|
||||
if(relativeGrid[18] != null) {
|
||||
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]);
|
||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
if (relativeGrid[23] and !relativeGrid[17] and neighbors <= 2) {
|
||||
pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[23] != null and relativeGrid[17] == null and neighbors <= 2) {
|
||||
try pixels[x][y + 1].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if (relativeGrid[19] and !relativeGrid[13] and neighbors <= 2) {
|
||||
pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
if(relativeGrid[19] != null and relativeGrid[13] == null and neighbors <= 2) {
|
||||
try pixels[x + 1][y].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
}
|
||||
|
||||
// Make stuff more round when there is many incoming connections:
|
||||
if(diagonalNeighbors >= 3 or straightNeighbors == 4) {
|
||||
pixels[x + 0][y + 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 0][y + 2].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 1][y + 0].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y + 0].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 0][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 0][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y + 0].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y + 3].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y + 0].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y + 3].add(item, relativeNeighborCount[12]);
|
||||
// Check which of the neighbors was empty:
|
||||
if(relativeGrid[6] == null) {
|
||||
pixels[x + 0][y + 0].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y - 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x - 1][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 0][y + 0].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y - 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x - 1][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if(relativeGrid[8] == null) {
|
||||
pixels[x + 3][y + 0].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 1][y - 1].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 4][y + 2].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 0].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y - 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 4][y + 2].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if(relativeGrid[16] == null) {
|
||||
pixels[x + 0][y + 3].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 2][y + 4].add(item, relativeNeighborCount[12]);
|
||||
pixels[x - 1][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 0][y + 3].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 2][y + 4].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x - 1][y + 1].add(item, relativeNeighborCount[12]);
|
||||
}
|
||||
if(relativeGrid[18] == null) {
|
||||
pixels[x + 3][y + 3].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 1][y + 4].add(item, relativeNeighborCount[12]);
|
||||
pixels[x + 4][y + 1].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 3][y + 3].add(item, relativeNeighborCount[12]);
|
||||
try pixels[x + 1][y + 4].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 x: u8 = 0;
|
||||
while(x < 17) : (x += 1) {
|
||||
@ -366,7 +375,7 @@ const TextureGenerator = struct {
|
||||
while(dy <= 0) : (dy += 1) {
|
||||
if(y + dy < 0 or y + dy >= 16) continue;
|
||||
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) {
|
||||
hasDifferentItems = true;
|
||||
}
|
||||
@ -387,7 +396,7 @@ const TextureGenerator = struct {
|
||||
if(y + dy < 0 or y + dy >= 16) continue;
|
||||
const otherItem = itemGrid[@intCast(usize, x + dx)][@intCast(usize, y + dy)];
|
||||
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;
|
||||
}
|
||||
|
||||
pub fn generate(tool: *Tool) void {
|
||||
pub fn generate(tool: *Tool) !void {
|
||||
const img = tool.texture;
|
||||
var pixelMaterials: [16][16]PixelData = undefined;
|
||||
var x: u8 = 0;
|
||||
@ -462,7 +471,7 @@ const TextureGenerator = struct {
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if(pixelMaterials[x][y].items.items.len != 0) {
|
||||
// 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:
|
||||
const lightTL = heightMap[x][y] - heightMap[x + 1][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);
|
||||
img.setRGB(x, y, material.colorPalette[light]);
|
||||
}
|
||||
@ -513,7 +524,7 @@ const ToolPhysics = struct {
|
||||
while(y > 0) : (y -= 5) {
|
||||
var x: u32 = 0;
|
||||
while(x < 5) : (x += 5) {
|
||||
if(tool.craftingGrid[y + x]) {
|
||||
if(tool.craftingGrid[y + x] != null) {
|
||||
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
|
||||
var x: u32 = 4;
|
||||
while(true) {
|
||||
if(tool.craftingGrid[y + x]) {
|
||||
tool.handlePosition.x = TextureGenerator.GRID_CENTERS_X[x + y] - 0.5;
|
||||
tool.handlePosition.y = TextureGenerator.GRID_CENTERS_Y[x + y] - 0.5;
|
||||
if(tool.craftingGrid[y + x] != null) {
|
||||
tool.handlePosition[0] = @intToFloat(f32, TextureGenerator.GRID_CENTERS_X[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:
|
||||
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;
|
||||
if(x != 4 and tool.craftingGrid[y + x + 1])
|
||||
if(x != 4 and tool.craftingGrid[y + x + 1] != null)
|
||||
neighbors += 1;
|
||||
if(y != 0) {
|
||||
if(tool.craftingGrid[y - 5 + x])
|
||||
if(tool.craftingGrid[y - 5 + x] != null)
|
||||
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;
|
||||
if(x != 4 and tool.craftingGrid[y - 5 + x + 1])
|
||||
if(x != 4 and tool.craftingGrid[y - 5 + x + 1] != null)
|
||||
neighbors += 1;
|
||||
}
|
||||
if(neighbors <= 1) {
|
||||
@ -563,8 +574,8 @@ const ToolPhysics = struct {
|
||||
if(tool.materialGrid[x][y]) |item| {
|
||||
if(item.material) |material| {
|
||||
const localMass = material.density;
|
||||
centerOfMass.x += localMass*(@intToFloat(f32, x) + 0.5);
|
||||
centerOfMass.y += localMass*(@intToFloat(f32, y) + 0.5);
|
||||
centerOfMass[0] += localMass*(@intToFloat(f32, x) + 0.5);
|
||||
centerOfMass[1] += localMass*(@intToFloat(f32, y) + 0.5);
|
||||
mass += localMass;
|
||||
}
|
||||
}
|
||||
@ -582,8 +593,8 @@ const ToolPhysics = struct {
|
||||
if(tool.materialGrid[x][y]) |item| {
|
||||
if(item.material) |material| {
|
||||
const localMass = material.density;
|
||||
const dx = @intToFloat(f32, x) + 0.5 - tool.centerOfMass.x;
|
||||
const dy = @intToFloat(f32, y) + 0.5 - tool.centerOfMass.y;
|
||||
const dx = @intToFloat(f32, x) + 0.5 - tool.centerOfMass[0];
|
||||
const dy = @intToFloat(f32, y) + 0.5 - tool.centerOfMass[1];
|
||||
inertia += localMass*(dx*dx + dy*dy);
|
||||
}
|
||||
}
|
||||
@ -591,21 +602,21 @@ const ToolPhysics = struct {
|
||||
}
|
||||
tool.inertiaCenterOfMass = inertia;
|
||||
// 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.
|
||||
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:
|
||||
const originalAngle = std.math.atan2(f32, @intToFloat(f32, point.y) + 0.5 - center.y, @intToFloat(f32, point.x) + 0.5 - center.x) - initialAngle;
|
||||
const originalDistance = @cos(originalAngle)*vec.length(center - Vec2f{@intToFloat(f32, point.x) + 0.5, @intToFloat(f32, point.y) + 0.5});
|
||||
var numOfSmoothPixels: u32 = 0;
|
||||
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.*[0]) + 0.5, @intToFloat(f32, point.*[1]) + 0.5});
|
||||
var numOfSmoothPixels: u31 = 0;
|
||||
var x: f32 = 0;
|
||||
while(x < 16) : (x += 1) {
|
||||
var y: f32 = 0;
|
||||
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 deltaAngle = @fabs(angle - originalAngle);
|
||||
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.
|
||||
@ -622,32 +633,32 @@ const ToolPhysics = struct {
|
||||
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.
|
||||
// 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.
|
||||
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 rightCollisionAngle: f32 = 0;
|
||||
var frontCollisionDistance: f32 = 0;
|
||||
var x: i32 = 0;
|
||||
var x: u8 = 0;
|
||||
while(x < 16) : (x += 1) {
|
||||
var y: i32 = 0;
|
||||
var y: u8 = 0;
|
||||
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 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});
|
||||
if(angle < leftCollisionAngle) {
|
||||
leftCollisionAngle = angle;
|
||||
leftCollisionPoint = Vec3i{x, y, 0};
|
||||
leftCollisionPoint.* = Vec3i{x, y, 0};
|
||||
}
|
||||
if(angle > rightCollisionAngle) {
|
||||
rightCollisionAngle = angle;
|
||||
rightCollisionPoint = Vec3i{x, y, 0};
|
||||
rightCollisionPoint.* = Vec3i{x, y, 0};
|
||||
}
|
||||
if(distance > frontCollisionDistance) {
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -685,7 +696,7 @@ const ToolPhysics = struct {
|
||||
// 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).
|
||||
// 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
|
||||
}
|
||||
@ -701,27 +712,26 @@ const ToolPhysics = struct {
|
||||
while(x < 2) : (x += 1) {
|
||||
var y: i32 = -1;
|
||||
while(y <= 2) : (y += 1) {
|
||||
if(x + collisionPointLower.x >= 0 and x + collisionPointLower.x < 16) {
|
||||
if(y + collisionPointLower.y >= 0 and y + collisionPointLower.y < 16) {
|
||||
if(tool.materialGrid[x + collisionPointLower.x][y + collisionPointLower.y])
|
||||
if(x + collisionPointLower[0] >= 0 and x + collisionPointLower[0] < 16) {
|
||||
if(y + collisionPointLower[1] >= 0 and y + collisionPointLower[1] < 16) {
|
||||
if(tool.materialGrid[@intCast(usize, x + collisionPointLower[0])][@intCast(usize, y + collisionPointLower[1])] != null)
|
||||
neighborsLower += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var neighborsUpper: u32 = 0;
|
||||
var dirUpper: Vec2i = Vec2i{0};
|
||||
// Vector2i dirUpper = new Vector2i();
|
||||
var dirUpper: Vec2i = Vec2i{0, 0};
|
||||
x = -1;
|
||||
while(x < 2) : (x += 1) {
|
||||
var y: i32 = -1;
|
||||
while(y <= 2) : (y += 1) {
|
||||
if(x + collisionPointUpper.x >= 0 and x + collisionPointUpper.x < 16) {
|
||||
if(y + collisionPointUpper.y >= 0 and y + collisionPointUpper.y < 16) {
|
||||
if(tool.materialGrid[x + collisionPointUpper.x][y + collisionPointUpper.y]) {
|
||||
if(x + collisionPointUpper[0] >= 0 and x + collisionPointUpper[0] < 16) {
|
||||
if(y + collisionPointUpper[1] >= 0 and y + collisionPointUpper[1] < 16) {
|
||||
if(tool.materialGrid[@intCast(usize, x + collisionPointUpper[0])][@intCast(usize, y + collisionPointUpper[1])] != null) {
|
||||
neighborsUpper += 1;
|
||||
dirUpper.x += x;
|
||||
dirUpper.y += y;
|
||||
dirUpper[0] += x;
|
||||
dirUpper[1] += y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -730,7 +740,7 @@ const ToolPhysics = struct {
|
||||
if(neighborsLower > 3 and neighborsUpper > 3) return 0;
|
||||
|
||||
// A pickaxe never points upwards:
|
||||
if (neighborsUpper == 3 and dirUpper.y == 2) {
|
||||
if(neighborsUpper == 3 and dirUpper[1] == 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -740,8 +750,8 @@ const ToolPhysics = struct {
|
||||
/// Determines how good an axe this side of the tool would make.
|
||||
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.
|
||||
const collisionPointLowerFloat = Vec2f{@intToFloat(f32, collisionPointLower.x), @intToFloat(f32, collisionPointLower.y)};
|
||||
const collisionPointUpperFloat = Vec2f{@intToFloat(f32, collisionPointUpper.x), @intToFloat(f32, collisionPointUpper.y)};
|
||||
const collisionPointLowerFloat = Vec2f{@intToFloat(f32, collisionPointLower[0]), @intToFloat(f32, collisionPointLower[1])};
|
||||
const collisionPointUpperFloat = Vec2f{@intToFloat(f32, collisionPointUpper[0]), @intToFloat(f32, collisionPointUpper[1])};
|
||||
const areaFactor = 0.25 + vec.length(collisionPointLowerFloat - collisionPointUpperFloat)/4;
|
||||
|
||||
return areaFactor*calculateImpactEnergy(tool, collisionPointLower)/8;
|
||||
@ -764,7 +774,7 @@ const ToolPhysics = struct {
|
||||
var y: u8 = 0;
|
||||
while(y < 16) : (y += 1) {
|
||||
sandPiles[x][y] = std.math.maxInt(u8);
|
||||
if (!tool.materialGrid[x][y]) {
|
||||
if(tool.materialGrid[x][y] == null) {
|
||||
sandPiles[x][y] = 0;
|
||||
try stack.append(Entry{.x=x, .y=y});
|
||||
} else if(x == 0 or x == 15 or y == 0 or y == 15) {
|
||||
@ -776,28 +786,28 @@ const ToolPhysics = struct {
|
||||
while(stack.popOrNull()) |entry| {
|
||||
x = entry.x;
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
var y: u8 = 0;
|
||||
while(y < 16) : (y += 1) {
|
||||
volume += sandPiles[x][y];
|
||||
volume += @intToFloat(f32, sandPiles[x][y]);
|
||||
}
|
||||
}
|
||||
volume /= 256; // TODO: Balancing
|
||||
@ -816,28 +826,28 @@ const ToolPhysics = struct {
|
||||
|
||||
|
||||
/// Determines all the basic properties of the tool.
|
||||
pub fn evaluateTool(tool: *Tool) void {
|
||||
pub fn evaluateTool(tool: *Tool) !void {
|
||||
const hasGoodHandle = findHandle(tool);
|
||||
calculateDurability(tool);
|
||||
determineInertia(tool);
|
||||
var leftCollisionPointLower = Vec3i{};
|
||||
var rightCollisionPointLower = Vec3i{};
|
||||
var frontCollisionPointLower = Vec3i{};
|
||||
var leftCollisionPointUpper = Vec3i{};
|
||||
var rightCollisionPointUpper = Vec3i{};
|
||||
var frontCollisionPointUpper = Vec3i{};
|
||||
var leftCollisionPointLower = Vec3i{0, 0, 0};
|
||||
var rightCollisionPointLower = Vec3i{0, 0, 0};
|
||||
var frontCollisionPointLower = Vec3i{0, 0, 0};
|
||||
var leftCollisionPointUpper = Vec3i{0, 0, 0};
|
||||
var rightCollisionPointUpper = Vec3i{0, 0, 0};
|
||||
var frontCollisionPointUpper = Vec3i{0, 0, 0};
|
||||
determineCollisionPoints(tool, &leftCollisionPointLower, &rightCollisionPointLower, &frontCollisionPointLower, 16);
|
||||
determineCollisionPoints(tool, &rightCollisionPointUpper, &leftCollisionPointUpper, &frontCollisionPointUpper, -20);
|
||||
|
||||
const leftPP = evaluatePickaxePower(tool, &leftCollisionPointLower, &leftCollisionPointUpper);
|
||||
const rightPP = evaluatePickaxePower(tool, &rightCollisionPointLower, &rightCollisionPointUpper);
|
||||
const leftPP = evaluatePickaxePower(tool, leftCollisionPointLower, leftCollisionPointUpper);
|
||||
const rightPP = evaluatePickaxePower(tool, rightCollisionPointLower, rightCollisionPointUpper);
|
||||
tool.pickaxePower = @max(leftPP, rightPP); // TODO: Adjust the swing direction.
|
||||
|
||||
const leftAP = evaluateAxePower(tool, &leftCollisionPointLower, &leftCollisionPointUpper);
|
||||
const rightAP = evaluateAxePower(tool, &rightCollisionPointLower, &rightCollisionPointUpper);
|
||||
const leftAP = evaluateAxePower(tool, leftCollisionPointLower, leftCollisionPointUpper);
|
||||
const rightAP = evaluateAxePower(tool, rightCollisionPointLower, rightCollisionPointUpper);
|
||||
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.
|
||||
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.
|
||||
inertiaCenterOfMass: f32,
|
||||
|
||||
pub fn init(allocator: Allocator) !*Tool {
|
||||
var self = try allocator.create(Tool);
|
||||
self.texture = try graphics.Image.init(allocator, 16, 16);
|
||||
pub fn init() !*Tool {
|
||||
var self = try main.globalAllocator.create(Tool);
|
||||
self.texture = try graphics.Image.init(main.globalAllocator, 16, 16);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Tool, allocator: Allocator) void {
|
||||
allocator.destroy(self);
|
||||
self.texture.deinit(allocator);
|
||||
pub fn deinit(self: *const Tool) void {
|
||||
main.globalAllocator.destroy(self);
|
||||
self.texture.deinit(main.globalAllocator);
|
||||
}
|
||||
|
||||
pub fn initFromCraftingGrid(allocator: Allocator, craftingGrid: [25]?*const BaseItem, seed: u32) !*Tool {
|
||||
var self = try init(allocator);
|
||||
pub fn initFromCraftingGrid(craftingGrid: [25]?*const BaseItem, seed: u32) !*Tool {
|
||||
var self = try init();
|
||||
self.seed = seed;
|
||||
self.craftingGrid = craftingGrid;
|
||||
// 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.
|
||||
TextureGenerator.generate(self);
|
||||
ToolPhysics.evaluateTool(self);
|
||||
try TextureGenerator.generate(self);
|
||||
try ToolPhysics.evaluateTool(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn initFromJson(allocator: Allocator, jsonObject: JsonElement) !*Tool {
|
||||
var self = try initFromCraftingGrid(allocator, extractItemsFromJson(jsonObject.getChild("grid")), jsonObject.get(u32, "seed", 0));
|
||||
self.durability = jsonObject.get(i32, "durability", self.maxDurability);
|
||||
pub fn initFromJson(jsonObject: JsonElement) !*Tool {
|
||||
var self = try initFromCraftingGrid(extractItemsFromJson(jsonObject.getChild("grid")), jsonObject.get(u32, "seed", 0));
|
||||
self.durability = jsonObject.get(u32, "durability", self.maxDurability);
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -920,7 +930,7 @@ const Tool = struct {
|
||||
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 jsonArray = try JsonElement.initArray(allocator);
|
||||
for(self.craftingGrid) |nullItem| {
|
||||
@ -964,23 +974,28 @@ const Tool = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Item = union(u8) {
|
||||
pub const Item = union(enum) {
|
||||
baseItem: *const BaseItem,
|
||||
tool: *const Tool,
|
||||
|
||||
pub fn init(self: *Item, allocator: Allocator) !void {
|
||||
_ = allocator;
|
||||
_ = self;
|
||||
|
||||
pub fn init(jsonObject: JsonElement) !Item {
|
||||
if(reverseIndices.get(jsonObject.get([]const u8, "item", "null"))) |baseItem| {
|
||||
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) {
|
||||
.baseItem => {
|
||||
|
||||
},
|
||||
.tool => |_tool| {
|
||||
_tool.deinit(allocator);
|
||||
_tool.deinit();
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1002,7 +1017,7 @@ pub const Item = union(u8) {
|
||||
try jsonObject.put("item", _baseItem.id);
|
||||
},
|
||||
.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();
|
||||
}
|
||||
|
||||
pub fn filled(self: *ItemStack) bool {
|
||||
pub fn filled(self: *const ItemStack) bool {
|
||||
if(self.item) |item| {
|
||||
return self.amount >= item.stackSize();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn empty(self: *ItemStack) bool {
|
||||
pub fn empty(self: *const ItemStack) bool {
|
||||
return self.amount == 0;
|
||||
}
|
||||
|
||||
/// Returns the number of items actually added/removed.
|
||||
pub fn add(self: *ItemStack, number: i32) i32 {
|
||||
std.debug.assert(self.item);
|
||||
const newAmount = self.amount + number;
|
||||
var returnValue: i32 = 0;
|
||||
pub fn add(self: *ItemStack, number: anytype) @TypeOf(number) {
|
||||
std.debug.assert(self.item != null);
|
||||
var newAmount = self.amount + number;
|
||||
var returnValue = number;
|
||||
if(newAmount < 0) {
|
||||
returnValue = number - newAmount;
|
||||
newAmount = 0;
|
||||
returnValue = newAmount - self.amount;
|
||||
} else if(newAmount > self.item.?.stackSize()) {
|
||||
returnValue = number - newAmount + self.item.?.stackSize();
|
||||
newAmount = self.item.?.stackSize();
|
||||
returnValue = newAmount - self.amount;
|
||||
}
|
||||
self.amount = @intCast(u16, newAmount);
|
||||
if(self.empty()) {
|
||||
@ -1050,7 +1066,7 @@ pub const ItemStack = struct {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
return @as(u32, self.amount) + number <= self.item.?.stackSize();
|
||||
}
|
||||
@ -1063,11 +1079,11 @@ pub const ItemStack = struct {
|
||||
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);
|
||||
if(self.item) |item| {
|
||||
item.insertToJson(allocator, result);
|
||||
result.put("amount", self.amount);
|
||||
try item.insertIntoJson(allocator, result);
|
||||
try result.put("amount", self.amount);
|
||||
}
|
||||
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 reverseIndices: std.StringHashMap(*BaseItem) = undefined;
|
||||
var itemList: std.ArrayList(BaseItem) = undefined;
|
||||
var itemList: [65536]BaseItem = undefined;
|
||||
var itemListSize: u16 = 0;
|
||||
|
||||
|
||||
pub fn globalInit() void {
|
||||
arena = std.heap.ArenaAllocator.init(std.heap.page_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 {
|
||||
std.log.info("{s}", .{id});
|
||||
if(reverseIndices.contains(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 {
|
||||
reverseIndices.clearAndFree();
|
||||
itemList.clearAndFree();
|
||||
itemListSize = 0;
|
||||
// TODO: Use arena.reset() instead.
|
||||
arena.deinit();
|
||||
arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
@ -1113,6 +1225,5 @@ pub fn reset() void {
|
||||
|
||||
pub fn deinit() void {
|
||||
reverseIndices.clearAndFree();
|
||||
itemList.clearAndFree();
|
||||
arena.deinit();
|
||||
}
|
13
src/json.zig
13
src/json.zig
@ -136,7 +136,7 @@ pub const JsonElement = union(JsonType) {
|
||||
.Null => return JsonElement{.JsonNull={}},
|
||||
.Bool => return JsonElement{.JsonBool=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 => {
|
||||
if(@TypeOf(value) == JsonElement) {
|
||||
return value;
|
||||
@ -144,6 +144,14 @@ pub const JsonElement = union(JsonType) {
|
||||
@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 => {
|
||||
@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 {
|
||||
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 {
|
||||
@ -185,7 +193,6 @@ pub const JsonElement = union(JsonType) {
|
||||
return self.* == JsonType.JsonNull;
|
||||
}
|
||||
|
||||
// TODO: toString()
|
||||
fn escape(string: []const u8, allocator: Allocator) ![]const u8 {
|
||||
var out = std.ArrayList(u8).init(allocator);
|
||||
for(string) |char| {
|
||||
|
@ -22,6 +22,7 @@ pub const c = @cImport ({
|
||||
});
|
||||
|
||||
pub threadlocal var threadAllocator: std.mem.Allocator = undefined;
|
||||
pub var globalAllocator: std.mem.Allocator = undefined;
|
||||
pub var threadPool: utils.ThreadPool = undefined;
|
||||
|
||||
var logFile: std.fs.File = undefined;
|
||||
@ -218,6 +219,11 @@ pub fn main() !void {
|
||||
defer if(gpa.deinit()) {
|
||||
@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.
|
||||
try std.fs.cwd().makePath("logs");
|
||||
|
@ -5,15 +5,19 @@ const assets = @import("assets.zig");
|
||||
const Block = @import("blocks.zig").Block;
|
||||
const chunk = @import("chunk.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 game = @import("game.zig");
|
||||
const settings = @import("settings.zig");
|
||||
const json = @import("json.zig");
|
||||
const JsonElement = json.JsonElement;
|
||||
const renderer = @import("renderer.zig");
|
||||
const utils = @import("utils.zig");
|
||||
const vec = @import("vec.zig");
|
||||
const Vec3d = vec.Vec3d;
|
||||
const Vec3f = vec.Vec3f;
|
||||
|
||||
//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_itemStackCollect: u8 = 7;
|
||||
const type_timeAndBiome: u8 = 8;
|
||||
fn receive(_: *Connection, data: []const u8) !void {
|
||||
fn receive(conn: *Connection, data: []const u8) !void {
|
||||
switch(data[0]) {
|
||||
type_renderDistance => {
|
||||
const renderDistance = std.mem.readIntBig(i32, data[1..5]);
|
||||
@ -1047,18 +1051,18 @@ pub const Protocols: struct {
|
||||
// );
|
||||
},
|
||||
type_itemStackCollect => {
|
||||
// TODO:
|
||||
// JsonObject json = JsonParser.parseObjectFromString(new String(data, offset + 1, length - 1, StandardCharsets.UTF_8));
|
||||
// Item item = Item.load(json, Cubyz.world.registries);
|
||||
// if (item == null) {
|
||||
// break;
|
||||
// }
|
||||
// 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());
|
||||
// if(remaining != 0) {
|
||||
// // Couldn't collect everything → drop it again.
|
||||
// itemStackDrop(Cubyz.world.serverConnection, new ItemStack(item, remaining), Cubyz.player.getPosition(), Camera.getDirection(), 0);
|
||||
// }
|
||||
const jsonObject = json.parseFromString(main.threadAllocator, data[1..]);
|
||||
defer jsonObject.free(main.threadAllocator);
|
||||
const item = try items.Item.init(jsonObject);
|
||||
game.Player.mutex.lock();
|
||||
defer game.Player.mutex.unlock();
|
||||
const remaining = game.Player.inventory__SEND_CHANGES_TO_SERVER.addItem(item, jsonObject.get(u16, "amount", 0));
|
||||
|
||||
try sendInventory_full(conn, game.Player.inventory__SEND_CHANGES_TO_SERVER);
|
||||
if(remaining != 0) {
|
||||
// Couldn't collect everything → drop it again.
|
||||
try itemStackDrop(conn, ItemStack{.item=item, .amount=remaining}, game.Player.getPosBlocking(), Vec3f{0, 0, 0}, 0);
|
||||
}
|
||||
},
|
||||
type_timeAndBiome => {
|
||||
if(game.world) |world| {
|
||||
@ -1134,10 +1138,14 @@ pub const Protocols: struct {
|
||||
try conn.sendImportant(id, &data);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// public void sendInventory_full(ServerConnection conn, Inventory inv) {
|
||||
// addHeaderAndSendImportant(conn, INVENTORY_FULL, inv.save().toString().getBytes(StandardCharsets.UTF_8));
|
||||
// }
|
||||
|
||||
pub fn sendInventory_full(conn: *Connection, inv: Inventory) !void {
|
||||
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 {
|
||||
var data: [1]u8 = undefined;
|
||||
@ -1145,23 +1153,28 @@ pub const Protocols: struct {
|
||||
try conn.sendImportant(id, &data);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// public void itemStackDrop(ServerConnection conn, ItemStack stack, Vector3d pos, Vector3f dir, float vel) {
|
||||
// JsonObject json = stack.store();
|
||||
// json.put("x", pos.x);
|
||||
// json.put("y", pos.y);
|
||||
// json.put("z", pos.z);
|
||||
// json.put("dirX", dir.x);
|
||||
// json.put("dirY", dir.y);
|
||||
// json.put("dirZ", dir.z);
|
||||
// json.put("vel", vel);
|
||||
// addHeaderAndSendImportant(conn, ITEM_STACK_DROP, json.toString().getBytes(StandardCharsets.UTF_8));
|
||||
// }
|
||||
pub fn itemStackDrop(conn: *Connection, stack: ItemStack, pos: Vec3d, dir: Vec3f, vel: f32) !void {
|
||||
var jsonObject = try stack.store(main.threadAllocator);
|
||||
defer jsonObject.free(main.threadAllocator);
|
||||
try jsonObject.put("x", pos[0]);
|
||||
try jsonObject.put("y", pos[1]);
|
||||
try jsonObject.put("z", pos[2]);
|
||||
try jsonObject.put("dirX", dir[0]);
|
||||
try jsonObject.put("dirY", dir[1]);
|
||||
try jsonObject.put("dirZ", dir[2]);
|
||||
try jsonObject.put("vel", vel);
|
||||
const string = try jsonObject.toString(main.threadAllocator);
|
||||
defer main.threadAllocator.free(string);
|
||||
try addHeaderAndSendImportant(conn, type_itemStackDrop, string);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// public void itemStackCollect(User user, ItemStack stack) {
|
||||
// addHeaderAndSendImportant(user, ITEM_STACK_COLLECT, stack.store().toString().getBytes(StandardCharsets.UTF_8));
|
||||
// }
|
||||
pub fn itemStackCollect(conn: *Connection, stack: ItemStack) !void {
|
||||
var jsonObject = try stack.store(main.threadAllocator);
|
||||
defer jsonObject.free(main.threadAllocator);
|
||||
const string = try jsonObject.toString(main.threadAllocator);
|
||||
defer main.threadAllocator.free(string);
|
||||
try addHeaderAndSendImportant(conn, type_itemStackCollect, string);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// public void sendTimeAndBiome(User user, ServerWorld world) {
|
||||
|
@ -10,16 +10,16 @@ pub fn scrambleSeed(seed: *u64) void {
|
||||
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;
|
||||
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 {
|
||||
nextWithBitSize(T, seed, @bitSizeOf(T));
|
||||
fn next(comptime T: type, seed: *u64) 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) {
|
||||
@compileError("Did not yet implement support for bigger numbers.");
|
||||
} else {
|
||||
@ -27,8 +27,8 @@ pub fn nextInt(T: type, seed: *u64) T {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nextIntBounded(T: type, seed: *u64, bound: T) T {
|
||||
var bitSize = std.math.log2_int_ceil(bound);
|
||||
pub fn nextIntBounded(comptime T: type, seed: *u64, bound: T) T {
|
||||
var bitSize = std.math.log2_int_ceil(T, bound);
|
||||
var result = nextWithBitSize(T, seed, bitSize);
|
||||
while(result >= bound) {
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ pub fn length(self: anytype) @typeInfo(@TypeOf(self)).Vector.child {
|
||||
return @sqrt(@reduce(.Add, self*self));
|
||||
}
|
||||
|
||||
pub fn normalize(self: anytype) @typeInfo(@TypeOf(self)).Vector.child {
|
||||
return self/length(self);
|
||||
pub fn normalize(self: anytype) @TypeOf(self) {
|
||||
return self/@splat(@typeInfo(@TypeOf(self)).Vector.len, length(self));
|
||||
}
|
||||
|
||||
pub fn cross(self: anytype, other: @TypeOf(self)) @TypeOf(self) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user