using System; using System.Collections.Generic; using Oxide.Core.Plugins; using UnityEngine; /* * MajestatBuild 1.0.0 * ==================== * Moduł dla MajestatCore 3.0.0 — zlicza postawione konstrukcje. * * WYMAGA: MajestatCore 3.0.0+ * * Rejestruje zakładkę "BUILD" w UI MajestatCore przez API_RegisterTab. * * Śledzone statystyki: * Build.Total — wszystkie postawione obiekty łącznie * Build.Walls — ściany, drzwi, okna, ramy * Build.Floors — podłogi, schody, skośne podłogi * Build.Turrets — wieżyczki automatyczne (autoturret) * Build.Traps — pułapki (beartrap, landmine, shotguntrap, flameturret) * Build.Doors — drzwi * Build.Electrical — elementy elektryczne (solary, baterie, switche) * Build.Pipes — rury wodne i przemysłowe */ namespace Oxide.Plugins { [Info("MajestatTopBuild", "Wo0t", "1.0.0")] [Description("Build module for MajestatTopCore — tracks placed structures.")] class MajestatTopBuild : RustPlugin { [PluginReference] Plugin MajestatTopCore; private bool _registered = false; // 0 = tylko przy starcie, np. 720 = co 12h private int _updateIntervalMinutes = 0; // ── Update checker ──────────────────────────────────────────── private const string PluginVersion = "1.0.0"; private const string PluginUpdateUrl = "http://download.koldrix.com/rust/plugins/MajestatTopBuild/version.json"; // ═════════════════════════════════════════════════════════════ // INIT // ═════════════════════════════════════════════════════════════ void OnServerInitialized() { if (MajestatTopCore == null) { PrintWarning("MajestatCore nie jest załadowany! Moduł nieaktywny."); return; } RegisterTab(); } void OnPluginLoaded(Plugin plugin) { if (plugin?.Name == "MajestatTopCore" && !_registered) RegisterTab(); } void OnPluginUnloaded(Plugin plugin) { if (plugin?.Name == "MajestatTopCore") _registered = false; } void Unload() { if (MajestatTopCore != null && _registered) MajestatTopCore.Call("API_UnregisterTab", "build"); } // ═════════════════════════════════════════════════════════════ // REJESTRACJA ZAKŁADKI // ═════════════════════════════════════════════════════════════ private void RegisterTab() { if (MajestatTopCore == null) return; var columns = new List> { new Dictionary { ["key"] = "Build.Total", ["header"] = "TOTAL" }, new Dictionary { ["key"] = "Build.Walls", ["header"] = "ŚCIANY" }, new Dictionary { ["key"] = "Build.Floors", ["header"] = "PODŁOGI" }, new Dictionary { ["key"] = "Build.Doors", ["header"] = "DRZWI" }, new Dictionary { ["key"] = "Build.Turrets", ["header"] = "WIEŻYCZKI"}, new Dictionary { ["key"] = "Build.Traps", ["header"] = "PUŁAPKI" }, new Dictionary { ["key"] = "Build.Electrical", ["header"] = "ELEKTR." }, new Dictionary { ["key"] = "Build.Pipes", ["header"] = "RURY" }, }; var tabDef = new Dictionary { ["id"] = "build", ["label"] = "BUILD", ["sort"] = "Build.Total", ["fame_sort"] = "Build.Total", ["order"] = 20, // TOP PvP=0, Gather=10, Build=20 ["columns"] = columns }; bool ok = (bool)(MajestatTopCore.Call("API_RegisterTab", tabDef) ?? false); if (!ok) { PrintError("Rejestracja zakładki nie powiodła się."); return; } // Zarejestruj źródła XP — Core doda je do cfg jeśli nie istnieją. // Admin ustawia wartości XP w konfiguracji MajestatCore. MajestatTopCore.Call("API_RegisterXpSource", "Build.Walls", 0.0); MajestatTopCore.Call("API_RegisterXpSource", "Build.Floors", 0.0); MajestatTopCore.Call("API_RegisterXpSource", "Build.Doors", 0.0); MajestatTopCore.Call("API_RegisterXpSource", "Build.Turrets", 0.0); MajestatTopCore.Call("API_RegisterXpSource", "Build.Traps", 0.0); MajestatTopCore.Call("API_RegisterXpSource", "Build.Electrical", 0.0); MajestatTopCore.Call("API_RegisterXpSource", "Build.Pipes", 0.0); _registered = true; // Pobierz interwał z konfiguracji MajestatTopCore var intervalObj = MajestatTopCore.Call("API_GetUpdateInterval"); _updateIntervalMinutes = intervalObj is int iv ? iv : 0; timer.Once(5f, CheckForUpdate); if (_updateIntervalMinutes > 0) timer.Every(_updateIntervalMinutes * 60f, CheckForUpdate); Puts("Zakładka BUILD zarejestrowana. Użyj /top → BUILD."); } // ═════════════════════════════════════════════════════════════ // HOOK — POSTAWIENIE OBIEKTU // ═════════════════════════════════════════════════════════════ void OnEntityBuilt(Planner planner, GameObject go) { if (planner == null || go == null || MajestatTopCore == null) return; var player = planner.GetOwnerPlayer(); if (player == null) return; var entity = go.GetComponent(); if (entity == null) return; string prefab = entity.ShortPrefabName?.ToLower() ?? ""; string statKey = ResolveKey(prefab); if (statKey == null) return; // Dodaj do konkretnej kategorii (z XP jeśli skonfigurowane) MajestatTopCore.Call("API_AddStat", player.UserIDString, statKey, 1.0, true, true); // Dodaj do sumy (bez XP — żeby nie liczyć podwójnie) MajestatTopCore.Call("API_AddStat", player.UserIDString, "Build.Total", 1.0, true, false); Puts($"BUILD: {player.displayName} postawił {prefab} → {statKey}"); } // ═════════════════════════════════════════════════════════════ // MAPOWANIE PREFAB → STATYSTYKA // ═════════════════════════════════════════════════════════════ private string ResolveKey(string prefab) { if (prefab == null) return null; // Ściany (wall, doorway, window, embrasure, wall.frame) if (prefab.Contains("wall") && !prefab.Contains("turret") && !prefab.Contains("fireplace")) return "Build.Walls"; // Podłogi i schody (floor, roof, stairs) if (prefab.Contains("floor") || prefab.Contains("roof") || prefab.Contains("stairs") || prefab.Contains("ramp")) return "Build.Floors"; // Drzwi (door, hatch, shutter) if (prefab.Contains("door") || prefab.Contains("hatch") || prefab.Contains("shutter")) return "Build.Doors"; // Wieżyczki automatyczne if (prefab.Contains("autoturret") || prefab.Contains("sam.site")) return "Build.Turrets"; // Pułapki (beartrap, landmine, shotguntrap, flameturret, guntrap) if (prefab.Contains("beartrap") || prefab.Contains("landmine") || prefab.Contains("shotguntrap") || prefab.Contains("flameturret") || prefab.Contains("guntrap") || prefab.Contains("spikes")) return "Build.Traps"; // Elektryka (solarpanel, battery, switch, generator, splitter, // combiner, blocker, xor, timer, counter, pressurepad, // sirenlight, strobelight, smartalarm, rf.broadcaster) if (prefab.Contains("electric") || prefab.Contains("solar") || prefab.Contains("battery") || prefab.Contains("switch") || prefab.Contains("generator") || prefab.Contains("splitter") || prefab.Contains("combiner") || prefab.Contains("blocker") || prefab.Contains("timer") || prefab.Contains("counter") || prefab.Contains("pressurepad") || prefab.Contains("sirenlight") || prefab.Contains("strobelight") || prefab.Contains("smartalarm") || prefab.Contains("rf.broadcaster") || prefab.Contains("rf.receiver") || prefab.Contains("igniter") || prefab.Contains("doorcontroller")) return "Build.Electrical"; // Rury i przemysł (water.pump, fluid.combiner, fluid.splitter, // industrial.conveyor, industrial.crafter) if (prefab.Contains("water.pump") || prefab.Contains("fluid") || prefab.Contains("industrial") || prefab.Contains("pipe") || prefab.Contains("sprinkler") || prefab.Contains("water.catcher")) return "Build.Pipes"; return null; } // ═════════════════════════════════════════════════════════════ // UPDATE CHECKER — niezależny od MajestatTopCore // ═════════════════════════════════════════════════════════════ private void CheckForUpdate() { Puts($"[Update] Sprawdzam aktualizacje... (aktualna wersja: {PluginVersion})"); webrequest.Enqueue(PluginUpdateUrl, null, OnUpdateResponse, this); } private void OnUpdateResponse(int code, string response) { if (code == 0 || code >= 400 || string.IsNullOrEmpty(response)) { Puts($"[Update] Nie można sprawdzić aktualizacji — serwer niedostępny (HTTP {code})."); return; } try { var data = JsonConvert.DeserializeObject>(response); if (data == null || !data.ContainsKey("version")) { Puts("[Update] Nieprawidłowy plik version.json."); return; } string latest = data["version"].Trim(); if (IsNewerVersion(latest, PluginVersion)) { string url = data.ContainsKey("url") ? data["url"] : PluginUpdateUrl; PrintWarning($"[Update] Dostępna nowa wersja: {latest} (zainstalowana: {PluginVersion})"); PrintWarning($"[Update] Pobierz: {url}"); } else { Puts($"[Update] Wersja aktualna ({PluginVersion}) — brak aktualizacji."); } } catch (Exception ex) { Puts($"[Update] Błąd odczytu odpowiedzi: {ex.Message}"); } } private bool IsNewerVersion(string latest, string current) { try { var l = System.Array.ConvertAll(latest.Split('.'), int.Parse); var c = System.Array.ConvertAll(current.Split('.'), int.Parse); int len = System.Math.Max(l.Length, c.Length); for (int i = 0; i < len; i++) { int lv = i < l.Length ? l[i] : 0; int cv = i < c.Length ? c[i] : 0; if (lv > cv) return true; if (lv < cv) return false; } return false; } catch { return false; } } } }