Ir para conteúdo

L3K0T

Diretor
  • Registro em

  • Última visita

  1. arcaydecom reagiu a uma resposta no tópico: WebSite Poketibia 1.0
  2. arawnzz reagiu a uma resposta no tópico: Sprite Stones, Badges e Gyns para Poketibia
  3. V2 O ServerStatusV2 é um app Android leve e eficiente para monitorar o status de portas TCP de qualquer servidor remoto, com notificações instantâneas de queda mesmo quando o app está fechado. Veja como ele funciona: Configuração de IP Ao abrir o app, basta digitar o endereço IP ou hostname do seu servidor na caixinha de texto. Toque em “MONITORAR” e o app grava o IP em cache (SharedPreferences), iniciando imediatamente o monitoramento. Um botão “ALTERAR IP” permite trocar de servidor sem reinstalar o app: ele para o serviço, limpa o IP salvo e volta para o modo de input. Monitoramento em segundo plano Internamente, o app inicia um Foreground Service que roda em background, exibindo uma notificação fixa (“Rodando em background…”). Mesmo se a Activity for fechada ou removida dos apps recentes, o serviço é reiniciado automaticamente, garantindo vigilância 24/7. Polling inteligente com Kotlin Coroutines A cada 10 segundos, o serviço tenta abrir conexão (socket) com as portas configuradas (80, 443, 7171, 7172, 587). Se qualquer porta cair (conexão falha após 1 000 ms), o app dispara uma notificação heads-up com som e vibração, alertando imediatamente. Interface de Status A Activity exibe um relatório agrupado por categoria (Site, Servidor e E-mail), mostrando “Online ✔️” ou “Offline ❌” para cada porta. Logo no primeiro ciclo, o app já exibe o status real sem precisar aguardar. Personalização e robustez O host fica salvo entre execuções, portanto você não precisa redigitar o IP sempre que abrir o app. O código usa ConcurrentHashMap e CoroutineScope, garantindo thread-safety e fácil cancelamento. Foi pensado para não sobrecarregar o servidor nem gerar bloqueio de IP, mantendo o polling num intervalo seguro de 10 s. Com o ServerStatusV2 você terá uma visão clara e confiável do uptime do seu OTServ (ou de qualquer outro serviço TCP), notificando quedas em tempo real e mantendo histórico local enquanto quiser. App: app.apk Scan: https://www.virustotal.com/gui/file/d0bdba516afc3634101b234e24e624302f7f850c892d6275e2c9f552e0db49db?nocache=1 BY L3K0T V4 Além dos recursos já descritos, nesta versão v4 o ServerStatusV2 agora monitora também: OTServ nas portas 7171, 7172 e 7173 Site na porta 80 e 443 E-mail nas portas 25, 587 e 465 Veja o que foi adicionado e aprimorado: Categorias de portas estendidas Antes víamos apenas “Site”, “Servidor” e “E-mail” com portas básicas. Agora há uma categoria “OTServ” para as três portas de jogo/login/console (7171, 7172, 7173), e a categoria “E-mail” cobre SMTP clássico (25), Submission com STARTTLS (587) e SMTPS legacy (465). Máscara de IP automática Ao digitar ou colar algo como 192168011, o campo transforma em 192.168.0.11 automaticamente, facilitando a entrada sem precisar digitar os pontos. Persistência com SharedPreferences e “ALTERAR IP” O IP fica salvo entre execuções. Se precisar trocar de servidor, basta tocar em ALTERAR IP, que interrompe o serviço, limpa o cache e permite nova edição. Foreground Service resiliente Serviço roda em background com notificação fixa, resiste a remoção de apps recentes e, em v4, inclui: Ignorar otimizações de bateria (Battery Saver/Doze Mode). WakeLock parcial para manter o CPU acordado enquanto monitora, evitando ser suspenso. Polling inteligente a cada 10 s Usando Kotlin Coroutines, cada porta é testada via socket com timeout de 1 000 ms. Se qualquer uma delas falhar, uma notificação heads-up com som e vibração alerta instantaneamente. Interface de Status Relatório agrupado por categoria, com bolinha (“●”), ícone e texto “Online ✔️” ou “Offline ❌”. Atualização logo no primeiro ciclo, sem esperar o polling inicial. Leve e robusto Usa ConcurrentHashMap para status thread-safe e cancelamento fácil de coroutines. Mantém intervalo de 10 s para evitar sobrecarga ou bloqueio de IP pelo servidor. App: app.apk Scan: https://www.virustotal.com/gui/file/d0bdba516afc3634101b234e24e624302f7f850c892d6275e2c9f552e0db49db?nocache=1 BY L3K0T
  4. Bom, como todos sabem, existe o shop.lua em servidores 0.4 para receber itens. Muitos deles têm loops infinitos ou fazem uma varredura completa no banco de dados, o que pode deixá-los instáveis. Isso ocorre principalmente quando o script não verifica adequadamente se há itens para processar ou se o banco de dados está sobrecarregado com consultas desnecessárias. No entanto, com algumas melhorias, podemos otimizar esse processo, garantindo que o servidor se mantenha estável e eficiente. No nosso exemplo, aplicamos algumas mudanças importantes: Checagem eficiente de itens pendentes: A consulta ao banco de dados foi otimizada para verificar se existem realmente itens pendentes para o jogador. Se não houver itens, o script termina sua execução rapidamente, evitando sobrecarga. Evitar loops infinitos: O loop foi ajustado para garantir que, se não houver mais itens para processar, o script saia sem continuar verificando o banco de dados, prevenindo loops desnecessários. Logs: Foi adicionado um sistema de logs, onde cada transação bem sucedida do jogador é registrada com data e hora, além de informações sobre o jogador e os itens recebidos. Execução controlada com intervalos: Ao invés de fazer consultas contínuas ao banco de dados, o script executa checagens de tempos em tempos, configuráveis pelo parâmetro SQL_interval. Isso distribui as verificações ao longo do tempo e evita que o servidor fique sobrecarregado com solicitações simultâneas. Segue o scripts: data/globalevents/scripts/shop.lua function getCurrentDateTime() local currentDateTime = os.date("%Y-%m-%d %H:%M:%S") return currentDateTime end function createDirectoryIfNotExists(dir) local command = "mkdir -p " .. dir os.execute(command) end function saveLog(message) local logFilePath = "data/logs/shop/shop.txt" local logDir = "data/logs/shop/" createDirectoryIfNotExists(logDir) local currentDateTime = getCurrentDateTime() local logMessage = string.format("[%s] %s\n", currentDateTime, message) local file = io.open(logFilePath, "a") if file then file:write(logMessage) file:close() else print("Erro ao tentar escrever no arquivo de log.") end end SHOP_MSG_TYPE = 19 SQL_interval = 5 function onThink(interval, lastExecution) local result_plr = db.getResult("SELECT * FROM z_ots_comunication WHERE `type` = 'login';") if result_plr:getID() == -1 then return true end local hasMoreItems = false while true do local id = tonumber(result_plr:getDataInt("id")) local cid = getCreatureByName(tostring(result_plr:getDataString("name"))) if isPlayer(cid) then hasMoreItems = true local itemtogive_id = tonumber(result_plr:getDataInt("param1")) local itemtogive_count = tonumber(result_plr:getDataInt("param2")) local add_item_name = tostring(result_plr:getDataString("param6")) local received_item = 0 local full_weight = 0 if isItemRune(itemtogive_id) then full_weight = getItemWeightById(itemtogive_id, 1) else full_weight = getItemWeightById(itemtogive_id, itemtogive_count) end local free_cap = getPlayerFreeCap(cid) if full_weight <= free_cap then local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) received_item = doPlayerAddItemEx(cid, new_item) if received_item == RETURNVALUE_NOERROR then doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você recebeu >> %s << da loja.", add_item_name)) doPlayerSave(cid) db.executeQuery("DELETE FROM `z_ots_comunication` WHERE `id` = " .. id .. ";") db.executeQuery("UPDATE `z_shop_history` SET `trans_state`='realized', `trans_real`=" .. os.time() .. " WHERE id = " .. id .. ";") saveLog(string.format("[%s] %s (ID: %d), Você recebeu >> %s << da loja.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name)) end else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, string.format("Você não tem capacidade suficiente para >> %s <<. Necessário: %.2f oz. Disponível: %.2f oz.", add_item_name, full_weight, free_cap)) saveLog(string.format("[%s] %s (ID: %d), Tentou comprar >> %s <<, mas não tinha capacidade suficiente. Necessário: %.2f oz. Disponível: %.2f oz.", getCurrentDateTime(), tostring(result_plr:getDataString("name")), id, add_item_name, full_weight, free_cap)) end end if not result_plr:next() then break end end result_plr:free() if not hasMoreItems then return false end return true end data/globalevents/globalevents.xml <globalevent name="shop" interval="30000" script="shop.lua"/> *Testado em Myaac *Testado em OTX2 8.60 *Testado em Ubuntu 20.04 *Não precisa criar pasta, ele mesmo cria. Com essas melhorias, a performance do servidor foi significativamente melhorada, garantindo que o sistema de loja funcione de forma mais estável e eficiente, sem sobrecarregar o banco de dados ou causar lags. Agora, a transação de itens na loja ocorre de forma mais controlada e com menos chance de erros ou travamentos. by @L3K0T
  5. Versões mais recentes do OTServ, como TFS 1.0 ou superior, requerem versões mais novas do Ubuntu, geralmente 18.04 ou superior, devido à compatibilidade com bibliotecas e dependências atualizadas. Já servidores mais antigos, como TFS 0.3 e 0.4, funcionam melhor em versões anteriores do Ubuntu, como 16.04 ou 14.04 ou 12.04 dependendo da configuração do sistema.
  6. L3K0T reagiu a uma resposta no tópico: (Resolvido)Player nao salva quando desloga
  7. L3K0T postou uma resposta no tópico em Suporte Tibia OTServer
    local internalNpcName = "Guardian" local npcType = Game.createNpcType(internalNpcName) local npcConfig = {} npcConfig.name = internalNpcName npcConfig.description = internalNpcName npcConfig.health = 100 npcConfig.maxHealth = npcConfig.health npcConfig.walkInterval = 0 npcConfig.walkRadius = 2 npcConfig.outfit = { lookTypeEx = 2152, } npcConfig.flags = { floorchange = false, } local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) npcType.onThink = function(npc, interval) npcHandler:onThink(npc, interval) end npcType.onAppear = function(npc, creature) npcHandler:onAppear(npc, creature) end npcType.onDisappear = function(npc, creature) npcHandler:onDisappear(npc, creature) end npcType.onMove = function(npc, creature, fromPosition, toPosition) npcHandler:onMove(npc, creature, fromPosition, toPosition) end npcType.onSay = function(npc, creature, type, message) npcHandler:onSay(npc, creature, type, message) end npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) if not player then return false end if message:lower() == "abre-te sésamo" then local topos = Position(32311, 11005, 6) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) player:teleportTo(topos) topos:sendMagicEffect(CONST_ME_TELEPORT) end return true end keywordHandler:addKeyword({ "abre-te sésamo" }, StdModule.say, {npcHandler = npcHandler, text = "Diga a palavra mágica e será transportado!"}) npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcType:register(npcConfig)
  8. isso é pq a versão ou config da sprite ou item.otb não é compativel
  9. TESTA AI local config = { centerRoom = Position(33584, 32689, 14), BossPosition = Position(33584, 32689, 14), playerPositions = { Position(33593, 32644, 14), Position(33593, 32645, 14), Position(33593, 32646, 14), Position(33593, 32647, 14), Position(33593, 32648, 14) }, newPosition = Position(33585, 32693, 14), cooldownTime = 120 --(2 minutos) } function onUse(player, item, fromPosition, target, toPosition, isHotkey) local lastUse = Game.getStorageValue(GlobalStorage.FerumbrasAscendantQuest.MazoranLeverCooldown) local currentTime = os.time() if lastUse > 0 and currentTime - lastUse < config.cooldownTime then local remainingTime = config.cooldownTime - (currentTime - lastUse) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Você precisa aguardar " .. remainingTime .. " segundos para puxar a alavanca novamente.") return true end if item.itemid == 9825 then local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) for i = 1, #specs do spec = specs[i] if spec:isPlayer() then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Alguém já está enfrentando Mazoran.") return true end end local spectators = Game.getSpectators(config.BossPosition, false, false, 20, 20, 20, 20) for i = 1, #spectators do local spectator = spectators[i] if spectator:isMonster() then spectator:remove() return true end end Game.createMonster("Mazoran", config.BossPosition, true, true) for y = 32644, 32648 do local playerTile = Tile(Position(33593, y, 14)):getTopCreature() if playerTile and playerTile:isPlayer() then playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) playerTile:teleportTo(config.newPosition) playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end end Game.setStorageValue(GlobalStorage.FerumbrasAscendantQuest.MazoranLeverCooldown, currentTime) Game.setStorageValue(GlobalStorage.FerumbrasAscendantQuest.MazoranTimer, 1) addEvent(clearForgotten, 30 * 60 * 1000, Position(33572, 32679, 14), Position(33599, 32701, 14), Position(33319, 32318, 13), GlobalStorage.FerumbrasAscendantQuest.MazoranTimer) item:transform(9826) elseif item.itemid == 9826 then item:transform(9825) end return true end
  10. Fluppe Naves reagiu a uma resposta no tópico: Tibia Ginius Versão 1.1 by L3K0T
  11. Rodrigo94 reagiu a uma resposta no tópico: System Drop Global - L3K0T TFS 0.4
  12. Alterei a função canWalkthrough para Impedir o atravessamento de pisos específicos (como 11059 e 11060) se já houver um jogador sobre eles e assim ninguem entra no mesmo depot que é comum em pvp então vamos retirar isso. Verificar o tipo de mundo (PVP / non-PVP / etc..) e zonas de proteção. No PVP, jogadores podem atravessar se estiverem fora de uma zona de proteção ou quando ambos não estiverem em combate. Segue as alterações: vá em Player.cpp e ache: bool Player::canWalkthrough(const Creature* creature) const { if(creature == this || hasFlag(PlayerFlag_CanPassThroughAllCreatures) || creature->isWalkable() || std::find(forceWalkthrough.begin(), forceWalkthrough.end(), creature->getID()) != forceWalkthrough.end() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if(!player) return false; if((((g_game.getWorldType() == WORLDTYPE_OPTIONAL && #ifdef __WAR_SYSTEM__ !player->isEnemy(this, true) && #endif player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground && Item::items[player->getTile()->ground->getID()].walkStack) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); } altere para bool Player::canWalkthrough(const Creature* creature) const { if(creature == this || hasCustomFlag(PlayerCustomFlag_CanTurnhop) || creature->isWalkable() || (creature->getMaster() && creature->getMaster() != this && canWalkthrough(creature->getMaster()))) return true; const Player* player = creature->getPlayer(); if(!player) return false; const Tile* tile = player->getTile(); if(tile && tile->ground) { // Verifica se o tile e o chão existem uint16_t groundID = tile->ground->getID(); if(groundID == 11059 || groundID == 11060) { return false; // Bloqueia atravessamento para esses pisos } } if((((g_game.getWorldType() == WORLDTYPE_OPTIONAL && !player->isEnemy(this, true) && #ifdef __WAR_SYSTEM__ !player->isEnemy(this, true) && #endif player->getVocation()->isAttackable()) || player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) || (player->getVocation()->isAttackable() && player->getLevel() < (uint32_t)g_config.getNumber(ConfigManager::PROTECTION_LEVEL))) && player->getTile()->ground && Item::items[player->getTile()->ground->getID()].walkStack) && (!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || player->getAccess() <= getAccess())) return true; return (player->isGhost() && getGhostAccess() < player->getGhostAccess()) || (isGhost() && getGhostAccess() > player->getGhostAccess()); } pronto só recompilar e testar.
  13. use xammp da versão mais antiga
  14. L3K0T reagiu a uma resposta no tópico: [13.40] Crystal Server 4.0 | Mapa Global
  15. L3K0T reagiu a uma resposta no tópico: [13.40] Crystal Server 4.0 | Mapa Global
  16. L3K0T postou uma resposta no tópico em Códigos C++
    Estou com algumas "revs não alteradas" e gostaria de compartilhar com vocês pois pode ajudar em alguma coisa. https://www.mediafire.com/folder/t3y80vqcnow4d/sources_revs_l3k0t
  17. realmente depende muito do site que ele está usando, mais esse erro é comum em php e suas versões, eu passei por esse erro em MyAAC só pegou em 7.2, com Nginx
  18. L3K0T reagiu a uma resposta no tópico: Ajuda Com Site erro HTTP ERROR 500
  19. cara eu uso php 7.2 no ubuntu 18.04 vai de boas
  20. function onStatsChange(cid, attacker, type, combat, value) if isMonster(cid) and isMonster(attacker) then local master = getCreatureMaster(attacker) if not master or not isPlayer(master) then return false -- Bloqueia o dano end end return true end on combat function onCombat(cid, target) if isMonster(cid) and isMonster(target) then local master = getCreatureMaster(cid) if not master or not isPlayer(master) then return false -- Bloqueia o ataque end end return true end <event type="combat" name="BlockMonsterCombat" script="block_monster_combat.lua"/>
  21. function onStatsChange(cid, attacker, type, combat, value) if isMonster(cid) and isMonster(attacker) then local master = getCreatureMaster(cid) if not master or not isPlayer(master) then return false end end return true end <event type="statschange" name="BlockMonsterDamage" script="seu_script.lua"/> registerCreatureEvent(cid, "BlockMonsterDamage")

Informação Importante

Confirmação de Termo