Added Chatbox

Added Chatbox
This commit is contained in:
novgorodschi catalin
2026-09-08 12:56:02 +03:00
parent 551c58fc3c
commit 009bba0ce6
10 changed files with 831 additions and 30 deletions
@@ -1227,7 +1227,13 @@ trait AutomationBattleResolution {
*/
private function applyOwnDefenceCasualties($data, $targettribe, $battlepart) {
global $database;
$targettribe = (int)$targettribe;
// FIX: daca satul a fost sters / owner 0 / oaza fara trib, nu avem ce sterge
if($targettribe < 1 || $targettribe > 9) {
return [];
}
$owndead = [];
$unitlist = $database->getUnit($data['to'], false);
$start = ($targettribe - 1) * 10 + 1;
@@ -1319,7 +1325,7 @@ trait AutomationBattleResolution {
} else {
$tribe = 4;
}
if($tribe < 1 || $tribe > 9) $tribe = 4; // fallback la natura
$start = ($tribe - 1) * 10 + 1;
$end = ($tribe * 10);
unset($dead);
+3
View File
@@ -60,6 +60,8 @@ include_once __DIR__ . '/Database/DatabaseHeroQueries.php';
include_once __DIR__ . '/Database/DatabaseStatisticsQueries.php';
include_once __DIR__ . '/Database/DatabaseArtefactQueries.php';
include_once __DIR__ . '/Database/DatabaseSystemQueries.php';
// Chat general (server-wide), cerut de Catalin 07.09.2026 - separat de alliance chat (chat.php)
include_once __DIR__ . '/Database/DatabaseGlobalChatQueries.php';
use App\Database\IDbConnection;
use App\Utils\Math;
@@ -80,6 +82,7 @@ class MYSQLi_DB implements IDbConnection {
use DatabaseStatisticsQueries;
use DatabaseArtefactQueries;
use DatabaseSystemQueries;
use DatabaseGlobalChatQueries;
@@ -0,0 +1,176 @@
<?php
#################################################################################
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
## --------------------------------------------------------------------------- ##
## Project: TravianZ ##
## Filename: DatabaseGlobalChatQueries.php ##
## Purpose: Server-wide ("World Chat") messages + moderation ##
## (mute/block), separate from the existing alliance chat ##
## (chat table, see GameEngine/Chat.php). ##
## ##
## Cerut de Catalin, 07.09.2026: chat general vizibil/scris de orice ##
## jucator logat, cu moderare pentru Admin (access 9) si MH (access 8). ##
## ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2026. All rights reserved. ##
## URLs: https://travianz.org ##
## https://github.com/Shadowss/TravianZ ##
#################################################################################
trait DatabaseGlobalChatQueries {
/**
* Posteaza un mesaj in chat-ul general, daca userul nu e mutat si a
* trecut rate-limit-ul minim intre 2 mesaje (anti-spam simplu).
*
* @return array ['ok'=>bool, 'reason'=>string|null, 'mutedUntil'=>int|null]
*/
function postGlobalChatMessage($uid, $msg) {
$uid = (int) $uid;
$msg = trim((string) $msg);
if ($uid <= 0) {
return ['ok' => false, 'reason' => 'notloggedin'];
}
if ($msg === '') {
return ['ok' => false, 'reason' => 'empty'];
}
// acelasi plafon ca la chat-ul de alianta existent (chat.msg e varchar(255);
// 250 lasa loc de siguranta pentru escaping/multi-byte)
$msg = function_exists('mb_substr') ? mb_substr($msg, 0, 250) : substr($msg, 0, 250);
$mutedUntil = $this->getGlobalChatMuteStatus($uid);
if ($mutedUntil !== null) {
return ['ok' => false, 'reason' => 'muted', 'mutedUntil' => $mutedUntil];
}
list($euid) = $this->escape_input($uid);
$lastRow = mysqli_fetch_assoc($this->query(
"SELECT date FROM " . TB_PREFIX . "chat_global WHERE id_user = $euid ORDER BY id DESC LIMIT 1"
));
$now = time();
// rate-limit: minim 3 secunde intre 2 mesaje ale aceluiasi user
if ($lastRow && ($now - (int) $lastRow['date']) < 3) {
return ['ok' => false, 'reason' => 'ratelimit'];
}
list($emsg) = $this->escape_input($msg);
$this->query(
"INSERT INTO " . TB_PREFIX . "chat_global (id_user, date, msg) VALUES ($euid, $now, '$emsg')"
);
return ['ok' => true];
}
/**
* Mesajele din chat-ul general, gata de afisat (ordine cronologica).
*
* Mod 1 - incarcare initiala: ultimele $limit mesaje ($sinceId = 0).
* Mod 2 - poll incremental: doar mesajele noi, mai mari decat $sinceId
* (evita re-trimiterea ferestrei intregi la fiecare interogare din JS).
*
* Tag-ul de alianta si nivelul de access sunt rezolvate live, printr-un
* singur JOIN (nu o interogare per mesaj) - reflecta mereu alianta
* curenta a jucatorului, nu una "inghetata" la momentul postarii.
*/
function getGlobalChatMessages($limit = 30, $sinceId = 0) {
$limit = (int) $limit;
$sinceId = (int) $sinceId;
$where = $sinceId > 0 ? "WHERE c.id > $sinceId" : "";
$order = $sinceId > 0 ? "ORDER BY c.id ASC" : "ORDER BY c.id DESC";
// plafon si pe polling-ul incremental (nu doar la incarcarea initiala) -
// daca un tab a stat minimizat/in background ore intregi (throttling de
// browser pe mobil), la revenire nu vrem un SELECT nemarginit
$limitSql = "LIMIT " . ($sinceId > 0 ? 200 : $limit);
$q = "SELECT c.id, c.id_user, c.date, c.msg, u.username, u.access, a.tag AS ally_tag, a.id AS ally_id
FROM " . TB_PREFIX . "chat_global c
LEFT JOIN " . TB_PREFIX . "users u ON u.id = c.id_user
LEFT JOIN " . TB_PREFIX . "alidata a ON a.id = u.alliance AND u.alliance > 0
$where
$order
$limitSql";
$rows = $this->mysqli_fetch_all($this->query($q));
// la incarcarea initiala am luat descrescator (ca sa prindem exact
// ultimele $limit), le intoarcem in ordine cronologica normala
if ($sinceId <= 0) {
$rows = array_reverse($rows);
}
return $rows;
}
/**
* Timestamp-ul (unix) pana la care userul e mutat din chat-ul general,
* sau null daca nu e mutat (inclusiv daca o mutare veche a expirat).
*/
function getGlobalChatMuteStatus($uid) {
$uid = (int) $uid;
$row = mysqli_fetch_assoc($this->query(
"SELECT muted_until FROM " . TB_PREFIX . "chat_mutes WHERE id_user = $uid"
));
if (!$row) {
return null;
}
$until = (int) $row['muted_until'];
return $until > time() ? $until : null;
}
/**
* Info despre viewer-ul curent, folosita de client ca sa stie daca
* afiseaza controalele de moderare si daca dezactiveaza inputul (mutat).
*/
function getGlobalChatViewerInfo($uid) {
$uid = (int) $uid;
$access = (int) $this->getUserField($uid, 'access', 0);
return [
'uid' => $uid,
'access' => $access,
'isMod' => $access >= MULTIHUNTER,
'mutedUntil' => $this->getGlobalChatMuteStatus($uid),
];
}
/**
* Muteaza (temporar sau permanent, dupa $untilTimestamp) un user din
* chat-ul general. Ierarhia de rang (cine pe cine poate muta) se
* verifica in ajax.php inainte de a apela asta - metoda doar scrie
* starea, ca sa ramana usor de testat separat.
*/
function muteGlobalChatUser($targetUid, $mutedBy, $untilTimestamp, $reason = '') {
$targetUid = (int) $targetUid;
$mutedBy = (int) $mutedBy;
$untilTimestamp = (int) $untilTimestamp;
list($ereason) = $this->escape_input((string) $reason);
$now = time();
$q = "INSERT INTO " . TB_PREFIX . "chat_mutes (id_user, muted_until, muted_by, reason, created)
VALUES ($targetUid, $untilTimestamp, $mutedBy, '$ereason', $now)
ON DUPLICATE KEY UPDATE muted_until = $untilTimestamp, muted_by = $mutedBy, reason = '$ereason', created = $now";
return $this->query($q) ? true : false;
}
function unmuteGlobalChatUser($targetUid) {
$targetUid = (int) $targetUid;
return $this->query(
"DELETE FROM " . TB_PREFIX . "chat_mutes WHERE id_user = $targetUid"
) ? true : false;
}
}
+19
View File
@@ -4404,3 +4404,22 @@ tz_def('TRAIN_BONUS_ARTIFACT', 'Artifact bonus');
tz_def('TRAIN_BONUS_HERO', 'Hero bonus');
tz_def('TRAIN_BONUS_ALLIANCE', 'Alliance bonus');
tz_def('TRAIN_BONUS_FINAL', 'Training time');
//////////////////////////////////////////////////////////////////////////////////////////////////////
// GENERAL (SERVER-WIDE) CHAT - floating widget, footer.tpl + Templates/GlobalChat/widget.tpl
//////////////////////////////////////////////////////////////////////////////////////////////////////
tz_def('GCHAT_TITLE', 'World Chat');
tz_def('GCHAT_PLACEHOLDER', 'Message...');
tz_def('GCHAT_SEND', 'Send');
tz_def('GCHAT_EMPTY', 'No messages yet.');
tz_def('GCHAT_MUTED', 'You are muted from chat.');
tz_def('GCHAT_RATELIMIT', 'You are sending messages too fast.');
tz_def('GCHAT_CONFIRM_BLOCK', 'Block this player from chat permanently?');
tz_def('GCHAT_MUTE_5M', 'Mute 5m');
tz_def('GCHAT_MUTE_30M', 'Mute 30m');
tz_def('GCHAT_MUTE_1H', 'Mute 1h');
tz_def('GCHAT_MUTE_24H', 'Mute 24h');
tz_def('GCHAT_BLOCK', 'Block');
tz_def('GCHAT_UNMUTE', 'Unmute');
tz_def('GCHAT_ADMIN_BADGE', 'Admin');
tz_def('GCHAT_MH_BADGE', 'MH');
+19 -1
View File
@@ -4141,4 +4141,22 @@ tz_def('SITTER_P_NOT_SITTING', 'Nu esti sitter pe niciun cont.');
tz_def('TRAIN_BONUS_ARTIFACT', 'Bonus artefact');
tz_def('TRAIN_BONUS_HERO', 'Bonus erou');
tz_def('TRAIN_BONUS_ALLIANCE', 'Bonus alianta');
tz_def('TRAIN_BONUS_FINAL', 'Timp instruire');
tz_def('TRAIN_BONUS_FINAL', 'Timp instruire');
//////////////////////////////////////////////////////////////////////////////////////////////////////
// CHAT GENERAL (server-wide) - widget plutitor, footer.tpl + Templates/GlobalChat/widget.tpl
//////////////////////////////////////////////////////////////////////////////////////////////////////
tz_def('GCHAT_TITLE', 'Chat general');
tz_def('GCHAT_PLACEHOLDER', 'Mesaj...');
tz_def('GCHAT_SEND', 'Trimite');
tz_def('GCHAT_EMPTY', 'Niciun mesaj inca.');
tz_def('GCHAT_MUTED', 'Esti mutat din chat.');
tz_def('GCHAT_RATELIMIT', 'Trimiti mesaje prea repede.');
tz_def('GCHAT_CONFIRM_BLOCK', 'Blochezi permanent acest jucator din chat?');
tz_def('GCHAT_MUTE_5M', 'Mute 5m');
tz_def('GCHAT_MUTE_30M', 'Mute 30m');
tz_def('GCHAT_MUTE_1H', 'Mute 1h');
tz_def('GCHAT_MUTE_24H', 'Mute 24h');
tz_def('GCHAT_BLOCK', 'Blocheaza');
tz_def('GCHAT_UNMUTE', 'Anuleaza mute');
tz_def('GCHAT_ADMIN_BADGE', 'Admin');
tz_def('GCHAT_MH_BADGE', 'MH');