Peake_Dad avatar

Minecraft - Hive Engine - Beta

strangedad

Published: 15 Mar 2026 β€Ί Updated: 15 Mar 2026Minecraft - Hive Engine - Beta

Minecraft - Hive Engine - Beta

Been working on making MineCraft and Hive, or mashing them together at least.

alt

It's a new upgraded version, trying to iron out the bugs. Also trying to figure out how to code in a stationary NPC that I don't have to cage in.

Taking all help if its given.

main.lua



-- main.lua

local g_Plugin = nil
local g_Config =
{
HiveEngineRpc = "https://api.hive-engine.com/rpc/contracts",
BridgeUrl = "http://127.0.0.1:8787",
BridgeAuthToken = "",
PaymentAccount = "",
BankEnabled = false,
BankX = 0,
BankY = 0,
BankZ = 0,
Debug = false,
BankName = "PeakeCoin Bank",
BankerName = "Banker",
DefaultSymbol = "PEAK",
BankSignsEnabled = true,
BankSignSymbols = "PEAK",
BankSignUpdateSeconds = 30,
}
local g_Accounts = {}
local g_Bridges = {}
local g_Ledger = {}
local g_Bank =
{
WorldName = "",
AtmX = 0,
AtmY = 0,
AtmZ = 0,
AtmBaseY = 0,
BankerId = nil,
Placed = false,
SignsPlaced = false,
LastPriceUpdate = 0,
Signs = {},
}
local g_TickCounter = 0

local CONFIG_FILE = nil

local function SetBlockAt(a_World, a_X, a_Y, a_Z, a_BlockType, a_BlockMeta)
local meta = a_BlockMeta or 0
local ok = pcall(function()
if (Vector3i ~= nil) then
a_World:SetBlock(Vector3i(a_X, a_Y, a_Z), a_BlockType, meta)
else
error("Vector3i not available")
end
end)
if not ok then
a_World:SetBlock(a_X, a_Y, a_Z, a_BlockType, meta)
end
end

local function ResolveConfigPath()
if (CONFIG_FILE and CONFIG_FILE ~= "") then
return CONFIG_FILE
end
local plugin = cPluginManager:Get():GetCurrentPlugin()
if (plugin) then
CONFIG_FILE = plugin:GetLocalFolder() .. "/HiveEngineTrade.ini"
else
CONFIG_FILE = "Plugins/HiveEngineTrade/HiveEngineTrade.ini"
end
return CONFIG_FILE
end

local function SendPlayerMessage(a_Player, a_Message)
if (a_Player and a_Player.SendMessage) then
a_Player:SendMessage(a_Message)
else
LOG(a_Message)
end
end

local function LoadConfig()
local configPath = ResolveConfigPath()
local ini = cIniFile()
if (not ini:ReadFile(configPath)) then
LOGINFO("HiveEngineTrade: creating default config at " .. configPath)
end

g_Config.HiveEngineRpc = ini:GetValueSet("HiveEngineTrade", "HiveEngineRpc", g_Config.HiveEngineRpc)
g_Config.BridgeUrl = ini:GetValueSet("HiveEngineTrade", "BridgeUrl", g_Config.BridgeUrl)
g_Config.BridgeAuthToken = ini:GetValueSet("HiveEngineTrade", "BridgeAuthToken", g_Config.BridgeAuthToken)
g_Config.PaymentAccount = ini:GetValueSet("HiveEngineTrade", "PaymentAccount", g_Config.PaymentAccount)
g_Config.BankEnabled = ini:GetValueSetB("HiveEngineTrade", "BankEnabled", g_Config.BankEnabled)
g_Config.BankX = ini:GetValueSetI("HiveEngineTrade", "BankX", g_Config.BankX)
g_Config.BankY = ini:GetValueSetI("HiveEngineTrade", "BankY", g_Config.BankY)
g_Config.BankZ = ini:GetValueSetI("HiveEngineTrade", "BankZ", g_Config.BankZ)
g_Config.Debug = ini:GetValueSetB("HiveEngineTrade", "Debug", g_Config.Debug)
g_Config.BankName = ini:GetValueSet("HiveEngineTrade", "BankName", g_Config.BankName)
g_Config.BankerName = ini:GetValueSet("HiveEngineTrade", "BankerName", g_Config.BankerName)
g_Config.DefaultSymbol = ini:GetValueSet("HiveEngineTrade", "DefaultSymbol", g_Config.DefaultSymbol)
g_Config.BankSignsEnabled = ini:GetValueSetB("HiveEngineTrade", "BankSignsEnabled", g_Config.BankSignsEnabled)
g_Config.BankSignSymbols = ini:GetValueSet("HiveEngineTrade", "BankSignSymbols", g_Config.BankSignSymbols)
g_Config.BankSignUpdateSeconds = ini:GetValueSetI("HiveEngineTrade", "BankSignUpdateSeconds", g_Config.BankSignUpdateSeconds)

g_Accounts = {}
local keyId = ini:FindKey("Accounts")
if (keyId ~= cIniFile.noID) then
local numValues = ini:GetNumValues(keyId)
for idx = 0, numValues - 1 do
local valueName = ini:GetValueName(keyId, idx)
if (valueName ~= "__placeholder") then
local value = ini:GetValue("Accounts", valueName)
if (value ~= "") then
g_Accounts[valueName] = value
end
end
end
end

g_Ledger = {}
local ledgerKeyId = ini:FindKey("Ledger")
if (ledgerKeyId ~= cIniFile.noID) then
local numValues = ini:GetNumValues(ledgerKeyId)
for idx = 0, numValues - 1 do
local valueName = ini:GetValueName(ledgerKeyId, idx)
if (valueName ~= "__placeholder") then
local value = ini:GetValue("Ledger", valueName)
local playerName, symbol = valueName:match("^([^:]+):(.+)$")
local amount = tonumber(value or "0") or 0
if (playerName and symbol and amount ~= 0) then
g_Ledger[playerName] = g_Ledger[playerName] or {}
g_Ledger[playerName][symbol] = amount
end
end
end
end

ini:WriteFile(configPath)

g_Bridges = {}
local bridgeKeyId = ini:FindKey("Bridges")
if (bridgeKeyId ~= cIniFile.noID) then
local numValues = ini:GetNumValues(bridgeKeyId)
for idx = 0, numValues - 1 do
local valueName = ini:GetValueName(bridgeKeyId, idx)
if (valueName ~= "__placeholder") then
local value = ini:GetValue("Bridges", valueName)
if (value ~= "") then
g_Bridges[valueName] = value
end
end
end
end
end

local function SaveAccount(a_PlayerName, a_HiveAccount)
local ini = cIniFile()
ini:ReadFile(ResolveConfigPath())
ini:SetValue("Accounts", a_PlayerName, a_HiveAccount)
ini:WriteFile(ResolveConfigPath())
g_Accounts[a_PlayerName] = a_HiveAccount
end

local function SaveBridge(a_PlayerName, a_BridgeUrl)
local ini = cIniFile()
ini:ReadFile(ResolveConfigPath())
if (a_BridgeUrl == nil or a_BridgeUrl == "") then
ini:DeleteValue("Bridges", a_PlayerName)
g_Bridges[a_PlayerName] = nil
else
ini:SetValue("Bridges", a_PlayerName, a_BridgeUrl)
g_Bridges[a_PlayerName] = a_BridgeUrl
end
ini:WriteFile(ResolveConfigPath())
end

local function GetLinkedAccount(a_PlayerName)
return g_Accounts[a_PlayerName]
end

local function GetBridgeUrlForPlayer(a_Player)
if (not a_Player) then
return g_Config.BridgeUrl
end
local name = a_Player:GetName()
return g_Bridges[name] or g_Config.BridgeUrl
end

local function HasAdminPermission(a_Player)
if (not a_Player) then
return true
end
if (a_Player.HasPermission) then
return a_Player:HasPermission("hive.admin")
end
return false
end

local function GetLedgerBalance(a_PlayerName, a_Symbol)
local perPlayer = g_Ledger[a_PlayerName]
if (not perPlayer) then
return 0
end
return perPlayer[a_Symbol] or 0
end

local function SetLedgerBalance(a_PlayerName, a_Symbol, a_Amount)
local amount = tonumber(a_Amount) or 0
if (amount == 0) then
if (g_Ledger[a_PlayerName]) then
g_Ledger[a_PlayerName][a_Symbol] = nil
end
else
g_Ledger[a_PlayerName] = g_Ledger[a_PlayerName] or {}
g_Ledger[a_PlayerName][a_Symbol] = amount
end

local ini = cIniFile()
ini:ReadFile(ResolveConfigPath())
local key = a_PlayerName .. ":" .. a_Symbol
if (amount == 0) then
ini:DeleteValue("Ledger", key)
else
ini:SetValue("Ledger", key, tostring(amount))
end
ini:WriteFile(ResolveConfigPath())

return amount
end

local function AddLedgerBalance(a_PlayerName, a_Symbol, a_Delta)
local delta = tonumber(a_Delta)
if (not delta) then
return nil, "Invalid amount"
end
local current = GetLedgerBalance(a_PlayerName, a_Symbol)
local nextAmount = current + delta
if (nextAmount < 0) then
return nil, "Insufficient balance"
end
return SetLedgerBalance(a_PlayerName, a_Symbol, nextAmount)
end

local function HttpPostJson(a_Url, a_Table, a_Callback, a_Headers)
local body, err = cJson:Serialize(a_Table)
if (not body) then
a_Callback(false, "JSON serialize failed: " .. (err or ""))
return
end

local headers = a_Headers or {}
headers["Content-Type"] = "application/json"

local ok, msg = cUrlClient:Post(a_Url,
function(a_Body, a_Data)
if (not a_Body) then
a_Callback(false, a_Data or "")
return
end
a_Callback(true, a_Body, a_Data)
end,
headers,
body
)

if (not ok) then
a_Callback(false, msg or "")
end
end

local function HeRpc(a_Method, a_Params, a_Callback)
HttpPostJson(
g_Config.HiveEngineRpc,
{ jsonrpc = "2.0", id = 1, method = a_Method, params = a_Params },
a_Callback
)
end

local function RequireLinkedAccount(a_Player)
local name = a_Player:GetName()
local account = GetLinkedAccount(name)
if (not account or account == "") then
SendPlayerMessage(a_Player, "No Hive account linked. Use /hive link ")
return nil
end
return account
end

function Initialize(a_Plugin)
g_Plugin = a_Plugin
g_Plugin:SetName("HiveEngineTrade")
g_Plugin:SetVersion(1)

LoadConfig()
LOG("HiveEngineTrade: ConfigPath=" .. ResolveConfigPath())
LOG("HiveEngineTrade: Config BankEnabled=" .. tostring(g_Config.BankEnabled) ..
" BankXYZ=" .. g_Config.BankX .. "," .. g_Config.BankY .. "," .. g_Config.BankZ ..
" Debug=" .. tostring(g_Config.Debug))

cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity)
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_BREAKING_BLOCK, OnPlayerBreakingBlock)
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick)

if (g_Config.BankEnabled) then
SetupBank()
end

LOG("Initialized " .. g_Plugin:GetName() .. " v." .. g_Plugin:GetVersion())
return true
end

local function IsBankerEntity(a_Entity)
if (not a_Entity) then
return false
end
if (g_Bank.BankerId and a_Entity:GetUniqueID() == g_Bank.BankerId) then
return true
end
if (a_Entity:GetClass() ~= "cVillager") then
return false
end
if (g_Bank.AtmX == 0 and g_Bank.AtmZ == 0) then
return false
end
local pos = a_Entity:GetPosition()
local dx = math.abs(pos.x - g_Bank.AtmX)
local dy = math.abs(pos.y - (g_Bank.AtmY or pos.y))
local dz = math.abs(pos.z - g_Bank.AtmZ)
return (dx <= 3) and (dy <= 3) and (dz <= 3)
end

local function EnsureBankerAt(a_World, a_X, a_Y, a_Z)
local found = nil
local searchBox = cBoundingBox(Vector3d(a_X, a_Y, a_Z), 4, 2)
a_World:ForEachEntityInBox(searchBox, function (a_Entity)
if (IsBankerEntity(a_Entity)) then
found = a_Entity
return true
end
return false
end)

if (found) then
g_Bank.BankerId = found:GetUniqueID()
return
end

local entityId = a_World:SpawnMob(a_X + 0.5, a_Y, a_Z + 0.5, mtVillager)
if (entityId == cEntity.INVALID_ID) then
LOGWARNING("HiveEngineTrade: failed to spawn banker villager")
return
end

a_World:DoWithEntityByID(entityId, function (a_Entity)
g_Bank.BankerId = a_Entity:GetUniqueID()
end)
end

local function ParseSymbolList(a_List)
local symbols = {}
for token in string.gmatch(a_List or "", "[^,%s]+") do
table.insert(symbols, string.upper(token))
end
if (#symbols == 0 and g_Config.DefaultSymbol ~= "") then
table.insert(symbols, string.upper(g_Config.DefaultSymbol))
end
return symbols
end

local function EnsureBankSigns(a_World)
if (g_Bank.SignsPlaced or (not g_Config.BankSignsEnabled)) then
return
end
local baseX = g_Bank.AtmX
local baseY = g_Bank.AtmY
local baseZ = g_Bank.AtmZ
local signBlock = 68 -- wall sign
local signMeta = 2 -- facing north (toward interior)
local symbols = ParseSymbolList(g_Config.BankSignSymbols)
local signY = baseY + 2
local signZ = baseZ + 2
local positions = {
{ baseX - 2, signY, signZ },
{ baseX - 1, signY, signZ },
{ baseX, signY, signZ },
{ baseX + 1, signY, signZ },
{ baseX + 2, signY, signZ },
}

g_Bank.Signs = {}
for idx, symbol in ipairs(symbols) do
local pos = positions[idx]
if (pos) then
local sx, sy, sz = pos[1], pos[2], pos[3]
SetBlockAt(a_World, sx, sy, sz, 0, 0)
SetBlockAt(a_World, sx, sy, sz, signBlock, signMeta)
a_World:SetSignLines(sx, sy, sz, "PRICE", symbol, "loading", "")
table.insert(g_Bank.Signs, { Symbol = symbol, X = sx, Y = sy, Z = sz })
end
end

g_Bank.SignsPlaced = true
if (g_Config.Debug) then
LOG("HiveEngineTrade: Bank signs placed count=" .. tostring(#g_Bank.Signs) .. " z=" .. tostring(signZ))
end
end

local function UpdateBankSigns()
if (not g_Config.BankSignsEnabled) then
return
end
if (g_Bank.WorldName == "" or (not g_Bank.SignsPlaced)) then
return
end
local now = os.time()
if ((now - g_Bank.LastPriceUpdate) < g_Config.BankSignUpdateSeconds) then
return
end
g_Bank.LastPriceUpdate = now

for _, sign in ipairs(g_Bank.Signs) do
HeRpc("findOne", {
contract = "market",
table = "metrics",
query = { symbol = sign.Symbol },
}, function(success, bodyOrErr)
local world = cRoot:Get():GetWorld(g_Bank.WorldName)
if (not world) then
return
end
if (not success) then
world:SetSignLines(sign.X, sign.Y, sign.Z, "PRICE", sign.Symbol, "n/a", "")
return
end
local result = cJson:Parse(bodyOrErr)
local lastPrice = "n/a"
local volume = ""
if (result and result.result) then
lastPrice = result.result.lastPrice or lastPrice
volume = result.result.volume or volume
end
local line4 = (volume ~= "") and ("vol " .. tostring(volume)) or ""
world:SetSignLines(sign.X, sign.Y, sign.Z, "PRICE", sign.Symbol, tostring(lastPrice), line4)
end)
end
end

local function EnsureBankPlatform(a_World, a_X, a_Y, a_Z)
-- Build a simple 7x7 stone-brick building with a plank roof.
-- a_Y is the desired ground level; we place the floor one block lower.
local baseY = a_Y - 1
-- Use numeric block IDs for compatibility:
-- 0 = air, 5 = planks, 98 = stone bricks
local floorBlock = 98
local wallBlock = 98
local roofBlock = 5
local roofMeta = 0  -- oak
local airBlock = 0
local size = 3
local wallHeight = 5
local barsBlock = 101 -- iron bars

-- Clear a 7x7x8 volume to remove old blocks
for dy = 0, 7 do
for dx = -size, size do
for dz = -size, size do
SetBlockAt(a_World, a_X + dx, baseY + dy, a_Z + dz, airBlock, 0)
end
end
end

-- Floor (7x7)
for dx = -size, size do
for dz = -size, size do
SetBlockAt(a_World, a_X + dx, baseY, a_Z + dz, floorBlock, 0)
end
end

-- Walls (height 5)
for dy = 1, wallHeight do
for dx = -size, size do
for dz = -size, size do
local isEdge = (dx == -size) or (dx == size) or (dz == -size) or (dz == size)
if (isEdge) then
-- Doorway at front center (z -size)
if not((dz == -size) and (dx == 0) and (dy <= 2)) then
SetBlockAt(a_World, a_X + dx, baseY + dy, a_Z + dz, wallBlock, 0)
end
end
end
end
end

-- Roof (7x7)
for dx = -size, size do
for dz = -size, size do
SetBlockAt(a_World, a_X + dx, baseY + wallHeight + 1, a_Z + dz, roofBlock, roofMeta)
end
end

-- Banker cage (3x3 iron bars) centered on the banker
local cageMinX = a_X - 1
local cageMaxX = a_X + 1
local cageMinZ = a_Z - 1
local cageMaxZ = a_Z + 1
for dy = 1, 3 do
for dx = cageMinX, cageMaxX do
for dz = cageMinZ, cageMaxZ do
local isEdge = (dx == cageMinX) or (dx == cageMaxX) or (dz == cageMinZ) or (dz == cageMaxZ)
if (isEdge) then
SetBlockAt(a_World, dx, baseY + dy, dz, barsBlock, 0)
else
SetBlockAt(a_World, dx, baseY + dy, dz, airBlock, 0)
end
end
end
end
-- Cage roof
for dx = cageMinX, cageMaxX do
for dz = cageMinZ, cageMaxZ do
SetBlockAt(a_World, dx, baseY + 4, dz, barsBlock, 0)
end
end
end

function SetupBank()
if (g_Bank.Placed) then
return
end
local world = cRoot:Get():GetDefaultWorld()
if (not world) then
LOGWARNING("HiveEngineTrade: default world not ready")
return
end
local spawnX = math.floor(world:GetSpawnX())
local spawnY = math.floor(world:GetSpawnY())
local spawnZ = math.floor(world:GetSpawnZ())

local useFixed = ((g_Config.BankX ~= 0) or (g_Config.BankY ~= 0) or (g_Config.BankZ ~= 0))
local atmX = useFixed and g_Config.BankX or (spawnX + 1)
local atmZ = useFixed and g_Config.BankZ or spawnZ

g_Bank.WorldName = world:GetName()
if (g_Config.Debug) then
LOG("HiveEngineTrade: SetupBank world=" .. g_Bank.WorldName .. " useFixed=" .. tostring(useFixed) .. " target=" .. atmX .. "," .. (useFixed and g_Config.BankY or spawnY) .. "," .. atmZ)
end

local chunkX = math.floor(atmX / 16)
local chunkZ = math.floor(atmZ / 16)

world:ChunkStay({{chunkX, chunkZ}}, nil, function ()
local groundY = spawnY
if (useFixed) then
groundY = g_Config.BankY
else
local isValid, height = world:TryGetHeight(atmX, atmZ)
if (isValid and height and (height > 0)) then
groundY = height
end
end
if (g_Config.Debug) then
LOG("HiveEngineTrade: Chunk ready; placing bank at " .. atmX .. "," .. groundY .. "," .. atmZ)
end
g_Bank.AtmX = atmX
g_Bank.AtmZ = atmZ
g_Bank.AtmY = groundY
g_Bank.AtmBaseY = groundY - 1
EnsureBankPlatform(world, atmX, groundY, atmZ)
world:SetSpawn(atmX, groundY, atmZ)
EnsureBankerAt(world, atmX, groundY, atmZ)
EnsureBankSigns(world)
g_Bank.Placed = true
if (g_Config.Debug) then
LOG("HiveEngineTrade: Bank placed and spawn set")
end
end)
end

function OnTick(a_TimeDelta)
if (g_Config.BankEnabled and (not g_Bank.Placed)) then
SetupBank()
end
if (g_Config.BankEnabled and g_Bank.Placed and (not g_Bank.SignsPlaced)) then
local world = cRoot:Get():GetWorld(g_Bank.WorldName)
if (world) then
EnsureBankSigns(world)
end
end
UpdateBankSigns()
g_TickCounter = g_TickCounter + 1
if (g_Config.Debug and (g_TickCounter == 20)) then
LOG("HiveEngineTrade: Tick running, bankPlaced=" .. tostring(g_Bank.Placed))
end
end

function HandleHiveBankSigns(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local world = a_Player:GetWorld()
g_Bank.SignsPlaced = false
EnsureBankSigns(world)
SendPlayerMessage(a_Player, "Bank signs refreshed")
return true
end

function HandleHiveLink(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local hiveAccount = a_Split[2]
if (not hiveAccount or hiveAccount == "") then
return true, "Usage: /hive link "
end
SaveAccount(a_Player:GetName(), hiveAccount)
SendPlayerMessage(a_Player, "Linked Hive account: " .. hiveAccount)
return true
end

function HandleHiveBridge(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local url = a_Split[2]
if (not url or url == "") then
return true, "Usage: /hive bridge "
end
if (string.lower(url) == "clear") then
SaveBridge(a_Player:GetName(), "")
SendPlayerMessage(a_Player, "Cleared personal bridge URL; using server default")
return true
end
SaveBridge(a_Player:GetName(), url)
SendPlayerMessage(a_Player, "Set personal bridge URL: " .. url)
return true
end

function HandleHiveVault(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local name = a_Player:GetName()
local perPlayer = g_Ledger[name]
if (not perPlayer) then
SendPlayerMessage(a_Player, "Vault balance: empty")
return true
end
SendPlayerMessage(a_Player, "Vault balances for " .. name .. ":")
local count = 0
for symbol, amount in pairs(perPlayer) do
SendPlayerMessage(a_Player, "- " .. symbol .. " = " .. tostring(amount))
count = count + 1
end
if (count == 0) then
SendPlayerMessage(a_Player, "Vault balance: empty")
end
return true
end

function HandleHiveVaultAdd(a_Split, a_Player)
if (not HasAdminPermission(a_Player)) then
return true, "No permission"
end
local playerName = a_Split[2]
local symbol = a_Split[3]
local amount = a_Split[4]
if (not playerName or not symbol or not amount) then
return true, "Usage: /hive vaultadd   "
end
local newBalance, err = AddLedgerBalance(playerName, symbol, amount)
if (not newBalance) then
SendPlayerMessage(a_Player, "Vault add failed: " .. (err or ""))
return true
end
SendPlayerMessage(a_Player, "Vault updated: " .. playerName .. " " .. symbol .. " = " .. tostring(newBalance))
return true
end

function HandleHiveVaultTake(a_Split, a_Player)
if (not HasAdminPermission(a_Player)) then
return true, "No permission"
end
local playerName = a_Split[2]
local symbol = a_Split[3]
local amount = a_Split[4]
if (not playerName or not symbol or not amount) then
return true, "Usage: /hive vaulttake   "
end
local delta = -math.abs(tonumber(amount) or 0)
if (delta == 0) then
return true, "Invalid amount"
end
local newBalance, err = AddLedgerBalance(playerName, symbol, delta)
if (not newBalance) then
SendPlayerMessage(a_Player, "Vault take failed: " .. (err or ""))
return true
end
SendPlayerMessage(a_Player, "Vault updated: " .. playerName .. " " .. symbol .. " = " .. tostring(newBalance))
return true
end

function HandleHiveDeposit(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local symbol = a_Split[2]
local amount = a_Split[3]
if (not symbol or not amount) then
return true, "Usage: /hive deposit  "
end
local amountNum = tonumber(amount)
if (not amountNum or amountNum <= 0) then
return true, "Invalid amount"
end
local hiveAccount = RequireLinkedAccount(a_Player)
if (not hiveAccount) then
return true
end

local headers = {}
if (g_Config.BridgeAuthToken ~= "") then
headers["Authorization"] = "Bearer " .. g_Config.BridgeAuthToken
end

local payload = {
action = "deposit",
account = hiveAccount,
player = a_Player:GetName(),
symbol = symbol,
amount = tostring(amountNum),
}

local bridgeUrl = GetBridgeUrlForPlayer(a_Player)
HttpPostJson(bridgeUrl .. "/deposit", payload, function(success, bodyOrErr)
if (not success) then
SendPlayerMessage(a_Player, "Deposit request failed: " .. (bodyOrErr or ""))
return
end
local result, err = cJson:Parse(bodyOrErr)
if (not result) then
SendPlayerMessage(a_Player, "Bridge response invalid: " .. (err or ""))
return
end
if (result.ok) then
local instructions = result.instructions or result.memo or result.address or "Deposit request created"
SendPlayerMessage(a_Player, "Deposit instructions: " .. instructions)
SendPlayerMessage(a_Player, "After deposit confirms, an admin will credit your vault balance.")
else
SendPlayerMessage(a_Player, "Deposit rejected: " .. (result.error or ""))
end
end, headers)

return true
end

function HandleHiveWithdraw(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local symbol = a_Split[2]
local amount = a_Split[3]
if (not symbol or not amount) then
return true, "Usage: /hive withdraw  "
end
local amountNum = tonumber(amount)
if (not amountNum or amountNum <= 0) then
return true, "Invalid amount"
end
local name = a_Player:GetName()
local balance = GetLedgerBalance(name, symbol)
if (balance < amountNum) then
SendPlayerMessage(a_Player, "Insufficient vault balance: " .. tostring(balance))
return true
end
local hiveAccount = RequireLinkedAccount(a_Player)
if (not hiveAccount) then
return true
end

local headers = {}
if (g_Config.BridgeAuthToken ~= "") then
headers["Authorization"] = "Bearer " .. g_Config.BridgeAuthToken
end

local payload = {
action = "withdraw",
account = hiveAccount,
player = a_Player:GetName(),
symbol = symbol,
amount = tostring(amountNum),
}

local bridgeUrl = GetBridgeUrlForPlayer(a_Player)
HttpPostJson(bridgeUrl .. "/withdraw", payload, function(success, bodyOrErr)
if (not success) then
SendPlayerMessage(a_Player, "Withdraw failed: " .. (bodyOrErr or ""))
return
end
local result, err = cJson:Parse(bodyOrErr)
if (not result) then
SendPlayerMessage(a_Player, "Bridge response invalid: " .. (err or ""))
return
end
if (result.ok) then
if (result.txid or result.processed) then
local newBalance = AddLedgerBalance(name, symbol, -amountNum)
SendPlayerMessage(a_Player, "Withdraw submitted: " .. (result.txid or "") .. ". New vault balance: " .. tostring(newBalance))
elseif (result.pending) then
SendPlayerMessage(a_Player, "Withdraw queued: " .. (result.requestId or ""))
SendPlayerMessage(a_Player, "An admin will finalize this withdrawal.")
else
SendPlayerMessage(a_Player, "Withdraw accepted.")
end
else
SendPlayerMessage(a_Player, "Withdraw rejected: " .. (result.error or ""))
end
end, headers)

return true
end

function HandleHiveBalance(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local symbol = a_Split[2]
if (not symbol or symbol == "") then
return true, "Usage: /hive balance  [hiveAccount]"
end

local hiveAccount = a_Split[3]
if (not hiveAccount or hiveAccount == "") then
hiveAccount = RequireLinkedAccount(a_Player)
if (not hiveAccount) then
return true
end
end

HeRpc("findOne", {
contract = "tokens",
table = "balances",
query = { account = hiveAccount, symbol = symbol },
}, function(success, bodyOrErr)
if (not success) then
SendPlayerMessage(a_Player, "Balance lookup failed: " .. (bodyOrErr or ""))
return
end
local result, err = cJson:Parse(bodyOrErr)
if (not result) then
SendPlayerMessage(a_Player, "Invalid response: " .. (err or ""))
return
end
local balance = "0"
if (result.result and result.result.balance) then
balance = result.result.balance
end
SendPlayerMessage(a_Player, "Balance " .. hiveAccount .. " " .. symbol .. " = " .. balance)
end)

return true
end

function HandleHivePrice(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local symbol = a_Split[2]
if (not symbol or symbol == "") then
return true, "Usage: /hive price "
end

HeRpc("findOne", {
contract = "market",
table = "metrics",
query = { symbol = symbol },
}, function(success, bodyOrErr)
if (not success) then
SendPlayerMessage(a_Player, "Price lookup failed: " .. (bodyOrErr or ""))
return
end
local result, err = cJson:Parse(bodyOrErr)
if (not result) then
SendPlayerMessage(a_Player, "Invalid response: " .. (err or ""))
return
end
local lastPrice = "n/a"
local volume = "n/a"
if (result.result) then
lastPrice = result.result.lastPrice or lastPrice
volume = result.result.volume or volume
end
SendPlayerMessage(a_Player, "Market " .. symbol .. " lastPrice=" .. lastPrice .. " volume=" .. volume)
end)

return true
end

function HandleHiveSwap(a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end
local hiveAmount = a_Split[2]
local symbol = a_Split[3] or g_Config.DefaultSymbol
if (not hiveAmount) then
return true, "Usage: /hive swap  [symbol]"
end

local amountNum = tonumber(hiveAmount)
if (not amountNum or amountNum <= 0) then
return true, "Invalid hiveAmount"
end

local hiveAccount = RequireLinkedAccount(a_Player)
if (not hiveAccount) then
return true
end

HeRpc("findOne", {
contract = "market",
table = "metrics",
query = { symbol = symbol },
}, function(success, bodyOrErr)
if (not success) then
SendPlayerMessage(a_Player, "Swap lookup failed: " .. (bodyOrErr or ""))
return
end
local result, err = cJson:Parse(bodyOrErr)
if (not result) then
SendPlayerMessage(a_Player, "Invalid response: " .. (err or ""))
return
end
if (not result.result or not result.result.lastPrice) then
SendPlayerMessage(a_Player, "No market data for " .. symbol)
return
end
local price = tonumber(result.result.lastPrice)
if (not price or price <= 0) then
SendPlayerMessage(a_Player, "Invalid market price for " .. symbol)
return
end
local quantity = amountNum / price
local qtyStr = string.format("%.3f", quantity)
local priceStr = string.format("%.3f", price)

SendPlayerMessage(a_Player, "Submitting market swap at price " .. priceStr .. " for quantity " .. qtyStr)
local split = { a_Split[1], symbol, priceStr, qtyStr }
SubmitTrade("buy", split, a_Player)
end)

return true
end

local function SubmitTrade(a_Action, a_Split, a_Player)
if (not a_Player) then
return true, "This command must be run by a player"
end

local symbol = a_Split[2]
local price = a_Split[3]
local quantity = a_Split[4]
if (not symbol or not price or not quantity) then
return true, "Usage: /hive " .. a_Action .. "   "
end

local hiveAccount = RequireLinkedAccount(a_Player)
if (not hiveAccount) then
return true
end

local headers = {}
if (g_Config.BridgeAuthToken ~= "") then
headers["Authorization"] = "Bearer " .. g_Config.BridgeAuthToken
end

local payload = {
action = a_Action,
account = hiveAccount,
symbol = symbol,
price = price,
quantity = quantity,
}

local bridgeUrl = GetBridgeUrlForPlayer(a_Player)
HttpPostJson(bridgeUrl .. "/trade", payload, function(success, bodyOrErr)
if (not success) then
SendPlayerMessage(a_Player, "Trade failed: " .. (bodyOrErr or ""))
return
end
local result, err = cJson:Parse(bodyOrErr)
if (not result) then
SendPlayerMessage(a_Player, "Bridge response invalid: " .. (err or ""))
return
end
if (result.ok) then
SendPlayerMessage(a_Player, "Trade submitted: " .. (result.txid or ""))
else
SendPlayerMessage(a_Player, "Trade rejected: " .. (result.error or ""))
end
end, headers)

return true
end

function HandleHiveBuy(a_Split, a_Player)
return SubmitTrade("buy", a_Split, a_Player)
end

function HandleHiveSell(a_Split, a_Player)
return SubmitTrade("sell", a_Split, a_Player)
end

function OnPlayerRightClickingEntity(a_Player, a_Entity)
if (not IsBankerEntity(a_Entity)) then
return false
end

SendPlayerMessage(a_Player, g_Config.BankName .. " - Banker")
SendPlayerMessage(a_Player, "Use /hive vault, /hive deposit  , /hive withdraw  ")
SendPlayerMessage(a_Player, "Market: /hive price " .. g_Config.DefaultSymbol .. " and /hive swap  " .. g_Config.DefaultSymbol)
return true
end

function OnPlayerBreakingBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta)
if (g_Bank.WorldName == "") then
return false
end
local world = a_Player:GetWorld()
if (world:GetName() ~= g_Bank.WorldName) then
return false
end
local inFootprint =
(a_BlockX >= g_Bank.AtmX - 2) and (a_BlockX <= g_Bank.AtmX + 2) and
(a_BlockZ >= g_Bank.AtmZ - 2) and (a_BlockZ <= g_Bank.AtmZ + 2) and
(a_BlockY >= g_Bank.AtmBaseY) and (a_BlockY <= g_Bank.AtmBaseY + 4)
if (inFootprint) then
SendPlayerMessage(a_Player, "This bank is unbreakable")
return true
end
return false
end

πŸͺ™ PeakeCoin Ecosystem

πŸ’± PeakeCoin USDT Bridge (Hive ↔ Polygon/MATIC)
Bridge SWAP.USDT from Hive Engine to USDT on Polygon (MATIC).
Whitelist access, documentation, and bridge status updates:
πŸ‘‰ https://geocities.ws/peakecoin


βš™οΈ HiveP.I.M.P. β€” PeakeCoin Intelligent Market Protector
Operated by hivepimp@hivepimp, P.I.M.P. focuses on stabilizing PEK markets and strengthening liquidity on Hive Engine.
Community participation supports long-term ecosystem health.


πŸ€– PeakeBot β€” Autonomous Trading System
Independent multi-token trading bot with RC-awareness, adaptive delay logic, and smart cycle control.
πŸ“Š Trading bot documentation:
πŸ‘‰ https://geocities.ws/p/e/peakecoin/trading-bot/peakebot_v0_01.html
πŸ’» Open-source repositories:
πŸ‘‰ https://github.com/paulmoon410


🎰 PeakeSino β€” The PeakeCoin Casino (Beta)
Blockchain-powered games using PEK as the native in-game currency.
Built on Hive with a focus on provable fairness and community-driven growth.
πŸƒ Play the beta games here:
πŸ‘‰ https://geocities.ws/peakecoin/pek_casino/beta_games/index.html


πŸ™ Acknowledgements

Thanks to and please follow:
enginewitty@enginewitty ecoinstant@ecoinstant neoxian@neoxian txracer@txracer thecrazygm@thecrazygm holdonia@holdonia aggroed@aggroed

For their continued support, guidance, and help expanding the PeakeCoin ecosystem.


Leave Minecraft - Hive Engine - Beta to:

Written by

Surviving the American Dream, and a father of 2.

Read more #hive-140217 posts


Best Posts From Peake_Dad

We have not curated any of strangedad's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From Peake_Dad