Minecraft - Hive Engine - Beta
Been working on making MineCraft and Hive, or mashing them together at least.
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, 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
@ecoinstant
@neoxian
@txracer
@thecrazygm
@holdonia
@aggroed
For their continued support, guidance, and help expanding the PeakeCoin ecosystem.
Leave Minecraft - Hive Engine - Beta to:
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
- Stolen Funds
- PeakeCoin Bots: Automated Trading Dashboard
- Peake RPG - MMO - Beta Version
- Peake RPG β Current Project Rundown
- Poor Manβs AI β Building While the Servers Are Down
- Hive Trading Bot - strategy.py - Part 4
- Hive Engine Trading Bot - Part 3 - rc_intelligence.py
- Hive Engine Trading Bot - Cycle Control - Part 2
- Hive Engine Trading Bot - Unified Logic - Part 1
- Arbiter Bot - Part 4 - place_order.py