Merge branch 'main' into curl

This commit is contained in:
MihailRis 2024-11-26 12:48:14 +03:00
commit e8b674ca65
73 changed files with 366 additions and 136 deletions

View File

@ -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
)
```

View File

@ -142,6 +142,8 @@ Element must be in direct sub-element of *inventory*.
- `sharefunc` - Lua event called on <btn>LMB</btn> + <btn>Shift</btn>. Inventory id and slot index passed as arguments.
- `updatefunc` - Lua event called on slot content update.Inventory id and slot index passed as arguments.
- `onrightclick` - Lua event called on <btn>RMB</btn> click. Inventory id and slot index passed as arguments.
- `taking` - the ability to take an item from a slot.
- `placing` - the ability to put an item in a slot.
## *slots-grid*
@ -154,4 +156,5 @@ Element must be in direct sub-element of *inventory*.
- `sharefunc` - Lua event called on <btn>LMB</btn> + <btn>Shift</btn>. Inventory id and slot index passed as arguments.
- `updatefunc` - Lua event called on slot content update.Inventory id and slot index passed as arguments.
- `onrightclick` - Lua event called on <btn>RMB</btn> click. Inventory id and slot index passed as arguments.
- `taking` - the ability to take an item from a slot.
- `placing` - the ability to put an item in a slot.

View File

@ -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
)
```

View File

@ -143,6 +143,8 @@
- `sharefunc` - lua событие вызываемое при использовании ЛКМ + Shift. Передается id инвентаря и индекс слота
- `updatefunc` - lua событие вызываемое при изменении содержимого слота
- `onrightclick` - lua событие вызываемое при использовании ПКМ. Передается id инвентаря и индекс слота
- `taking` - возможность взять предмет из слота.
- `placing` - возможность положить предмет в слот.
## Сетка слотов - *slots-grid*
@ -156,3 +158,5 @@
- `sharefunc` - lua событие вызываемое при использовании ЛКМ + Shift. Передается id инвентаря и индекс слота
- `updatefunc` - lua событие вызываемое при изменении содержимого слота
- `onrightclick` - lua событие вызываемое при использовании ПКМ. Передается id инвентаря и индекс слота
- `taking` - возможность взять предмет из слота.
- `placing` - возможность положить предмет в слот.

View File

@ -1,4 +1,4 @@
{
"texture": "bazalt",
"breakable": false
}
}

View File

@ -2,5 +2,6 @@
"texture": "blue_lamp",
"emission": [0, 0, 15],
"shadeless": true,
"material": "base:glass"
"material": "base:glass",
"base:durability": 0.3
}

View File

@ -1,3 +1,4 @@
{
"texture": "brick"
}
"texture": "brick",
"base:durability": 10.5
}

View File

@ -1,3 +1,4 @@
{
"texture": "coal_ore"
"texture": "coal_ore",
"base:durability": 16.0
}

View File

@ -1,5 +1,6 @@
{
"texture": "dirt",
"material": "base:ground",
"surface-replacement": "base:grass_block"
"surface-replacement": "base:grass_block",
"base:durability": 1.0
}

View File

@ -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
}

View File

@ -4,5 +4,6 @@
"draw-group": 2,
"light-passing": true,
"sky-light-passing": true,
"translucent": true
"translucent": true,
"base:durability": 0.36
}

View File

@ -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
}

View File

@ -7,5 +7,6 @@
"grass_top",
"grass_side",
"grass_side"
]
}
],
"base:durability": 1.3
}

View File

@ -2,5 +2,6 @@
"texture": "green_lamp",
"emission": [0, 15, 0],
"shadeless": true,
"material": "base:glass"
"material": "base:glass",
"base:durability": 0.3
}

View File

@ -3,5 +3,6 @@
"material": "base:glass",
"draw-group": 4,
"light-passing": true,
"translucent": true
"translucent": true,
"base:durability": 0.3
}

View File

@ -1,5 +1,6 @@
{
"texture": "lamp",
"emission": [15, 14, 13],
"shadeless": true
"shadeless": true,
"base:durability": 0.3
}

View File

@ -1,4 +1,5 @@
{
"texture": "leaves",
"material": "base:grass"
}
"material": "base:grass",
"base:durability": 0.7
}

View File

@ -8,5 +8,6 @@
"light-passing": true,
"sky-light-passing": true,
"shadeless": true,
"material": "base:glass"
"material": "base:glass",
"base:durability": 0.2
}

View File

@ -1,4 +1,5 @@
{
"texture": "metal",
"material": "base:metal"
"material": "base:metal",
"base:durability": 10.0
}

View File

@ -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
}

View File

@ -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
}

View File

@ -1,4 +1,5 @@
{
"texture": "planks",
"material": "base:wood"
}
"material": "base:wood",
"base:durability": 5.0
}

View File

@ -2,5 +2,6 @@
"texture": "red_lamp",
"emission": [15, 0, 0],
"shadeless": true,
"material": "base:glass"
"material": "base:glass",
"base:durability": 0.3
}

View File

@ -1,4 +1,5 @@
{
"texture": "rust",
"material": "base:metal"
"material": "base:metal",
"base:durability": 6.6
}

View File

@ -1,4 +1,5 @@
{
"texture": "sand",
"material": "base:sand"
}
"material": "base:sand",
"base:durability": 0.7
}

View File

@ -1,3 +1,4 @@
{
"texture": "stone"
}
"texture": "stone",
"base:durability": 12.0
}

View File

@ -31,5 +31,6 @@
"particles:smoke_0",
"particles:smoke_1"
]
}
},
"base:durability": 0.1
}

View File

@ -8,5 +8,6 @@
"wood",
"wood"
],
"rotation": "pipe"
}
"rotation": "pipe",
"base:durability": 6.0
}

View File

@ -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
}

View File

@ -0,0 +1 @@
"base:durability" = {}

View File

@ -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

View 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

View File

@ -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)

View File

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -84,13 +84,11 @@ events.on("core:open_traceback", function(traceback_b64)
framestr = framestr.."("..tostring(frame.name)..")"
end
local color = "#FFFFFF"
if frame.source:starts_with("core:") then
color = "#C0D0C5"
end
tb_list:add(gui.template("stack_frame", {
location=framestr,
color=color,
callback=callback
callback=callback,
enabled=file.exists(frame.source)
}))
end
tb_list.size = srcsize

View File

@ -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

View File

@ -1,3 +1,3 @@
<label hover-color="#A0A0FF" interactive="true" onclick="%{callback}" color="%{color}">
<label hover-color="#A0A0FF" interactive="true" onclick="%{callback}" color="%{color}" enabled="%{enabled}">
%{location}
</label>

View 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

View File

@ -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;

View File

@ -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)

View File

@ -185,8 +185,16 @@ assetload::postfunc assetload::layout(
return [=](auto assets) {
try {
auto cfg = std::dynamic_pointer_cast<LayoutCfg>(config);
size_t pos = name.find(':');
auto prefix = name.substr(0, pos);
assets->store(
UiDocument::read(cfg->env, name, file, "abs:" + file), name
UiDocument::read(
cfg->env,
name,
file,
prefix + ":layouts/" + name.substr(pos + 1) + ".xml"
),
name
);
} catch (const parsing_error& err) {
throw std::runtime_error(

View File

@ -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();

View File

@ -366,6 +366,7 @@ void Engine::loadContent() {
load_configs(pack.folder);
}
content = contentBuilder.build();
interpreter->reset();
scripting::on_content_load(content.get());
ContentLoader::loadScripts(*content);

View File

@ -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);
}

View File

@ -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];
}
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -112,7 +112,7 @@ SlotView::SlotView(
layout(std::move(layout))
{
setColor(glm::vec4(0, 0, 0, 0.2f));
setTooltipDelay(0.05f);
setTooltipDelay(0.0f);
}
void SlotView::draw(const DrawContext* pctx, Assets* assets) {
@ -135,7 +135,7 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
const int slotSize = InventoryView::SLOT_SIZE;
const ItemStack& stack = *bound;
glm::vec4 tint(1.0f);
glm::vec4 tint(1, 1, 1, isEnabled() ? 1 : 0.5f);
glm::vec2 pos = calcPos();
glm::vec4 color = getColor();
@ -208,11 +208,73 @@ bool SlotView::isHighlighted() const {
return highlighted;
}
void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) {
if (layout.taking && Events::pressed(keycode::LEFT_SHIFT)) {
if (layout.shareFunc) {
layout.shareFunc(layout.index, stack);
}
if (layout.updateFunc) {
layout.updateFunc(layout.index, stack);
}
return;
}
if (!layout.itemSource && stack.accepts(grabbed) && layout.placing) {
stack.move(grabbed, content->getIndices());
} else {
if (layout.itemSource) {
if (grabbed.isEmpty()) {
grabbed.set(stack);
} else {
grabbed.clear();
}
} else if (grabbed.isEmpty()) {
if (layout.taking) {
std::swap(grabbed, stack);
}
} else if (layout.taking && layout.placing) {
std::swap(grabbed, stack);
}
}
}
void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
if (layout.rightClick) {
layout.rightClick(inventoryid, stack);
if (layout.updateFunc) {
layout.updateFunc(layout.index, stack);
}
return;
}
if (layout.itemSource)
return;
if (grabbed.isEmpty()) {
if (!stack.isEmpty() && layout.taking) {
grabbed.set(stack);
int halfremain = stack.getCount() / 2;
grabbed.setCount(stack.getCount() - halfremain);
stack.setCount(halfremain);
}
return;
}
auto& stackDef = content->getIndices()->items.require(stack.getItemId());
if (!layout.placing) {
return;
}
if (stack.isEmpty()) {
stack.set(grabbed);
stack.setCount(1);
grabbed.setCount(grabbed.getCount() - 1);
} else if (stack.accepts(grabbed) && stack.getCount() < stackDef.stackSize) {
stack.setCount(stack.getCount() + 1);
grabbed.setCount(grabbed.getCount() - 1);
}
}
void SlotView::clicked(gui::GUI* gui, mousecode button) {
if (bound == nullptr)
return;
auto exchangeSlot = std::dynamic_pointer_cast<SlotView>(gui->get(EXCHANGE_SLOT_NAME));
auto exchangeSlot =
std::dynamic_pointer_cast<SlotView>(gui->get(EXCHANGE_SLOT_NAME));
if (exchangeSlot == nullptr) {
return;
}
@ -220,57 +282,9 @@ void SlotView::clicked(gui::GUI* gui, mousecode button) {
ItemStack& stack = *bound;
if (button == mousecode::BUTTON_1) {
if (Events::pressed(keycode::LEFT_SHIFT)) {
if (layout.shareFunc) {
layout.shareFunc(layout.index, stack);
}
if (layout.updateFunc) {
layout.updateFunc(layout.index, stack);
}
return;
}
if (!layout.itemSource && stack.accepts(grabbed)) {
stack.move(grabbed, content->getIndices());
} else {
if (layout.itemSource) {
if (grabbed.isEmpty()) {
grabbed.set(stack);
} else {
grabbed.clear();
}
} else {
std::swap(grabbed, stack);
}
}
performLeftClick(stack, grabbed);
} else if (button == mousecode::BUTTON_2) {
if (layout.rightClick) {
layout.rightClick(inventoryid, stack);
if (layout.updateFunc) {
layout.updateFunc(layout.index, stack);
}
return;
}
if (layout.itemSource)
return;
if (grabbed.isEmpty()) {
if (!stack.isEmpty()) {
grabbed.set(stack);
int halfremain = stack.getCount() / 2;
grabbed.setCount(stack.getCount() - halfremain);
stack.setCount(halfremain);
}
} else {
auto& stackDef =
content->getIndices()->items.require(stack.getItemId());
if (stack.isEmpty()) {
stack.set(grabbed);
stack.setCount(1);
grabbed.setCount(grabbed.getCount() - 1);
} else if (stack.accepts(grabbed) && stack.getCount() < stackDef.stackSize) {
stack.setCount(stack.getCount() + 1);
grabbed.setCount(grabbed.getCount() - 1);
}
}
performRightClick(stack, grabbed);
}
if (layout.updateFunc) {
layout.updateFunc(layout.index, stack);

View File

@ -34,6 +34,9 @@ namespace gui {
slotcallback rightClick;
int padding = 0;
bool taking = true;
bool placing = true;
SlotLayout(
int index,
glm::vec2 position,
@ -55,6 +58,9 @@ namespace gui {
std::wstring tooltip;
itemid_t prevItem = 0;
void performLeftClick(ItemStack& stack, ItemStack& grabbed);
void performRightClick(ItemStack& stack, ItemStack& grabbed);
public:
SlotView(SlotLayout layout);

View File

@ -483,6 +483,8 @@ static slotcallback readSlotFunc(InventoryView* view, UiXmlReader& reader, xml::
static void readSlot(InventoryView* view, UiXmlReader& reader, xml::xmlelement element) {
int index = element->attr("index", "0").asInt();
bool itemSource = element->attr("item-source", "false").asBool();
bool taking = element->attr("taking", "true").asBool();
bool placing = element->attr("placing", "true").asBool();
SlotLayout layout(index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
if (element->has("pos")) {
layout.position = element->attr("pos").asVec2();
@ -496,6 +498,8 @@ static void readSlot(InventoryView* view, UiXmlReader& reader, xml::xmlelement e
if (element->has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick");
}
layout.taking = taking;
layout.placing = placing;
auto slot = view->addSlot(layout);
reader.readUINode(reader, element, *slot);
view->add(slot);
@ -507,6 +511,8 @@ static void readSlotsGrid(InventoryView* view, UiXmlReader& reader, xml::xmlelem
int cols = element->attr("cols", "0").asInt();
int count = element->attr("count", "0").asInt();
const int slotSize = InventoryView::SLOT_SIZE;
bool taking = element->attr("taking", "true").asBool();
bool placing = element->attr("placing", "true").asBool();
int interval = element->attr("interval", "-1").asInt();
if (interval < 0) {
interval = InventoryView::SLOT_INTERVAL;
@ -537,6 +543,8 @@ static void readSlotsGrid(InventoryView* view, UiXmlReader& reader, xml::xmlelem
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick");
}
layout.padding = padding;
layout.taking = taking;
layout.placing = placing;
int idx = 0;
for (int row = 0; row < rows; row++) {

View File

@ -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)) {

View File

@ -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};

View File

@ -125,6 +125,10 @@ namespace cmd {
const std::unordered_map<std::string, Command>& getCommands() const {
return commands;
}
void clear() {
commands.clear();
}
};
class CommandsInterpreter {
@ -158,5 +162,10 @@ namespace cmd {
CommandsRepository* getRepository() const {
return repository.get();
}
void reset() {
repository->clear();
variables.clear();
}
};
}

View File

@ -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) {

View File

@ -19,7 +19,7 @@ static fs::path resolve_path(const std::string& path) {
static fs::path resolve_path_soft(const std::string& path) {
if (path.find(':') == std::string::npos) {
return path;
return fs::u8path("");
}
return engine->getPaths()->resolve(path, false);
}

View File

@ -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},

View File

@ -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>},

View File

@ -68,7 +68,6 @@ void scripting::initialize(Engine* engine) {
lua::initialize(*engine->getPaths());
load_script(fs::path("stdlib.lua"), true);
load_script(fs::path("stdcmd.lua"), true);
load_script(fs::path("classes.lua"), true);
}
@ -157,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();
@ -170,8 +185,18 @@ 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);
}
void scripting::on_world_load(LevelController* controller) {

View File

@ -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;