mirror of
https://github.com/Jacobwasbeast/LegacyWeaveLoader.git
synced 2026-05-22 13:44:31 +00:00
693 lines
21 KiB
C++
693 lines
21 KiB
C++
#include "NativeExports.h"
|
|
#include "IdRegistry.h"
|
|
#include "CreativeInventory.h"
|
|
#include "GameObjectFactory.h"
|
|
#include "FurnaceRecipeRegistry.h"
|
|
#include "GameHooks.h"
|
|
#include "CustomPickaxeRegistry.h"
|
|
#include "CustomToolMaterialRegistry.h"
|
|
#include "CustomBlockRegistry.h"
|
|
#include "CustomSlabRegistry.h"
|
|
#include "ManagedBlockRegistry.h"
|
|
#include "ModStrings.h"
|
|
#include "LogUtil.h"
|
|
#include <Windows.h>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
namespace
|
|
{
|
|
using LevelHasNeighborSignal_fn = bool (__fastcall *)(void* thisPtr, int x, int y, int z);
|
|
using LevelSetTileAndData_fn = bool (__fastcall *)(void* thisPtr, int x, int y, int z, int blockId, int data, int flags);
|
|
using LevelAddToTickNextTick_fn = void (__fastcall *)(void* thisPtr, int x, int y, int z, int blockId, int delay);
|
|
using LevelGetTile_fn = int (__fastcall *)(void* thisPtr, int x, int y, int z);
|
|
|
|
LevelHasNeighborSignal_fn s_levelHasNeighborSignal = nullptr;
|
|
LevelSetTileAndData_fn s_levelSetTileAndData = nullptr;
|
|
LevelAddToTickNextTick_fn s_levelAddToTickNextTick = nullptr;
|
|
LevelGetTile_fn s_levelGetTile = nullptr;
|
|
}
|
|
|
|
void NativeExports::SetLevelInteropSymbols(void* hasNeighborSignal, void* setTileAndData, void* addToTickNextTick, void* getTile)
|
|
{
|
|
s_levelHasNeighborSignal = reinterpret_cast<LevelHasNeighborSignal_fn>(hasNeighborSignal);
|
|
s_levelSetTileAndData = reinterpret_cast<LevelSetTileAndData_fn>(setTileAndData);
|
|
s_levelAddToTickNextTick = reinterpret_cast<LevelAddToTickNextTick_fn>(addToTickNextTick);
|
|
s_levelGetTile = reinterpret_cast<LevelGetTile_fn>(getTile);
|
|
}
|
|
|
|
static std::wstring Utf8ToWide(const char* utf8)
|
|
{
|
|
if (!utf8 || !utf8[0]) return std::wstring();
|
|
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, nullptr, 0);
|
|
if (len <= 0) return std::wstring();
|
|
std::wstring result(len - 1, 0);
|
|
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, &result[0], len);
|
|
return result;
|
|
}
|
|
|
|
static int ResolveRecipeId(const char* namespacedId, bool preferItem)
|
|
{
|
|
if (!namespacedId || !namespacedId[0]) return -1;
|
|
|
|
int itemId = IdRegistry::Instance().GetNumericId(IdRegistry::Type::Item, namespacedId);
|
|
int blockId = IdRegistry::Instance().GetNumericId(IdRegistry::Type::Block, namespacedId);
|
|
|
|
if (preferItem)
|
|
return (itemId >= 0) ? itemId : blockId;
|
|
|
|
return (blockId >= 0) ? blockId : itemId;
|
|
}
|
|
|
|
static bool PrepareBlockRegistration(
|
|
const char* namespacedId,
|
|
const char* iconName,
|
|
const char* displayName,
|
|
int* outId,
|
|
int* outDescId,
|
|
std::wstring* outIcon)
|
|
{
|
|
if (!namespacedId || !outId || !outDescId || !outIcon)
|
|
return false;
|
|
|
|
*outId = IdRegistry::Instance().Register(IdRegistry::Type::Block, namespacedId);
|
|
if (*outId < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed to allocate block ID for '%s'", namespacedId);
|
|
return false;
|
|
}
|
|
|
|
*outIcon = Utf8ToWide(iconName);
|
|
*outDescId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
*outDescId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(*outDescId, wName.c_str());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
|
|
int native_register_block(
|
|
const char* namespacedId,
|
|
int materialId,
|
|
float hardness,
|
|
float resistance,
|
|
int soundType,
|
|
const char* iconName,
|
|
float lightEmission,
|
|
int lightBlock,
|
|
const char* displayName,
|
|
int requiredHarvestLevel,
|
|
int requiredTool,
|
|
int acceptsRedstonePower)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = -1;
|
|
int descId = -1;
|
|
std::wstring wIcon;
|
|
if (!PrepareBlockRegistration(namespacedId, iconName, displayName, &id, &descId, &wIcon))
|
|
return -1;
|
|
|
|
LogUtil::Log("[WeaveLoader] Registered block '%s' -> ID %d (hardness=%.1f, resistance=%.1f)",
|
|
namespacedId, id, hardness, resistance);
|
|
|
|
if (!GameObjectFactory::CreateTile(id, materialId, hardness, resistance,
|
|
soundType, wIcon.empty() ? nullptr : wIcon.c_str(), lightEmission, lightBlock, descId))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create game Tile for block '%s' id=%d", namespacedId, id);
|
|
}
|
|
|
|
if (requiredHarvestLevel >= 0 || requiredTool != 0 || acceptsRedstonePower != 0)
|
|
{
|
|
CustomBlockRegistry::Register(id, requiredHarvestLevel, requiredTool, acceptsRedstonePower != 0);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_managed_block(
|
|
const char* namespacedId,
|
|
int materialId,
|
|
float hardness,
|
|
float resistance,
|
|
int soundType,
|
|
const char* iconName,
|
|
float lightEmission,
|
|
int lightBlock,
|
|
const char* displayName,
|
|
int requiredHarvestLevel,
|
|
int requiredTool,
|
|
int acceptsRedstonePower)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = -1;
|
|
int descId = -1;
|
|
std::wstring wIcon;
|
|
if (!PrepareBlockRegistration(namespacedId, iconName, displayName, &id, &descId, &wIcon))
|
|
return -1;
|
|
|
|
if (!GameObjectFactory::CreateManagedTile(id, materialId, hardness, resistance,
|
|
soundType, wIcon.empty() ? nullptr : wIcon.c_str(), lightEmission, lightBlock, descId))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create managed Tile for '%s' id=%d", namespacedId, id);
|
|
}
|
|
|
|
ManagedBlockRegistry::Register(id);
|
|
|
|
if (requiredHarvestLevel >= 0 || requiredTool != 0 || acceptsRedstonePower != 0)
|
|
{
|
|
CustomBlockRegistry::Register(id, requiredHarvestLevel, requiredTool, acceptsRedstonePower != 0);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_falling_block(
|
|
const char* namespacedId,
|
|
int materialId,
|
|
float hardness,
|
|
float resistance,
|
|
int soundType,
|
|
const char* iconName,
|
|
float lightEmission,
|
|
int lightBlock,
|
|
const char* displayName,
|
|
int requiredHarvestLevel,
|
|
int requiredTool,
|
|
int acceptsRedstonePower)
|
|
{
|
|
int id = -1;
|
|
int descId = -1;
|
|
std::wstring wIcon;
|
|
if (!PrepareBlockRegistration(namespacedId, iconName, displayName, &id, &descId, &wIcon))
|
|
return -1;
|
|
|
|
if (!GameObjectFactory::CreateFallingTile(id, materialId, hardness, resistance,
|
|
soundType, wIcon.empty() ? nullptr : wIcon.c_str(), lightEmission, lightBlock, descId))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create falling Tile for '%s' id=%d", namespacedId, id);
|
|
}
|
|
|
|
ManagedBlockRegistry::Register(id);
|
|
|
|
if (requiredHarvestLevel >= 0 || requiredTool != 0 || acceptsRedstonePower != 0)
|
|
CustomBlockRegistry::Register(id, requiredHarvestLevel, requiredTool, acceptsRedstonePower != 0);
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_slab_block(
|
|
const char* namespacedId,
|
|
int materialId,
|
|
float hardness,
|
|
float resistance,
|
|
int soundType,
|
|
const char* iconName,
|
|
float lightEmission,
|
|
int lightBlock,
|
|
const char* displayName,
|
|
int requiredHarvestLevel,
|
|
int requiredTool,
|
|
int acceptsRedstonePower,
|
|
int* outDoubleBlockNumericId)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int halfId = -1;
|
|
int descId = -1;
|
|
std::wstring wIcon;
|
|
if (!PrepareBlockRegistration(namespacedId, iconName, displayName, &halfId, &descId, &wIcon))
|
|
return -1;
|
|
|
|
std::string fullName = std::string(namespacedId) + "_double";
|
|
int fullId = IdRegistry::Instance().Register(IdRegistry::Type::Block, fullName.c_str());
|
|
if (fullId < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed to allocate double slab block ID for '%s'", namespacedId);
|
|
return -1;
|
|
}
|
|
|
|
if (outDoubleBlockNumericId)
|
|
*outDoubleBlockNumericId = fullId;
|
|
|
|
if (!GameObjectFactory::CreateSlabPair(halfId, fullId, materialId, hardness, resistance,
|
|
soundType, wIcon.empty() ? nullptr : wIcon.c_str(), lightEmission, lightBlock, descId))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create slab pair for '%s' half=%d full=%d", namespacedId, halfId, fullId);
|
|
}
|
|
|
|
if (requiredHarvestLevel >= 0 || requiredTool != 0 || acceptsRedstonePower != 0)
|
|
{
|
|
CustomBlockRegistry::Register(halfId, requiredHarvestLevel, requiredTool, acceptsRedstonePower != 0);
|
|
CustomBlockRegistry::Register(fullId, requiredHarvestLevel, requiredTool, acceptsRedstonePower != 0);
|
|
}
|
|
|
|
return halfId;
|
|
}
|
|
|
|
void native_configure_managed_block(int numericBlockId, int dropNumericBlockId, int cloneNumericBlockId)
|
|
{
|
|
if (numericBlockId < 0)
|
|
return;
|
|
ManagedBlockRegistry::Configure(numericBlockId, dropNumericBlockId, cloneNumericBlockId);
|
|
}
|
|
|
|
int native_register_item(
|
|
const char* namespacedId,
|
|
int maxStackSize,
|
|
int maxDamage,
|
|
const char* iconName,
|
|
const char* displayName)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Item, namespacedId);
|
|
if (id < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed to allocate item ID for '%s'", namespacedId);
|
|
return -1;
|
|
}
|
|
|
|
LogUtil::Log("[WeaveLoader] Registered item '%s' -> ID %d (stack=%d, durability=%d)",
|
|
namespacedId, id, maxStackSize, maxDamage);
|
|
|
|
std::wstring wIcon = Utf8ToWide(iconName);
|
|
|
|
int descId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
descId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descId, wName.c_str());
|
|
}
|
|
|
|
if (!GameObjectFactory::CreateItem(id, maxStackSize, maxDamage,
|
|
wIcon.empty() ? nullptr : wIcon.c_str(), descId))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create game Item for '%s' id=%d", namespacedId, id);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_pickaxe_item(
|
|
const char* namespacedId,
|
|
int tier,
|
|
int maxDamage,
|
|
const char* iconName,
|
|
const char* displayName)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Item, namespacedId);
|
|
if (id < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed to allocate pickaxe item ID for '%s'", namespacedId);
|
|
return -1;
|
|
}
|
|
|
|
LogUtil::Log("[WeaveLoader] Registered pickaxe item '%s' -> ID %d (tier=%d, durability=%d)",
|
|
namespacedId, id, tier, maxDamage);
|
|
|
|
std::wstring wIcon = Utf8ToWide(iconName);
|
|
|
|
int descId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
descId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descId, wName.c_str());
|
|
}
|
|
|
|
if (!GameObjectFactory::CreatePickaxeItem(id, tier, maxDamage,
|
|
wIcon.empty() ? nullptr : wIcon.c_str(), descId))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create native PickaxeItem for '%s' id=%d", namespacedId, id);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_shovel_item(
|
|
const char* namespacedId,
|
|
int tier,
|
|
int maxDamage,
|
|
const char* iconName,
|
|
const char* displayName)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Item, namespacedId);
|
|
if (id < 0) return -1;
|
|
|
|
std::wstring wIcon = Utf8ToWide(iconName);
|
|
int descId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
descId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descId, wName.c_str());
|
|
}
|
|
|
|
if (!GameObjectFactory::CreateShovelItem(id, tier, maxDamage, wIcon.empty() ? nullptr : wIcon.c_str(), descId))
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create native ShovelItem for '%s' id=%d", namespacedId, id);
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_hoe_item(
|
|
const char* namespacedId,
|
|
int tier,
|
|
int maxDamage,
|
|
const char* iconName,
|
|
const char* displayName)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Item, namespacedId);
|
|
if (id < 0) return -1;
|
|
|
|
std::wstring wIcon = Utf8ToWide(iconName);
|
|
int descId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
descId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descId, wName.c_str());
|
|
}
|
|
|
|
if (!GameObjectFactory::CreateHoeItem(id, tier, maxDamage, wIcon.empty() ? nullptr : wIcon.c_str(), descId))
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create native HoeItem for '%s' id=%d", namespacedId, id);
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_axe_item(
|
|
const char* namespacedId,
|
|
int tier,
|
|
int maxDamage,
|
|
const char* iconName,
|
|
const char* displayName)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Item, namespacedId);
|
|
if (id < 0) return -1;
|
|
|
|
std::wstring wIcon = Utf8ToWide(iconName);
|
|
int descId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
descId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descId, wName.c_str());
|
|
}
|
|
|
|
if (!GameObjectFactory::CreateAxeItem(id, tier, maxDamage, wIcon.empty() ? nullptr : wIcon.c_str(), descId))
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create native HatchetItem for '%s' id=%d", namespacedId, id);
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_register_sword_item(
|
|
const char* namespacedId,
|
|
int tier,
|
|
int maxDamage,
|
|
const char* iconName,
|
|
const char* displayName)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Item, namespacedId);
|
|
if (id < 0) return -1;
|
|
|
|
std::wstring wIcon = Utf8ToWide(iconName);
|
|
int descId = -1;
|
|
if (displayName && displayName[0])
|
|
{
|
|
descId = ModStrings::AllocateId();
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descId, wName.c_str());
|
|
}
|
|
|
|
if (!GameObjectFactory::CreateSwordItem(id, tier, maxDamage, wIcon.empty() ? nullptr : wIcon.c_str(), descId))
|
|
LogUtil::Log("[WeaveLoader] Warning: failed to create native WeaponItem for '%s' id=%d", namespacedId, id);
|
|
|
|
return id;
|
|
}
|
|
|
|
int native_configure_custom_pickaxe_item(
|
|
int numericItemId,
|
|
int harvestLevel,
|
|
float destroySpeed)
|
|
{
|
|
return native_configure_custom_tool_item(
|
|
numericItemId,
|
|
static_cast<int>(CustomToolMaterialRegistry::ToolKind::Pickaxe),
|
|
harvestLevel,
|
|
destroySpeed,
|
|
0.0f);
|
|
}
|
|
|
|
int native_configure_custom_tool_item(
|
|
int numericItemId,
|
|
int toolKind,
|
|
int harvestLevel,
|
|
float destroySpeed,
|
|
float attackDamage)
|
|
{
|
|
if (numericItemId < 0 || harvestLevel < 0 || destroySpeed <= 0.0f)
|
|
return 0;
|
|
|
|
const auto kind = static_cast<CustomToolMaterialRegistry::ToolKind>(toolKind);
|
|
CustomToolMaterialRegistry::Register(numericItemId, kind, harvestLevel, destroySpeed, attackDamage);
|
|
if (kind == CustomToolMaterialRegistry::ToolKind::Pickaxe)
|
|
{
|
|
CustomPickaxeRegistry::Register(numericItemId, harvestLevel, destroySpeed);
|
|
}
|
|
|
|
void* itemPtr = GameObjectFactory::FindItem(numericItemId);
|
|
if (itemPtr)
|
|
{
|
|
switch (kind)
|
|
{
|
|
case CustomToolMaterialRegistry::ToolKind::Pickaxe:
|
|
case CustomToolMaterialRegistry::ToolKind::Shovel:
|
|
case CustomToolMaterialRegistry::ToolKind::Axe:
|
|
if (destroySpeed > 0.0f)
|
|
*reinterpret_cast<float*>(static_cast<char*>(itemPtr) + 0xA0) = destroySpeed;
|
|
if (attackDamage > 0.0f)
|
|
*reinterpret_cast<float*>(static_cast<char*>(itemPtr) + 0xA4) = attackDamage;
|
|
break;
|
|
case CustomToolMaterialRegistry::ToolKind::Sword:
|
|
if (attackDamage > 0.0f)
|
|
*reinterpret_cast<float*>(static_cast<char*>(itemPtr) + 0x98) = attackDamage;
|
|
break;
|
|
case CustomToolMaterialRegistry::ToolKind::Hoe:
|
|
break;
|
|
}
|
|
}
|
|
|
|
LogUtil::Log("[WeaveLoader] Configured custom tool item id=%d (kind=%d harvest=%d speed=%.2f attack=%.2f)",
|
|
numericItemId, toolKind, harvestLevel, destroySpeed, attackDamage);
|
|
return 1;
|
|
}
|
|
|
|
int native_allocate_description_id()
|
|
{
|
|
return ModStrings::AllocateId();
|
|
}
|
|
|
|
void native_register_string(int descriptionId, const char* displayName)
|
|
{
|
|
if (!displayName) return;
|
|
std::wstring wName = Utf8ToWide(displayName);
|
|
ModStrings::Register(descriptionId, wName.c_str());
|
|
}
|
|
|
|
int native_register_entity(
|
|
const char* namespacedId,
|
|
float width,
|
|
float height,
|
|
int trackingRange)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
|
|
int id = IdRegistry::Instance().Register(IdRegistry::Type::Entity, namespacedId);
|
|
if (id < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed to allocate entity ID for '%s'", namespacedId);
|
|
return -1;
|
|
}
|
|
|
|
LogUtil::Log("[WeaveLoader] Registered entity '%s' -> ID %d (%.1fx%.1f)",
|
|
namespacedId, id, width, height);
|
|
|
|
return id;
|
|
}
|
|
|
|
void native_add_shaped_recipe(
|
|
const char* resultId,
|
|
int resultCount,
|
|
const char* pattern,
|
|
const char* ingredientIds)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Added shaped recipe: %dx %s", resultCount, resultId);
|
|
}
|
|
|
|
void native_add_furnace_recipe(
|
|
const char* inputId,
|
|
const char* outputId,
|
|
float xp)
|
|
{
|
|
int inputNumeric = ResolveRecipeId(inputId, false);
|
|
int outputNumeric = ResolveRecipeId(outputId, true);
|
|
|
|
if (inputNumeric < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed furnace recipe: unknown input '%s'", inputId ? inputId : "(null)");
|
|
return;
|
|
}
|
|
|
|
if (outputNumeric < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed furnace recipe: unknown output '%s'", outputId ? outputId : "(null)");
|
|
return;
|
|
}
|
|
|
|
if (!FurnaceRecipeRegistry::AddRecipe(inputNumeric, outputNumeric, xp))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Failed furnace recipe: %s -> %s (%.1f xp)", inputId, outputId, xp);
|
|
return;
|
|
}
|
|
|
|
LogUtil::Log("[WeaveLoader] Added furnace recipe: %s[%d] -> %s[%d] (%.1f xp)",
|
|
inputId, inputNumeric, outputId, outputNumeric, xp);
|
|
}
|
|
|
|
void native_log(const char* message, int level)
|
|
{
|
|
if (message)
|
|
LogUtil::Log("%s", message);
|
|
}
|
|
|
|
int native_get_block_id(const char* namespacedId)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
return IdRegistry::Instance().GetNumericId(IdRegistry::Type::Block, namespacedId);
|
|
}
|
|
|
|
int native_get_item_id(const char* namespacedId)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
return IdRegistry::Instance().GetNumericId(IdRegistry::Type::Item, namespacedId);
|
|
}
|
|
|
|
int native_get_entity_id(const char* namespacedId)
|
|
{
|
|
if (!namespacedId) return -1;
|
|
return IdRegistry::Instance().GetNumericId(IdRegistry::Type::Entity, namespacedId);
|
|
}
|
|
|
|
int native_consume_item_from_player(void* playerPtr, int numericItemId, int count)
|
|
{
|
|
if (numericItemId < 0 || count <= 0)
|
|
return 0;
|
|
return GameHooks::ConsumePlayerResource(playerPtr, numericItemId, count) ? 1 : 0;
|
|
}
|
|
|
|
int native_damage_item_instance(void* itemInstancePtr, int amount, void* ownerSharedPtr)
|
|
{
|
|
if (amount <= 0)
|
|
return 0;
|
|
return GameHooks::DamageItemInstance(itemInstancePtr, amount, ownerSharedPtr) ? 1 : 0;
|
|
}
|
|
|
|
int native_spawn_entity_from_player_look(void* playerPtr, void* playerSharedPtr, int numericEntityId, double speed, double spawnForward, double spawnUp)
|
|
{
|
|
if (numericEntityId < 0)
|
|
return 0;
|
|
return GameHooks::SummonEntityFromPlayerLook(playerPtr, playerSharedPtr, numericEntityId, speed, spawnForward, spawnUp) ? 1 : 0;
|
|
}
|
|
|
|
int native_summon_entity_by_id(int numericEntityId, double x, double y, double z)
|
|
{
|
|
if (!GameHooks::SummonEntityByNumericId(numericEntityId, x, y, z))
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Summon failed: entity=%d at (%.2f, %.2f, %.2f)",
|
|
numericEntityId, x, y, z);
|
|
return 0;
|
|
}
|
|
|
|
LogUtil::Log("[WeaveLoader] Summoned entity=%d at (%.2f, %.2f, %.2f)",
|
|
numericEntityId, x, y, z);
|
|
return 1;
|
|
}
|
|
|
|
int native_level_has_neighbor_signal(void* levelPtr, int x, int y, int z)
|
|
{
|
|
return (levelPtr && s_levelHasNeighborSignal && s_levelHasNeighborSignal(levelPtr, x, y, z)) ? 1 : 0;
|
|
}
|
|
|
|
int native_level_set_tile(void* levelPtr, int x, int y, int z, int blockId, int data, int flags)
|
|
{
|
|
return (levelPtr && s_levelSetTileAndData && s_levelSetTileAndData(levelPtr, x, y, z, blockId, data, flags)) ? 1 : 0;
|
|
}
|
|
|
|
int native_level_schedule_tick(void* levelPtr, int x, int y, int z, int blockId, int delay)
|
|
{
|
|
if (!levelPtr)
|
|
return 0;
|
|
if (ManagedBlockRegistry::IsManaged(blockId))
|
|
{
|
|
GameHooks::EnqueueManagedBlockTick(levelPtr, x, y, z, blockId, delay);
|
|
return 1;
|
|
}
|
|
if (!s_levelAddToTickNextTick)
|
|
return 0;
|
|
s_levelAddToTickNextTick(levelPtr, x, y, z, blockId, delay);
|
|
return 1;
|
|
}
|
|
|
|
int native_level_get_tile(void* levelPtr, int x, int y, int z)
|
|
{
|
|
if (!levelPtr || !s_levelGetTile)
|
|
return -1;
|
|
return s_levelGetTile(levelPtr, x, y, z);
|
|
}
|
|
|
|
int native_summon_entity(const char* namespacedId, double x, double y, double z)
|
|
{
|
|
if (!namespacedId || !namespacedId[0])
|
|
return 0;
|
|
|
|
const int entityNumericId =
|
|
IdRegistry::Instance().GetNumericId(IdRegistry::Type::Entity, namespacedId);
|
|
if (entityNumericId < 0)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Summon failed: unknown entity id '%s'", namespacedId);
|
|
return 0;
|
|
}
|
|
|
|
return native_summon_entity_by_id(entityNumericId, x, y, z);
|
|
}
|
|
|
|
void native_subscribe_event(const char* eventName, void* managedFnPtr)
|
|
{
|
|
LogUtil::Log("[WeaveLoader] Event subscription: %s", eventName ? eventName : "(null)");
|
|
}
|
|
|
|
void native_add_to_creative(int numericId, int count, int auxValue, int groupIndex)
|
|
{
|
|
CreativeInventory::AddPending(numericId, count, auxValue, groupIndex);
|
|
}
|
|
|
|
} // extern "C"
|