@ -55,8 +55,21 @@ inventory.create(size: int) -> int
|
||||
-- Create inventory copy. Returns the created copy ID.
|
||||
inventory.clone(invid: int) -> int
|
||||
|
||||
-- Move item from slotA of invA to slotB of invB.
|
||||
-- Move an item from slotA of invA to slotB of invB.
|
||||
-- invA may be the same as invB.
|
||||
-- If slotB will be chosen automaticly if argument is not specified.
|
||||
-- The move may be incomplete if the available slot has no enough stack space.
|
||||
inventory.move(invA: int, slotA: int, invB: int, slotB: int)
|
||||
|
||||
-- Moves an item from slotA of inventory invA to a suitable slot(s)
|
||||
-- in the specified range of inventory invB.
|
||||
-- invA may be the same as invB.
|
||||
-- The move may be incomplete if the available slots are filled.
|
||||
inventory.move(
|
||||
invA: int,
|
||||
slotA: int,
|
||||
invB: int,
|
||||
rangeBegin: int,
|
||||
[optional] rangeEnd: int
|
||||
)
|
||||
```
|
||||
|
||||
@ -66,5 +66,20 @@ inventory.clone(invid: int) -> int
|
||||
-- Перемещает предмет из slotA инвентаря invA в slotB инвентаря invB.
|
||||
-- invA и invB могут указывать на один инвентарь.
|
||||
-- slotB будет выбран автоматически, если не указывать явно.
|
||||
-- Перемещение может быть неполным, если стек слота заполнится.
|
||||
inventory.move(invA: int, slotA: int, invB: int, slotB: int)
|
||||
|
||||
-- Перемещает предмет из slotA инвентаря invA в подходящий слот, находящийся в
|
||||
-- указанном отрезке инвентаря invB.
|
||||
-- invA и invB могут указывать на один инвентарь.
|
||||
-- rangeBegin - начало отрезка.
|
||||
-- rangeEnd - конец отрезка.
|
||||
-- Перемещение может быть неполным, если доступные слоты будут заполнены.
|
||||
inventory.move_range(
|
||||
invA: int,
|
||||
slotA: int,
|
||||
invB: int,
|
||||
rangeBegin: int,
|
||||
[опционально] rangeEnd: int
|
||||
)
|
||||
```
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"texture": "bazalt",
|
||||
"breakable": false
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
"texture": "blue_lamp",
|
||||
"emission": [0, 0, 15],
|
||||
"shadeless": true,
|
||||
"material": "base:glass"
|
||||
"material": "base:glass",
|
||||
"base:durability": 0.3
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
{
|
||||
"texture": "brick"
|
||||
}
|
||||
"texture": "brick",
|
||||
"base:durability": 10.5
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
{
|
||||
"texture": "coal_ore"
|
||||
"texture": "coal_ore",
|
||||
"base:durability": 16.0
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"texture": "dirt",
|
||||
"material": "base:ground",
|
||||
"surface-replacement": "base:grass_block"
|
||||
"surface-replacement": "base:grass_block",
|
||||
"base:durability": 1.0
|
||||
}
|
||||
|
||||
@ -7,5 +7,6 @@
|
||||
"replaceable": true,
|
||||
"grounded": true,
|
||||
"model": "X",
|
||||
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7]
|
||||
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7],
|
||||
"base:durability": 0.0
|
||||
}
|
||||
|
||||
@ -4,5 +4,6 @@
|
||||
"draw-group": 2,
|
||||
"light-passing": true,
|
||||
"sky-light-passing": true,
|
||||
"translucent": true
|
||||
"translucent": true,
|
||||
"base:durability": 0.36
|
||||
}
|
||||
|
||||
@ -8,5 +8,6 @@
|
||||
"replaceable": true,
|
||||
"grounded": true,
|
||||
"model": "X",
|
||||
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7]
|
||||
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7],
|
||||
"base:durability": 0.0
|
||||
}
|
||||
|
||||
@ -7,5 +7,6 @@
|
||||
"grass_top",
|
||||
"grass_side",
|
||||
"grass_side"
|
||||
]
|
||||
}
|
||||
],
|
||||
"base:durability": 1.3
|
||||
}
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
"texture": "green_lamp",
|
||||
"emission": [0, 15, 0],
|
||||
"shadeless": true,
|
||||
"material": "base:glass"
|
||||
"material": "base:glass",
|
||||
"base:durability": 0.3
|
||||
}
|
||||
|
||||
@ -3,5 +3,6 @@
|
||||
"material": "base:glass",
|
||||
"draw-group": 4,
|
||||
"light-passing": true,
|
||||
"translucent": true
|
||||
"translucent": true,
|
||||
"base:durability": 0.3
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"texture": "lamp",
|
||||
"emission": [15, 14, 13],
|
||||
"shadeless": true
|
||||
"shadeless": true,
|
||||
"base:durability": 0.3
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"texture": "leaves",
|
||||
"material": "base:grass"
|
||||
}
|
||||
"material": "base:grass",
|
||||
"base:durability": 0.7
|
||||
}
|
||||
|
||||
@ -8,5 +8,6 @@
|
||||
"light-passing": true,
|
||||
"sky-light-passing": true,
|
||||
"shadeless": true,
|
||||
"material": "base:glass"
|
||||
"material": "base:glass",
|
||||
"base:durability": 0.2
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"texture": "metal",
|
||||
"material": "base:metal"
|
||||
"material": "base:metal",
|
||||
"base:durability": 10.0
|
||||
}
|
||||
|
||||
@ -12,5 +12,6 @@
|
||||
"hitbox": [0.0, 0.0, 0.0, 1.0, 1.0, 0.2],
|
||||
"light-passing": true,
|
||||
"sky-light-passing": true,
|
||||
"rotation": "pane"
|
||||
"rotation": "pane",
|
||||
"base:durability": 2.5
|
||||
}
|
||||
|
||||
@ -11,5 +11,6 @@
|
||||
"hitbox": [0.25, 0.0, 0.25, 0.5, 1.0, 0.5],
|
||||
"light-passing": true,
|
||||
"rotation": "pipe",
|
||||
"material": "base:metal"
|
||||
"material": "base:metal",
|
||||
"base:durability": 4.7
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"texture": "planks",
|
||||
"material": "base:wood"
|
||||
}
|
||||
"material": "base:wood",
|
||||
"base:durability": 5.0
|
||||
}
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
"texture": "red_lamp",
|
||||
"emission": [15, 0, 0],
|
||||
"shadeless": true,
|
||||
"material": "base:glass"
|
||||
"material": "base:glass",
|
||||
"base:durability": 0.3
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"texture": "rust",
|
||||
"material": "base:metal"
|
||||
"material": "base:metal",
|
||||
"base:durability": 6.6
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"texture": "sand",
|
||||
"material": "base:sand"
|
||||
}
|
||||
"material": "base:sand",
|
||||
"base:durability": 0.7
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
{
|
||||
"texture": "stone"
|
||||
}
|
||||
"texture": "stone",
|
||||
"base:durability": 12.0
|
||||
}
|
||||
|
||||
@ -31,5 +31,6 @@
|
||||
"particles:smoke_0",
|
||||
"particles:smoke_1"
|
||||
]
|
||||
}
|
||||
},
|
||||
"base:durability": 0.1
|
||||
}
|
||||
|
||||
@ -8,5 +8,6 @@
|
||||
"wood",
|
||||
"wood"
|
||||
],
|
||||
"rotation": "pipe"
|
||||
}
|
||||
"rotation": "pipe",
|
||||
"base:durability": 6.0
|
||||
}
|
||||
|
||||
@ -14,5 +14,6 @@
|
||||
"rotation": "pane",
|
||||
"model": "aabb",
|
||||
"hitbox": [0.0, 0.0, 0.8, 1.0, 2.0, 0.2],
|
||||
"ambient-occlusion": false
|
||||
"ambient-occlusion": false,
|
||||
"base:durability": 5.9
|
||||
}
|
||||
|
||||
1
res/content/base/config/user-props.toml
Normal file
@ -0,0 +1 @@
|
||||
"base:durability" = {}
|
||||
@ -4,7 +4,7 @@
|
||||
],
|
||||
"hitbox": [0.4, 0.25, 0.4],
|
||||
"sensors": [
|
||||
["aabb", -0.2, -0.2, -0.2, 0.2, 0.2, 0.2],
|
||||
["radius", 0.3],
|
||||
["radius", 1.6]
|
||||
],
|
||||
"blocking": false
|
||||
|
||||
11
res/content/base/modules/util.lua
Normal file
@ -0,0 +1,11 @@
|
||||
local base_entities = {}
|
||||
|
||||
function base_entities.drop(ppos, itemid, count, pickup_delay)
|
||||
return entities.spawn("base:drop", ppos, {base__drop={
|
||||
id=itemid,
|
||||
count=count,
|
||||
pickup_delay=pickup_delay
|
||||
}})
|
||||
end
|
||||
|
||||
return base_entities
|
||||
@ -3,10 +3,13 @@ local body = entity.rigidbody
|
||||
local rig = entity.skeleton
|
||||
|
||||
inair = true
|
||||
ready = false
|
||||
target = -1
|
||||
timer = 0.3
|
||||
|
||||
local dropitem = ARGS
|
||||
if dropitem then
|
||||
timer = dropitem.pickup_delay or timer
|
||||
end
|
||||
if SAVED_DATA.item then
|
||||
dropitem.id = item.index(SAVED_DATA.item)
|
||||
dropitem.count = SAVED_DATA.count
|
||||
@ -40,7 +43,6 @@ function on_grounded(force)
|
||||
mat4.scale(matrix, scale, matrix)
|
||||
rig:set_matrix(0, matrix)
|
||||
inair = false
|
||||
ready = true
|
||||
end
|
||||
|
||||
function on_fall()
|
||||
@ -50,12 +52,12 @@ end
|
||||
function on_sensor_enter(index, oid)
|
||||
local playerid = hud.get_player()
|
||||
local playerentity = player.get_entity(playerid)
|
||||
if ready and oid == playerentity and index == 0 then
|
||||
if timer < 0.0 and oid == playerentity and index == 0 then
|
||||
entity:despawn()
|
||||
inventory.add(player.get_inventory(playerid), dropitem.id, dropitem.count)
|
||||
audio.play_sound_2d("events/pickup", 0.5, 0.8+math.random()*0.4, "regular")
|
||||
end
|
||||
if index == 1 and ready and oid == playerentity then
|
||||
if index == 1 and oid == playerentity then
|
||||
target = oid
|
||||
end
|
||||
end
|
||||
@ -80,8 +82,12 @@ function on_render()
|
||||
end
|
||||
end
|
||||
|
||||
function on_update()
|
||||
function on_update(tps)
|
||||
timer = timer - 1.0/tps
|
||||
if target ~= -1 then
|
||||
if timer > 0.0 then
|
||||
return
|
||||
end
|
||||
local dir = vec3.sub(entities.get(target).transform:get_pos(), tsf:get_pos())
|
||||
vec3.normalize(dir, dir)
|
||||
vec3.mul(dir, 10.0, dir)
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
local base_util = require "util"
|
||||
|
||||
local DROP_FORCE = 8
|
||||
local DROP_INIT_VEL = {0, 3, 0}
|
||||
|
||||
@ -17,10 +19,7 @@ function on_hud_open()
|
||||
local pvel = {player.get_vel(pid)}
|
||||
local ppos = vec3.add({player.get_pos(pid)}, {0, 0.7, 0})
|
||||
local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE)
|
||||
local drop = entities.spawn("base:drop", ppos, {base__drop={
|
||||
id=itemid,
|
||||
count=1
|
||||
}})
|
||||
local drop = base_util.drop(ppos, itemid, 1, 1.5)
|
||||
local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL))
|
||||
drop.rigidbody:set_vel(velocity)
|
||||
end)
|
||||
|
||||
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.1 KiB |
@ -2,7 +2,11 @@ function inventory_share_func(invid, slotid)
|
||||
local blockinv = hud.get_block_inventory()
|
||||
if blockinv ~= 0 then
|
||||
inventory.move(invid, slotid, blockinv)
|
||||
else
|
||||
elseif rules.get("allow-content-access") then
|
||||
inventory.set(invid, slotid, 0, 0)
|
||||
elseif slotid < 10 then
|
||||
inventory.move_range(invid, slotid, invid, 10)
|
||||
else
|
||||
inventory.move_range(invid, slotid, invid, 0, 9)
|
||||
end
|
||||
end
|
||||
|
||||
27
res/scripts/post_content.lua
Normal file
@ -0,0 +1,27 @@
|
||||
local user_props = file.read_combined_object("config/user-props.toml")
|
||||
local names = {}
|
||||
for name, _ in pairs(user_props) do
|
||||
table.insert(names, name)
|
||||
end
|
||||
-- remove undefined properties
|
||||
for id, blockprops in pairs(block.properties) do
|
||||
for propname, value in pairs(blockprops) do
|
||||
if propname:find(':') and not table.has(names, propname) then
|
||||
print("erase property", propname)
|
||||
blockprops[propname] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function make_read_only(t)
|
||||
setmetatable(t, {
|
||||
__newindex = function()
|
||||
error("table is read-only")
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
make_read_only(block.properties)
|
||||
for k,v in pairs(block.properties) do
|
||||
make_read_only(v)
|
||||
end
|
||||
@ -16,8 +16,11 @@ void main() {
|
||||
vec4 tex_color = texture(u_texture0, a_texCoord);
|
||||
float depth = (a_distance/256.0);
|
||||
float alpha = a_color.a * tex_color.a;
|
||||
if (u_alphaClip && alpha < 0.9f)
|
||||
discard;
|
||||
if (u_alphaClip) {
|
||||
if (alpha < 0.2f)
|
||||
discard;
|
||||
alpha = 1.0;
|
||||
}
|
||||
f_color = mix(a_color * tex_color, vec4(fogColor,1.0),
|
||||
min(1.0, pow(depth*u_fogFactor, u_fogCurve)));
|
||||
f_color.a = alpha;
|
||||
|
||||
@ -39,8 +39,8 @@ SOFTWARE.
|
||||
#define ABSORPTION_FALLOFF 4e3 /* how much the absorption decreases the further away it gets from the maximum height */
|
||||
// and the steps (more looks better, but is slower)
|
||||
// the primary step has the most effect on looks
|
||||
#define PRIMARY_STEPS 12
|
||||
#define LIGHT_STEPS 4
|
||||
#define PRIMARY_STEPS 6
|
||||
#define LIGHT_STEPS 2
|
||||
|
||||
vec3 calculate_scattering(
|
||||
vec3 start, // the start of the ray (the camera position)
|
||||
|
||||
@ -191,6 +191,7 @@ void ContentLoader::loadBlock(
|
||||
Block& def, const std::string& name, const fs::path& file
|
||||
) {
|
||||
auto root = files::read_json(file);
|
||||
def.properties = root;
|
||||
|
||||
if (root.has("parent")) {
|
||||
const auto& parentName = root["parent"].asString();
|
||||
@ -360,6 +361,7 @@ void ContentLoader::loadItem(
|
||||
ItemDef& def, const std::string& name, const fs::path& file
|
||||
) {
|
||||
auto root = files::read_json(file);
|
||||
def.properties = root;
|
||||
|
||||
if (root.has("parent")) {
|
||||
const auto& parentName = root["parent"].asString();
|
||||
|
||||
@ -25,7 +25,7 @@ GLTexture::GLTexture(const ubyte* data, uint width, uint height, ImageFormat ima
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -242,18 +242,34 @@ void ImageData::extrude(int x, int y, int w, int h) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fixing black transparent pixels for Mip-Mapping
|
||||
void ImageData::fixAlphaColor() {
|
||||
// Fixing black transparent pixels for Mip-Mapping
|
||||
for (uint ly = 0; ly < height-1; ly++) {
|
||||
for (uint lx = 0; lx < width-1; lx++) {
|
||||
if (data[((ly) * width + lx) * 4 + 3]) {
|
||||
for (int c = 0; c < 3; c++) {
|
||||
int val = data[((ly) + + lx) * 4 + c];
|
||||
if (data[((ly) * width + lx + 1) * 4 + 3] == 0)
|
||||
data[((ly) * width + lx + 1) * 4 + c] = val;
|
||||
if (data[((ly + 1) * width + lx) * 4 + 3] == 0)
|
||||
data[((ly + 1) * width + lx) * 4 + c] = val;
|
||||
}
|
||||
int samples = 0;
|
||||
int sums[3] {};
|
||||
for (uint ly = 0; ly < height; ly++) {
|
||||
for (uint lx = 0; lx < width; lx++) {
|
||||
if (data[(ly * width + lx) * 4 + 3] == 0) {
|
||||
continue;
|
||||
}
|
||||
samples++;
|
||||
for (int c = 0; c < 3; c++) {
|
||||
sums[c] += data[(ly * width + lx) * 4 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (samples == 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
sums[i] /= samples;
|
||||
}
|
||||
for (uint ly = 0; ly < height; ly++) {
|
||||
for (uint lx = 0; lx < width; lx++) {
|
||||
if (data[(ly * width + lx) * 4 + 3] != 0) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
data[(ly * width + lx) * 4 + i] = sums[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
||||
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
||||
glm::vec3(1.01f),
|
||||
regions,
|
||||
glm::vec4(0),
|
||||
glm::vec4(1,1,1,0),
|
||||
false
|
||||
);
|
||||
break;
|
||||
@ -66,7 +66,7 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
||||
glm::vec3(wrapper.position) + aabb.center(),
|
||||
size * glm::vec3(1.01f),
|
||||
regions,
|
||||
glm::vec4(0),
|
||||
glm::vec4(1,1,1,0),
|
||||
false
|
||||
);
|
||||
break;
|
||||
|
||||
@ -196,8 +196,8 @@ void ChunksRenderer::drawChunks(
|
||||
shader.uniform1i("u_alphaClip", true);
|
||||
|
||||
// TODO: minimize draw calls number
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
auto chunk = chunks.getChunks()[indices[i].index];
|
||||
for (int i = indices.size()-1; i >= 0; i--) {
|
||||
auto& chunk = chunks.getChunks()[indices[i].index];
|
||||
auto mesh = retrieveChunk(indices[i].index, camera, shader, culling);
|
||||
|
||||
if (mesh) {
|
||||
|
||||
@ -114,7 +114,7 @@ model::Model ModelsGenerator::generate(
|
||||
} else if (blockDef.model == BlockModel::custom) {
|
||||
model = assets.require<model::Model>(blockDef.modelName);
|
||||
for (auto& mesh : model.meshes) {
|
||||
mesh.scale(glm::vec3(0.3f));
|
||||
mesh.scale(glm::vec3(0.2f));
|
||||
}
|
||||
return model;
|
||||
}
|
||||
@ -130,7 +130,7 @@ model::Model ModelsGenerator::generate(
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
mesh.scale(glm::vec3(0.3f));
|
||||
mesh.scale(glm::vec3(0.2f));
|
||||
}
|
||||
configure_textures(model, blockDef, assets);
|
||||
return model;
|
||||
|
||||
@ -247,12 +247,12 @@ void WorldRenderer::renderHands(
|
||||
|
||||
// prepare modified HUD camera
|
||||
Camera hudcam = camera;
|
||||
hudcam.far = 100.0f;
|
||||
hudcam.setFov(1.2f);
|
||||
hudcam.far = 10.0f;
|
||||
hudcam.setFov(0.9f);
|
||||
hudcam.position = {};
|
||||
|
||||
// configure model matrix
|
||||
const glm::vec3 itemOffset(0.08f, 0.035f, -0.1);
|
||||
const glm::vec3 itemOffset(0.06f, 0.035f, -0.1);
|
||||
|
||||
static glm::mat4 prevRotation(1.0f);
|
||||
|
||||
|
||||
@ -37,6 +37,12 @@ void Inventory::move(
|
||||
ItemStack& item, const ContentIndices* indices, size_t begin, size_t end
|
||||
) {
|
||||
end = std::min(slots.size(), end);
|
||||
for (size_t i = begin; i < end && !item.isEmpty(); i++) {
|
||||
ItemStack& slot = slots[i];
|
||||
if (!slot.isEmpty() && slot.accepts(item)) {
|
||||
slot.move(item, indices);
|
||||
}
|
||||
}
|
||||
for (size_t i = begin; i < end && !item.isEmpty(); i++) {
|
||||
ItemStack& slot = slots[i];
|
||||
if (slot.accepts(item)) {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "data/dv.hpp"
|
||||
#include "typedefs.hpp"
|
||||
|
||||
struct item_funcs_set {
|
||||
@ -25,6 +26,8 @@ struct ItemDef {
|
||||
/// @brief Item name will shown in inventory
|
||||
std::string caption;
|
||||
|
||||
dv::value properties = nullptr;
|
||||
|
||||
itemcount_t stackSize = 64;
|
||||
bool generated = false;
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
|
||||
@ -197,7 +197,7 @@ PlayerController::PlayerController(
|
||||
player(level->players->get(0)),
|
||||
camControl(player, settings.camera),
|
||||
blocksController(blocksController),
|
||||
playerTickClock(20, 3) {
|
||||
playerTickClock(60, 1) {
|
||||
}
|
||||
|
||||
void PlayerController::onFootstep(const Hitbox& hitbox) {
|
||||
@ -509,8 +509,7 @@ void PlayerController::updateInteraction(float delta) {
|
||||
bool longInteraction = interactionTimer <= 0 || xkey;
|
||||
bool lclick = Events::jactive(BIND_PLAYER_DESTROY) ||
|
||||
(longInteraction && Events::active(BIND_PLAYER_DESTROY));
|
||||
bool lattack = Events::jactive(BIND_PLAYER_ATTACK) ||
|
||||
(longInteraction && Events::active(BIND_PLAYER_ATTACK));
|
||||
bool lattack = Events::jactive(BIND_PLAYER_ATTACK);
|
||||
bool rclick = Events::jactive(BIND_PLAYER_BUILD) ||
|
||||
(longInteraction && Events::active(BIND_PLAYER_BUILD));
|
||||
if (lclick || rclick) {
|
||||
|
||||
@ -334,7 +334,9 @@ static int p_set_interval(UINode* node, lua::State* L) {
|
||||
static int p_get_content_offset(UINode* node, lua::State* L) {
|
||||
return lua::pushvec(L, node->getContentOffset());
|
||||
}
|
||||
|
||||
static int p_get_id(UINode* node, lua::State* L) {
|
||||
return lua::pushstring(L, node->getId());
|
||||
}
|
||||
static int p_get_color(UINode* node, lua::State* L) {
|
||||
return lua::pushcolor(L, node->getColor());
|
||||
}
|
||||
@ -390,6 +392,7 @@ static int l_gui_getattr(lua::State* L) {
|
||||
std::string_view,
|
||||
std::function<int(UINode*, lua::State*)>>
|
||||
getters {
|
||||
{"id", p_get_id},
|
||||
{"color", p_get_color},
|
||||
{"hoverColor", p_get_hover_color},
|
||||
{"pressedColor", p_get_pressed_color},
|
||||
|
||||
@ -156,12 +156,32 @@ static int l_inventory_move(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_inventory_move_range(lua::State* L) {
|
||||
auto invAid = lua::tointeger(L, 1);
|
||||
auto slotAid = lua::tointeger(L, 2);
|
||||
auto invA = get_inventory(invAid, 1);
|
||||
validate_slotid(slotAid, invA.get());
|
||||
|
||||
auto invBid = lua::tointeger(L, 3);
|
||||
auto slotBegin = lua::isnoneornil(L, 4) ? -1 : lua::tointeger(L, 4);
|
||||
auto slotEnd = lua::isnoneornil(L, 5) ? -1 : lua::tointeger(L, 5) + 1;
|
||||
auto invB = get_inventory(invBid, 3);
|
||||
auto& slot = invA->getSlot(slotAid);
|
||||
if (slotBegin == -1) {
|
||||
invB->move(slot, content->getIndices());
|
||||
} else {
|
||||
invB->move(slot, content->getIndices(), slotBegin, slotEnd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg inventorylib[] = {
|
||||
{"get", lua::wrap<l_inventory_get>},
|
||||
{"set", lua::wrap<l_inventory_set>},
|
||||
{"size", lua::wrap<l_inventory_size>},
|
||||
{"add", lua::wrap<l_inventory_add>},
|
||||
{"move", lua::wrap<l_inventory_move>},
|
||||
{"move_range", lua::wrap<l_inventory_move_range>},
|
||||
{"get_block", lua::wrap<l_inventory_get_block>},
|
||||
{"bind_block", lua::wrap<l_inventory_bind_block>},
|
||||
{"unbind_block", lua::wrap<l_inventory_unbind_block>},
|
||||
|
||||
@ -156,10 +156,26 @@ void scripting::process_post_runnables() {
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static int push_properties_tables(
|
||||
lua::State* L, const ContentUnitIndices<T>& indices
|
||||
) {
|
||||
const auto units = indices.getDefs();
|
||||
size_t size = indices.count();
|
||||
lua::createtable(L, size, 0);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
lua::pushvalue(L, units[i]->properties);
|
||||
lua::rawseti(L, i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void scripting::on_content_load(Content* content) {
|
||||
scripting::content = content;
|
||||
scripting::indices = content->getIndices();
|
||||
|
||||
const auto& indices = *content->getIndices();
|
||||
|
||||
auto L = lua::get_main_state();
|
||||
if (lua::getglobal(L, "block")) {
|
||||
const auto& materials = content->getBlockMaterials();
|
||||
@ -169,8 +185,17 @@ void scripting::on_content_load(Content* content) {
|
||||
lua::setfield(L, name);
|
||||
}
|
||||
lua::setfield(L, "materials");
|
||||
|
||||
push_properties_tables(L, indices.blocks);
|
||||
lua::setfield(L, "properties");
|
||||
lua::pop(L);
|
||||
}
|
||||
if (lua::getglobal(L, "item")) {
|
||||
push_properties_tables(L, indices.blocks);
|
||||
lua::setfield(L, "properties");
|
||||
lua::pop(L);
|
||||
}
|
||||
load_script(fs::path("post_content.lua"), true);
|
||||
load_script(fs::path("stdcmd.lua"), true);
|
||||
}
|
||||
|
||||
|
||||
@ -120,6 +120,8 @@ public:
|
||||
/// @brief Textures set applied to block sides
|
||||
std::array<std::string, 6> textureFaces; // -x,x, -y,y, -z,z
|
||||
|
||||
dv::value properties = nullptr;
|
||||
|
||||
/// @brief id of used BlockMaterial, may specify non-existing material
|
||||
std::string material = DEFAULT_MATERIAL;
|
||||
|
||||
|
||||