esp filter and customize lobby

This commit is contained in:
2025-11-04 19:35:50 +11:00
parent 92101631af
commit d80ea2b827
10 changed files with 1670 additions and 51 deletions

View File

@@ -26,7 +26,8 @@ namespace DevourClient
ESP = 3, ESP = 3,
Items = 4, Items = 4,
Misc = 5, Misc = 5,
Players = 6 Players = 6,
Network = 7
} }
static Rect windowRect = new Rect(Settings.Settings.x + 10, Settings.Settings.y + 10, 800, 750); static Rect windowRect = new Rect(Settings.Settings.x + 10, Settings.Settings.y + 10, 800, 750);
@@ -56,9 +57,10 @@ namespace DevourClient
static bool azazel_esp = false; static bool azazel_esp = false;
static bool azazel_skel_esp = false; static bool azazel_skel_esp = false;
static bool azazel_snapline = false; static bool azazel_snapline = false;
static bool item_esp = false; // These variables are now managed by ESP.ItemESPConfig system
static bool goat_rat_esp = false; static bool item_esp => ESP.ItemESPConfig.ItemESP;
static bool demon_esp = false; static bool goat_rat_esp => ESP.ItemESPConfig.GoatRatESP;
static bool demon_esp => ESP.ItemESPConfig.DemonESP;
static bool fullbright = false; static bool fullbright = false;
static bool need_fly_reset = false; static bool need_fly_reset = false;
static bool crosshair = false; static bool crosshair = false;
@@ -66,6 +68,11 @@ namespace DevourClient
static bool should_show_start_message = true; static bool should_show_start_message = true;
static Texture2D crosshairTexture = default!; static Texture2D crosshairTexture = default!;
// Network variables
static int selectedRegion = 0;
static int lobbySize = 4;
static bool isPrivateLobby = false;
private static int frameCount = 0; private static int frameCount = 0;
private static int lastMemoryLog = 0; private static int lastMemoryLog = 0;
private const int GC_GEN0_INTERVAL = 300; private const int GC_GEN0_INTERVAL = 300;
@@ -97,9 +104,11 @@ namespace DevourClient
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetCorpses())); Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetCorpses()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetCrows())); Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetCrows()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetLumps())); Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetLumps()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetDirtyHeads()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetAzazels())); Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetAzazels()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetAllPlayers())); Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetAllPlayers()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetMonkeys())); Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetMonkeys()));
Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetDolls()));
} }
public void Update() public void Update()
@@ -271,9 +280,13 @@ namespace DevourClient
GUI.skin.textField.normal.background = GUIHelper.MakeTex(2, 2, new Color(0.2f, 0.2f, 0.2f, 0.8f)); GUI.skin.textField.normal.background = GUIHelper.MakeTex(2, 2, new Color(0.2f, 0.2f, 0.2f, 0.8f));
GUI.skin.textField.normal.textColor = Color.white; GUI.skin.textField.normal.textColor = Color.white;
GUI.skin.textField.focused.background = GUIHelper.MakeTex(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.9f)); GUI.skin.textField.focused.background = GUIHelper.MakeTex(2, 2, new Color(0.3f, 0.5f, 0.3f, 0.9f));
GUI.skin.textField.focused.textColor = Color.yellow; GUI.skin.textField.focused.textColor = Color.white;
GUI.skin.textField.border = new RectOffset(2, 2, 2, 2); GUI.skin.textField.hover.background = GUIHelper.MakeTex(2, 2, new Color(0.25f, 0.25f, 0.25f, 0.85f));
GUI.skin.textField.border = new RectOffset(4, 4, 4, 4);
GUI.skin.textField.padding = new RectOffset(6, 6, 4, 4);
GUI.skin.textField.fontSize = 14;
GUI.skin.textField.alignment = TextAnchor.MiddleLeft;
GUI.skin.label.normal.textColor = Color.white; GUI.skin.label.normal.textColor = Color.white;
@@ -310,6 +323,7 @@ namespace DevourClient
} }
} }
// Goat/Rat ESP - now using separate ESP type filtering
if (goat_rat_esp) if (goat_rat_esp)
{ {
foreach (Il2Cpp.GoatBehaviour goat in Helpers.Entities.GoatsAndRats) foreach (Il2Cpp.GoatBehaviour goat in Helpers.Entities.GoatsAndRats)
@@ -317,12 +331,18 @@ namespace DevourClient
if (goat != null) if (goat != null)
{ {
string itemName = goat.name.Replace("Survival", "").Replace("(Clone)", ""); string itemName = goat.name.Replace("Survival", "").Replace("(Clone)", "");
string translatedName = MultiLanguageSystem.Translate(itemName);
Render.Render.DrawNameESP(goat.transform.position, translatedName, new Color(0.94f, 0.61f, 0.18f, 1.0f)); // Check if ESP should be shown for this item
if (ESP.ItemESPConfig.ShouldShowESP(itemName))
{
string translatedName = MultiLanguageSystem.Translate(itemName);
Render.Render.DrawNameESP(goat.transform.position, translatedName, new Color(0.94f, 0.61f, 0.18f, 1.0f));
}
} }
} }
} }
// Item ESP - now using separate ESP type filtering
if (item_esp) if (item_esp)
{ {
foreach (Il2Cpp.SurvivalInteractable obj in Helpers.Entities.SurvivalInteractables) foreach (Il2Cpp.SurvivalInteractable obj in Helpers.Entities.SurvivalInteractables)
@@ -330,8 +350,13 @@ namespace DevourClient
if (obj != null) if (obj != null)
{ {
string itemName = obj.prefabName.Replace("Survival", ""); string itemName = obj.prefabName.Replace("Survival", "");
string translatedName = MultiLanguageSystem.Translate(itemName);
Render.Render.DrawNameESP(obj.transform.position, translatedName, new Color(1.0f, 1.0f, 1.0f)); // Check if ESP should be shown for this item
if (ESP.ItemESPConfig.ShouldShowESP(itemName))
{
string translatedName = MultiLanguageSystem.Translate(itemName);
Render.Render.DrawNameESP(obj.transform.position, translatedName, new Color(1.0f, 1.0f, 1.0f));
}
} }
} }
@@ -339,85 +364,130 @@ namespace DevourClient
{ {
if (key != null) if (key != null)
{ {
string translatedName = MultiLanguageSystem.Translate("Key"); // Check if ESP should be shown for keys
Render.Render.DrawNameESP(key.transform.position, translatedName, new Color(1.0f, 1.0f, 1.0f)); if (ESP.ItemESPConfig.ShouldShowESP("Key"))
{
string translatedName = MultiLanguageSystem.Translate("Key");
Render.Render.DrawNameESP(key.transform.position, translatedName, new Color(1.0f, 1.0f, 1.0f));
}
} }
} }
} }
// Enemy ESP - now using separate ESP type filtering
if (demon_esp) if (demon_esp)
{ {
// Demon (Farmhouse)
foreach (Il2Cpp.SurvivalDemonBehaviour demon in Helpers.Entities.Demons) foreach (Il2Cpp.SurvivalDemonBehaviour demon in Helpers.Entities.Demons)
{ {
if (demon != null) if (demon != null)
{ {
string enemyName = demon.name.Replace("Survival", "").Replace("(Clone)", ""); string enemyName = demon.name.Replace("Survival", "").Replace("(Clone)", "");
string translatedName = MultiLanguageSystem.Translate(enemyName);
Render.Render.DrawNameESP(demon.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); // Check if ESP should be shown for this enemy
if (ESP.ItemESPConfig.ShouldShowESP(enemyName))
{
string translatedName = MultiLanguageSystem.Translate(enemyName);
Render.Render.DrawNameESP(demon.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
}
} }
} }
// Spider (Inn)
foreach (Il2Cpp.SpiderBehaviour spider in Helpers.Entities.Spiders) foreach (Il2Cpp.SpiderBehaviour spider in Helpers.Entities.Spiders)
{ {
if (spider != null) if (spider != null && ESP.ItemESPConfig.ShouldShowESP("Spider"))
{ {
string translatedName = MultiLanguageSystem.Translate("Spider"); string translatedName = MultiLanguageSystem.Translate("Spider");
Render.Render.DrawNameESP(spider.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(spider.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// Ghost (Town)
foreach (Il2Cpp.GhostBehaviour ghost in Helpers.Entities.Ghosts) foreach (Il2Cpp.GhostBehaviour ghost in Helpers.Entities.Ghosts)
{ {
if (ghost != null) if (ghost != null && ESP.ItemESPConfig.ShouldShowESP("Ghost"))
{ {
string translatedName = MultiLanguageSystem.Translate("Ghost"); string translatedName = MultiLanguageSystem.Translate("Ghost");
Render.Render.DrawNameESP(ghost.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(ghost.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// Boar/Pig (Slaughterhouse)
foreach (Il2Cpp.BoarBehaviour boar in Helpers.Entities.Boars) foreach (Il2Cpp.BoarBehaviour boar in Helpers.Entities.Boars)
{ {
if (boar != null) if (boar != null && ESP.ItemESPConfig.ShouldShowESP("Boar"))
{ {
string translatedName = MultiLanguageSystem.Translate("Boar"); string translatedName = MultiLanguageSystem.Translate("Boar");
Render.Render.DrawNameESP(boar.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(boar.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// Corpse (Slaughterhouse)
foreach (Il2Cpp.CorpseBehaviour corpse in Helpers.Entities.Corpses) foreach (Il2Cpp.CorpseBehaviour corpse in Helpers.Entities.Corpses)
{ {
if (corpse != null) if (corpse != null && ESP.ItemESPConfig.ShouldShowESP("Corpse"))
{ {
string translatedName = MultiLanguageSystem.Translate("Corpse"); string translatedName = MultiLanguageSystem.Translate("Corpse");
Render.Render.DrawNameESP(corpse.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(corpse.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// Crow (Manor)
foreach (Il2Cpp.CrowBehaviour crow in Helpers.Entities.Crows) foreach (Il2Cpp.CrowBehaviour crow in Helpers.Entities.Crows)
{ {
if (crow != null) if (crow != null && ESP.ItemESPConfig.ShouldShowESP("Crow"))
{ {
string translatedName = MultiLanguageSystem.Translate("Crow"); string translatedName = MultiLanguageSystem.Translate("Crow");
Render.Render.DrawNameESP(crow.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(crow.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// Lump (Manor)
foreach (Il2Cpp.ManorLumpController lump in Helpers.Entities.Lumps) foreach (Il2Cpp.ManorLumpController lump in Helpers.Entities.Lumps)
{ {
if (lump != null) if (lump != null && ESP.ItemESPConfig.ShouldShowESP("Lump"))
{ {
string translatedName = MultiLanguageSystem.Translate("Lump"); string translatedName = MultiLanguageSystem.Translate("Lump");
Render.Render.DrawNameESP(lump.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(lump.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// DirtyHead (Manor)
foreach (Il2Cpp.GoatBehaviour dirtyHead in Helpers.Entities.DirtyHeads)
{
if (dirtyHead != null && ESP.ItemESPConfig.ShouldShowESP("DirtyHead"))
{
string translatedName = MultiLanguageSystem.Translate("DirtyHead");
Render.Render.DrawNameESP(dirtyHead.transform.position, translatedName, new Color(0.94f, 0.61f, 0.18f, 1.0f));
}
}
// Monkey (Carnival)
foreach (Il2Cpp.MonkeyBehaviour monkey in Helpers.Entities.Monkeys) foreach (Il2Cpp.MonkeyBehaviour monkey in Helpers.Entities.Monkeys)
{ {
if (monkey != null) if (monkey != null && ESP.ItemESPConfig.ShouldShowESP("Monkey"))
{ {
string translatedName = MultiLanguageSystem.Translate("Monkey"); string translatedName = MultiLanguageSystem.Translate("Monkey");
Render.Render.DrawNameESP(monkey.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f)); Render.Render.DrawNameESP(monkey.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
} }
} }
// Doll (Carnival)
foreach (Il2Cpp.GoatBehaviour doll in Helpers.Entities.Dolls)
{
if (doll != null)
{
string itemName = doll.name.Replace("Survival", "").Replace("(Clone)", "");
// Check if ESP should be shown for Doll
if (ESP.ItemESPConfig.ShouldShowESP(itemName))
{
string translatedName = MultiLanguageSystem.Translate(itemName);
Render.Render.DrawNameESP(doll.transform.position, translatedName, new Color(1.0f, 0.0f, 0.0f, 1.0f));
}
}
}
} }
if (azazel_esp || azazel_snapline || azazel_skel_esp) if (azazel_esp || azazel_snapline || azazel_skel_esp)
@@ -508,6 +578,11 @@ namespace DevourClient
current_tab = CurrentTab.Players; current_tab = CurrentTab.Players;
} }
if (GUILayout.Button(MultiLanguageSystem.Translate("Network"), GUILayout.Height(40)) || Input.GetKeyDown(KeyCode.F8))
{
current_tab = CurrentTab.Network;
}
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
switch (current_tab) switch (current_tab)
@@ -533,6 +608,9 @@ namespace DevourClient
case CurrentTab.Players: case CurrentTab.Players:
PlayersTab(); PlayersTab();
break; break;
case CurrentTab.Network:
NetworkTab();
break;
} }
@@ -726,11 +804,7 @@ namespace DevourClient
switch (Helpers.Map.GetActiveScene()) switch (Helpers.Map.GetActiveScene())
{ {
case "Menu": case "Menu":
if (GUI.Button(new Rect(Settings.Settings.x + 190, Settings.Settings.y + 70, 150, 30), MultiLanguageSystem.Translate("Force Start Game")) && BoltNetwork.IsServer && !Player.IsInGame()) // Force Start Game button removed - only available in Network tab
{
Il2CppHorror.Menu menu = UnityEngine.Object.FindObjectOfType<Il2CppHorror.Menu>();
menu.OnLobbyStartButtonClick();
}
break; break;
case "Devour": case "Devour":
@@ -1027,9 +1101,65 @@ namespace DevourClient
Settings.Settings.azazel_esp_color = azazel_esp_color_input; Settings.Settings.azazel_esp_color = azazel_esp_color_input;
} }
item_esp = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 330, 150, 20), item_esp, MultiLanguageSystem.Translate("Item ESP")); // ESP panel moved to the right, dynamically displayed based on map
goat_rat_esp = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 360, 150, 20), goat_rat_esp, MultiLanguageSystem.Translate("Goat/Rat ESP")); DrawESPPanel();
demon_esp = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 390, 150, 20), demon_esp, MultiLanguageSystem.Translate("Demon ESP")); }
/// <summary>
/// Draw dynamic ESP panel - display corresponding item types based on current map
/// </summary>
private static void DrawESPPanel()
{
string currentScene = Helpers.Map.GetActiveScene();
// Get ESP types supported by current map
List<ESP.ItemESPConfig.ESPType> espTypes = ESP.ItemESPConfig.GetMapESPTypes(currentScene);
// Don't display panel if in menu scene or no available ESP types
if (espTypes.Count == 0)
return;
// Right side panel position
float panelX = Settings.Settings.x + 370;
float panelY = Settings.Settings.y + 70;
float panelWidth = 180;
float itemHeight = 30;
float padding = 5;
// Draw title
GUI.Label(new Rect(panelX, panelY, panelWidth, 25),
MultiLanguageSystem.Translate("ESP Settings"),
GUI.skin.box);
// Draw ESP toggle list
float yOffset = panelY + 30;
foreach (var espType in espTypes)
{
string displayName = ESP.ItemESPConfig.GetESPTypeName(espType);
string translatedName = MultiLanguageSystem.Translate(displayName);
bool currentState = ESP.ItemESPConfig.GetESPState(espType);
bool newState = GUI.Toggle(
new Rect(panelX + padding, yOffset, panelWidth - padding * 2, itemHeight - padding),
currentState,
translatedName
);
if (newState != currentState)
{
ESP.ItemESPConfig.SetESPState(espType, newState);
}
yOffset += itemHeight;
}
// Display current map name (debug info)
string mapDisplayName = Helpers.Map.GetMapName(currentScene);
GUI.Label(
new Rect(panelX, yOffset + 10, panelWidth, 20),
$"Map: {mapDisplayName}",
new GUIStyle(GUI.skin.label) { fontSize = 10, alignment = TextAnchor.MiddleCenter }
);
} }
private static void ItemsTab() private static void ItemsTab()
@@ -1292,7 +1422,7 @@ namespace DevourClient
// Hacks.Misc.CarryObject("SurvivalCleanHead"); // Hacks.Misc.CarryObject("SurvivalCleanHead");
// } // }
// } // }
if (GUILayout.Button(MultiLanguageSystem.Translate("Doll Head"))) if (GUILayout.Button(MultiLanguageSystem.Translate("DollHead")))
{ {
if (BoltNetwork.IsServer && !Player.IsInGame()) if (BoltNetwork.IsServer && !Player.IsInGame())
{ {
@@ -1688,9 +1818,9 @@ namespace DevourClient
int i = 0; int i = 0;
foreach (BasePlayer bp in Entities.Players) foreach (BasePlayer bp in Entities.Players)
{ {
// Silently skip invalid player objects (avoid frequent log output)
if (bp == null || bp.Name == "") if (bp == null || bp.Name == "")
{ {
MelonLogger.Warning("players is null");
continue; continue;
} }
@@ -1706,7 +1836,7 @@ namespace DevourClient
bp.Revive(); bp.Revive();
} }
if (GUI.Button(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 105 + i, 90, 30), "Jumpscare")) if (GUI.Button(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 105 + i, 90, 30), MultiLanguageSystem.Translate("Jumpscare")))
{ {
bp.Jumpscare(); bp.Jumpscare();
} }
@@ -1716,19 +1846,19 @@ namespace DevourClient
bp.TP(); bp.TP();
} }
if (GUI.Button(new Rect(Settings.Settings.x + 380, Settings.Settings.y + 105 + i, 100, 30), "Lock in cage")) if (GUI.Button(new Rect(Settings.Settings.x + 380, Settings.Settings.y + 105 + i, 100, 30), MultiLanguageSystem.Translate("Lock in cage")))
{ {
bp.LockInCage(); bp.LockInCage();
} }
if (GUI.Button(new Rect(Settings.Settings.x + 490, Settings.Settings.y + 105 + i, 90, 30), "TP Azazel")) if (GUI.Button(new Rect(Settings.Settings.x + 490, Settings.Settings.y + 105 + i, 90, 30), MultiLanguageSystem.Translate("TP Azazel")))
{ {
bp.TPAzazel(); bp.TPAzazel();
} }
if (Helpers.Map.GetActiveScene() == "Town") if (Helpers.Map.GetActiveScene() == "Town")
{ {
if (GUI.Button(new Rect(Settings.Settings.x + 590, Settings.Settings.y + 105 + i, 90, 30), "Shoot Player")) if (GUI.Button(new Rect(Settings.Settings.x + 590, Settings.Settings.y + 105 + i, 90, 30), MultiLanguageSystem.Translate("Shoot Player")))
{ {
bp.ShootPlayer(); bp.ShootPlayer();
} }
@@ -1739,7 +1869,98 @@ namespace DevourClient
} }
else else
{ {
GUI.Label(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 70, 150, 30), "Waiting for the game to start."); GUI.Label(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 70, 300, 30), MultiLanguageSystem.Translate("Waiting for the game to start"));
}
}
private static void NetworkTab()
{
int yOffset = 70;
int xBase = (int)Settings.Settings.x + 10;
int yBase = (int)Settings.Settings.y;
// Network information display
GUI.Label(new Rect(xBase, yBase + yOffset, 300, 30),
MultiLanguageSystem.Translate("Network Info") + ": " + Network.NetworkHelper.GetRoomInfo());
yOffset += 40;
// Room management section
GUI.Label(new Rect(xBase, yBase + yOffset, 300, 30),
$"=== {MultiLanguageSystem.Translate("Lobby Manager")} ===");
yOffset += 35;
// Region selection - click to cycle through
GUI.Label(new Rect(xBase, yBase + yOffset, 100, 30),
MultiLanguageSystem.Translate("Region") + ":");
string[] regionDisplayNames = Network.RegionHelper.GetRegionDisplayNames();
// Click button to cycle through regions
if (GUI.Button(new Rect(xBase + 110, yBase + yOffset, 200, 30), regionDisplayNames[selectedRegion]))
{
selectedRegion = (selectedRegion + 1) % regionDisplayNames.Length;
}
yOffset += 40;
// Room player limit
GUI.Label(new Rect(xBase, yBase + yOffset, 100, 30),
MultiLanguageSystem.Translate("Lobby Size") + ":");
lobbySize = (int)GUI.HorizontalSlider(new Rect(xBase + 110, yBase + yOffset + 5, 120, 20), lobbySize, 1, 64);
GUI.Label(new Rect(xBase + 240, yBase + yOffset, 50, 30), lobbySize.ToString());
yOffset += 35;
// Private room option
isPrivateLobby = GUI.Toggle(new Rect(xBase, yBase + yOffset, 200, 30),
isPrivateLobby, MultiLanguageSystem.Translate("Private Lobby"));
yOffset += 35;
// Create room button
if (GUI.Button(new Rect(xBase, yBase + yOffset, 300, 40),
MultiLanguageSystem.Translate("Create Lobby")))
{
string regionCode = Network.RegionHelper.GetRegionCodeByIndex(selectedRegion);
Network.LobbyManager.CreateLobby(regionCode, lobbySize, isPrivateLobby);
}
yOffset += 50;
// Lobby control section
GUI.Label(new Rect(xBase, yBase + yOffset, 300, 30),
$"=== {MultiLanguageSystem.Translate("Lobby Control")} ===");
yOffset += 35;
// Force start button (host only)
bool isHost = Network.NetworkHelper.IsHost();
GUI.enabled = isHost;
if (GUI.Button(new Rect(xBase, yBase + yOffset, 300, 35),
MultiLanguageSystem.Translate("Force Start Game") + (isHost ? "" : " (" + MultiLanguageSystem.Translate("Host Only") + ")")))
{
Network.LobbyManager.ForceLobbyStart();
}
GUI.enabled = true;
yOffset += 45;
// Network statistics
if (Network.NetworkHelper.IsNetworkRunning())
{
yOffset += 10;
GUI.Label(new Rect(xBase, yBase + yOffset, 300, 30),
$"=== {MultiLanguageSystem.Translate("Network Stats")} ===");
yOffset += 35;
GUI.Label(new Rect(xBase, yBase + yOffset, 200, 30),
MultiLanguageSystem.Translate("Player Count") + ": " + Network.NetworkHelper.GetPlayerCount());
yOffset += 30;
if (!isHost)
{
GUI.Label(new Rect(xBase, yBase + yOffset, 200, 30),
"Ping: " + Network.NetworkHelper.GetPing() + "ms");
yOffset += 30;
}
GUI.Label(new Rect(xBase, yBase + yOffset, 200, 30),
MultiLanguageSystem.Translate("Connection ID") + ": " + Network.NetworkHelper.GetConnectionID());
} }
} }

View File

@@ -0,0 +1,654 @@
using System.Collections.Generic;
namespace DevourClient.ESP
{
/// <summary>
/// Item ESP configuration management class - dynamically display different item types based on map
/// </summary>
public static class ItemESPConfig
{
// ESP type enumeration
public enum ESPType
{
// Common items (all maps)
FirstAid, // First Aid
Battery, // Battery
Keys, // Keys
// Farmhouse (Anna) specific
Hay, // Hay
Gasoline, // Gasoline
// Asylum (Molly) specific
RottonFood, // Rotten Food
Fuse, // Fuse
// Inn specific
Bleach, // Bleach
Egg, // Egg
// Town specific
RitualBook, // Ritual Book
Matchbox, // Matchbox
// Gasoline (reused)
// Slaughterhouse specific
Bone, // Bone
// Gasoline (reused)
// Manor specific
// Bleach (reused)
Cake, // Cake
CleanHead, // Clean Head
Spade, // Spade
// Carnival specific
Coin, // Coin
MusicBox, // Music Box
DollHead, // Doll Head
// Enemy ESP - Farmhouse
Demon, // Demon
Goat, // Goat
// Enemy ESP - Asylum
Inmates, // Inmates
Rat, // Rat
// Enemy ESP - Inn
Spider, // Spider
// Enemy ESP - Town
Ghost, // Ghost
// Enemy ESP - Slaughterhouse
Corpse, // Corpse
Roar, // Roar
Pig, // Pig
// Enemy ESP - Manor
Crow, // Crow
DirtyHead, // Dirty Head
Lump, // Lump
// Enemy ESP - Carnival
Monkey, // Monkey
Doll // Doll
}
// ESP type configuration supported by each map
private static Dictionary<string, List<ESPType>> mapESPTypes = new Dictionary<string, List<ESPType>>()
{
// Anna - Farmhouse map
{ "Anna", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.Hay, // Specific: Hay
ESPType.Gasoline, // Specific: Gasoline
ESPType.Demon, // Enemy: Demon
ESPType.Goat // Enemy: Goat
}
},
// Molly - Asylum map
{ "Molly", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.RottonFood, // Specific: Rotten Food
ESPType.Fuse, // Specific: Fuse
ESPType.Inmates, // Enemy: Inmates
ESPType.Rat // Enemy: Rat
}
},
// Inn map
{ "Inn", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.Bleach, // Specific: Bleach
ESPType.Egg, // Specific: Egg
ESPType.Spider // Enemy: Spider
}
},
// Town map
{ "Town", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.RitualBook, // Specific: Ritual Book
ESPType.Matchbox, // Specific: Matchbox
ESPType.Gasoline, // Specific: Gasoline
ESPType.Ghost // Enemy: Ghost
}
},
// Slaughterhouse map
{ "Slaughterhouse", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.Bone, // Specific: Bone
ESPType.Gasoline, // Specific: Gasoline
ESPType.Corpse, // Enemy: Corpse
ESPType.Roar, // Enemy: Roar
ESPType.Pig // Enemy: Pig
}
},
// Manor map
{ "Manor", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.Bleach, // Specific: Bleach
ESPType.Cake, // Specific: Cake
ESPType.CleanHead, // Specific: Clean Head
ESPType.Spade, // Specific: Spade
ESPType.Crow, // Enemy: Crow
ESPType.DirtyHead, // Enemy: Dirty Head
ESPType.Lump // Enemy: Lump
}
},
// Carnival map
{ "Carnival", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.Coin, // Specific: Coin
ESPType.MusicBox, // Specific: Music Box
ESPType.DollHead, // Specific: Doll Head
ESPType.Monkey, // Enemy: Monkey
ESPType.Doll // Enemy: Doll
}
},
// Devour - default map (same as Farmhouse)
{ "Devour", new List<ESPType>
{
ESPType.FirstAid, // Common: First Aid
ESPType.Battery, // Common: Battery
ESPType.Keys, // Common: Keys
ESPType.Hay, // Specific: Hay
ESPType.Gasoline, // Specific: Gasoline
ESPType.Demon, // Enemy: Demon
ESPType.Goat // Enemy: Goat
}
}
};
// ESP enable status
private static Dictionary<ESPType, bool> espStates = new Dictionary<ESPType, bool>()
{
// Common items
{ ESPType.FirstAid, false },
{ ESPType.Battery, false },
{ ESPType.Keys, false },
// Farmhouse specific
{ ESPType.Hay, false },
{ ESPType.Gasoline, false },
// Asylum specific
{ ESPType.RottonFood, false },
{ ESPType.Fuse, false },
// Inn specific
{ ESPType.Bleach, false },
{ ESPType.Egg, false },
// Town specific
{ ESPType.RitualBook, false },
{ ESPType.Matchbox, false },
// Slaughterhouse specific
{ ESPType.Bone, false },
// Manor specific
{ ESPType.Cake, false },
{ ESPType.CleanHead, false },
{ ESPType.Spade, false },
// Carnival specific
{ ESPType.Coin, false },
{ ESPType.MusicBox, false },
{ ESPType.DollHead, false },
// Enemy - Farmhouse
{ ESPType.Demon, false },
{ ESPType.Goat, false },
// Enemy - Asylum
{ ESPType.Inmates, false },
{ ESPType.Rat, false },
// Enemy - Inn
{ ESPType.Spider, false },
// Enemy - Town
{ ESPType.Ghost, false },
// Enemy - Slaughterhouse
{ ESPType.Corpse, false },
{ ESPType.Roar, false },
{ ESPType.Pig, false },
// Enemy - Manor
{ ESPType.Crow, false },
{ ESPType.DirtyHead, false },
{ ESPType.Lump, false },
// Enemy - Carnival
{ ESPType.Monkey, false },
{ ESPType.Doll, false }
};
/// <summary>
/// Get list of ESP types supported by specified map
/// </summary>
public static List<ESPType> GetMapESPTypes(string sceneName)
{
// If in menu, return empty list
if (sceneName == "Menu")
return new List<ESPType>();
// If map is in configuration, return corresponding configuration
if (mapESPTypes.ContainsKey(sceneName))
return mapESPTypes[sceneName];
// Default return basic configuration (common items + Farmhouse enemies)
return new List<ESPType>
{
ESPType.FirstAid,
ESPType.Battery,
ESPType.Keys,
ESPType.Demon,
ESPType.Goat
};
}
/// <summary>
/// Get ESP type enable status
/// </summary>
public static bool GetESPState(ESPType type)
{
return espStates.ContainsKey(type) ? espStates[type] : false;
}
/// <summary>
/// Set ESP type enable status
/// </summary>
public static void SetESPState(ESPType type, bool enabled)
{
if (espStates.ContainsKey(type))
espStates[type] = enabled;
}
/// <summary>
/// Toggle ESP type enable status
/// </summary>
public static void ToggleESPState(ESPType type)
{
if (espStates.ContainsKey(type))
espStates[type] = !espStates[type];
}
/// <summary>
/// Get ESP type display name (for translation key)
/// </summary>
public static string GetESPTypeName(ESPType type)
{
switch (type)
{
// Common items
case ESPType.FirstAid:
return "First Aid ESP";
case ESPType.Battery:
return "Battery ESP";
case ESPType.Keys:
return "Key ESP";
// Farmhouse specific
case ESPType.Hay:
return "Hay ESP";
case ESPType.Gasoline:
return "Gasoline ESP";
// Asylum specific
case ESPType.RottonFood:
return "Rotton Food ESP";
case ESPType.Fuse:
return "Fuse ESP";
// Inn specific
case ESPType.Bleach:
return "Bleach ESP";
case ESPType.Egg:
return "Egg ESP";
// Town specific
case ESPType.RitualBook:
return "Ritual Book ESP";
case ESPType.Matchbox:
return "Matchbox ESP";
// Slaughterhouse specific
case ESPType.Bone:
return "Bone ESP";
// Manor specific
case ESPType.Cake:
return "Cake ESP";
case ESPType.CleanHead:
return "Clean Head ESP";
case ESPType.Spade:
return "Spade ESP";
// Carnival specific
case ESPType.Coin:
return "Coin ESP";
case ESPType.MusicBox:
return "Music Box ESP";
case ESPType.DollHead:
return "Doll Head ESP";
// Enemy - Farmhouse
case ESPType.Demon:
return "Demon ESP";
case ESPType.Goat:
return "Goat ESP";
// Enemy - Asylum
case ESPType.Inmates:
return "Inmates ESP";
case ESPType.Rat:
return "Rat ESP";
// Enemy - Inn
case ESPType.Spider:
return "Spider ESP";
// Enemy - Town
case ESPType.Ghost:
return "Ghost ESP";
// Enemy - Slaughterhouse
case ESPType.Corpse:
return "Corpse ESP";
case ESPType.Roar:
return "Roar ESP";
case ESPType.Pig:
return "Pig ESP";
// Enemy - Manor
case ESPType.Crow:
return "Crow ESP";
case ESPType.DirtyHead:
return "Dirty Head ESP";
case ESPType.Lump:
return "Lump ESP";
// Enemy - Carnival
case ESPType.Monkey:
return "Monkey ESP";
case ESPType.Doll:
return "Doll ESP";
default:
return type.ToString();
}
}
/// <summary>
/// Get corresponding ESP type based on item name
/// </summary>
public static ESPType? GetESPTypeByItemName(string itemName)
{
// Remove "Survival" and "(Clone)" prefix/suffix
itemName = itemName.Replace("Survival", "").Replace("(Clone)", "").Trim();
// Match item name to ESP type
switch (itemName.ToLower())
{
// Common items
case "firstaidcontainer":
case "first aid":
case "firstaid":
return ESPType.FirstAid;
case "batterypickup":
case "battery":
return ESPType.Battery;
case "keybehaviour":
case "key":
return ESPType.Keys;
// Farmhouse specific
case "haypickup":
case "hay":
return ESPType.Hay;
case "gasolinepickup":
case "gasoline":
case "gas":
return ESPType.Gasoline;
// Asylum specific
case "rottonfoodpickup":
case "rotton food":
case "rottonfood":
return ESPType.RottonFood;
case "fusepickup":
case "fuse":
return ESPType.Fuse;
// Inn specific
case "bleachpickup":
case "bleach":
return ESPType.Bleach;
case "eggpickup":
case "egg":
return ESPType.Egg;
// Town specific
case "ritualbookpickup":
case "ritual book":
case "ritualbook":
return ESPType.RitualBook;
case "matchboxpickup":
case "matchbox":
return ESPType.Matchbox;
// Slaughterhouse specific
case "bonepickup":
case "bone":
return ESPType.Bone;
// Manor specific
case "cakepickup":
case "cake":
return ESPType.Cake;
case "cleanheadpickup":
case "clean head":
case "cleanhead":
return ESPType.CleanHead;
case "spadepickup":
case "spade":
return ESPType.Spade;
// Carnival specific
case "coinpickup":
case "coin":
return ESPType.Coin;
case "musicboxpickup":
case "musicbox-idle":
return ESPType.MusicBox;
case "dollheadpickup":
case "doll head":
case "dollhead":
return ESPType.DollHead;
// Enemy - Farmhouse
case "demon":
case "demonbehaviour":
return ESPType.Demon;
case "goat":
case "goatbehaviour":
return ESPType.Goat;
// Enemy - Asylum
case "inmates":
case "inmate":
case "inmatebehaviour":
return ESPType.Inmates;
case "rat":
case "ratbehaviour":
return ESPType.Rat;
// Enemy - Inn
case "spider":
case "spiderbehaviour":
return ESPType.Spider;
// Enemy - Town
case "ghost":
case "ghostbehaviour":
return ESPType.Ghost;
// Enemy - Slaughterhouse
case "corpse":
case "corpsebehaviour":
return ESPType.Corpse;
case "roar":
case "roarbehaviour":
return ESPType.Roar;
case "pig":
case "boar":
case "boarbehaviour":
case "pigbehaviour":
return ESPType.Pig;
// Enemy - Manor
case "crow":
case "crowbehaviour":
return ESPType.Crow;
case "dirty head":
case "dirtyhead":
case "dirtyheadbehaviour":
return ESPType.DirtyHead;
case "lump":
case "lumpcontroller":
case "manorlumpcontroller":
return ESPType.Lump;
// Enemy - Carnival
case "monkey":
case "monkeybehaviour":
return ESPType.Monkey;
case "doll":
case "dollbehaviour":
return ESPType.Doll;
default:
return null; // Unknown item type
}
}
/// <summary>
/// Check if ESP should be shown for specified item
/// </summary>
public static bool ShouldShowESP(string itemName)
{
ESPType? espType = GetESPTypeByItemName(itemName);
if (espType == null)
return false;
return GetESPState(espType.Value);
}
/// <summary>
/// Reset all ESP states
/// </summary>
public static void ResetAllStates()
{
var keys = new List<ESPType>(espStates.Keys);
foreach (var key in keys)
{
espStates[key] = false;
}
}
// Properties for backward compatibility - return whether any related ESP is enabled
public static bool ItemESP
{
get => GetESPState(ESPType.FirstAid) ||
GetESPState(ESPType.Battery) ||
GetESPState(ESPType.Keys) ||
GetESPState(ESPType.Hay) ||
GetESPState(ESPType.Gasoline) ||
GetESPState(ESPType.RottonFood) ||
GetESPState(ESPType.Fuse) ||
GetESPState(ESPType.Bleach) ||
GetESPState(ESPType.Egg) ||
GetESPState(ESPType.RitualBook) ||
GetESPState(ESPType.Matchbox) ||
GetESPState(ESPType.Bone) ||
GetESPState(ESPType.Cake) ||
GetESPState(ESPType.CleanHead) ||
GetESPState(ESPType.Spade) ||
GetESPState(ESPType.Coin) ||
GetESPState(ESPType.MusicBox) ||
GetESPState(ESPType.DollHead);
}
public static bool GoatRatESP
{
get => GetESPState(ESPType.Goat) || GetESPState(ESPType.Rat);
}
public static bool DemonESP
{
get => GetESPState(ESPType.Demon) ||
GetESPState(ESPType.Goat) ||
GetESPState(ESPType.Inmates) ||
GetESPState(ESPType.Rat) ||
GetESPState(ESPType.Spider) ||
GetESPState(ESPType.Ghost) ||
GetESPState(ESPType.Corpse) ||
GetESPState(ESPType.Roar) ||
GetESPState(ESPType.Pig) ||
GetESPState(ESPType.Crow) ||
GetESPState(ESPType.DirtyHead) ||
GetESPState(ESPType.Lump) ||
GetESPState(ESPType.Monkey) ||
GetESPState(ESPType.Doll);
}
}
}

View File

@@ -91,11 +91,12 @@ namespace DevourClient.Hacks
if (burnAll) if (burnAll)
{ {
_slaughterhouseAltarController.BurnGoat();
_slaughterhouseAltarController.SkipToGoat(10);
} }
else else
{ {
_slaughterhouseAltarController.SkipToGoat(10); _slaughterhouseAltarController.BurnGoat();
} }
break; break;

View File

@@ -190,9 +190,11 @@ namespace DevourClient.Helpers
public static Il2Cpp.CorpseBehaviour[] Corpses = default!; public static Il2Cpp.CorpseBehaviour[] Corpses = default!;
public static Il2Cpp.CrowBehaviour[] Crows = default!; public static Il2Cpp.CrowBehaviour[] Crows = default!;
public static Il2Cpp.ManorLumpController[] Lumps = default!; public static Il2Cpp.ManorLumpController[] Lumps = default!;
public static Il2Cpp.GoatBehaviour[] DirtyHeads = default!;
public static Il2Cpp.MonkeyBehaviour[] Monkeys = default!; public static Il2Cpp.MonkeyBehaviour[] Monkeys = default!;
public static Il2Cpp.GoatBehaviour[] Dolls = default!;
// 协程生命周期管理 // Coroutine lifecycle management
private static List<object> activeCoroutines = new List<object>(); private static List<object> activeCoroutines = new List<object>();
private static bool isRunning = false; private static bool isRunning = false;
@@ -363,6 +365,17 @@ namespace DevourClient.Helpers
} }
} }
public static IEnumerator GetDirtyHeads()
{
while (isRunning)
{
DirtyHeads = Il2Cpp.GoatBehaviour.FindObjectsOfType<Il2Cpp.GoatBehaviour>();
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f);
}
}
public static IEnumerator GetMonkeys() public static IEnumerator GetMonkeys()
{ {
while (isRunning) while (isRunning)
@@ -374,6 +387,17 @@ namespace DevourClient.Helpers
} }
} }
public static IEnumerator GetDolls()
{
while (isRunning)
{
Dolls = Il2Cpp.GoatBehaviour.FindObjectsOfType<Il2Cpp.GoatBehaviour>();
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f);
}
}
public static IEnumerator GetAzazels() public static IEnumerator GetAzazels()
{ {
while (isRunning) while (isRunning)
@@ -443,7 +467,9 @@ namespace DevourClient.Helpers
Corpses = null; Corpses = null;
Crows = null; Crows = null;
Lumps = null; Lumps = null;
DirtyHeads = null;
Monkeys = null; Monkeys = null;
Dolls = null;
if (LocalPlayer_ != null) if (LocalPlayer_ != null)
{ {

View File

@@ -108,9 +108,9 @@ namespace DevourClient.Localization
cn: "硬币", fr: "Pièce", de: "Münze", es: "Moneda", cn: "硬币", fr: "Pièce", de: "Münze", es: "Moneda",
ja: "コイン", ko: "동전", ru: "Монета", pt: "Moeda", it: "Moneta"); ja: "コイン", ko: "동전", ru: "Монета", pt: "Moeda", it: "Moneta");
// 仪式物品 // Ritual items
AddTranslation("Egg", AddTranslation("Egg",
cn: "蛋", fr: "Œuf", de: "Ei", es: "Huevo", cn: "蛋", fr: "Œuf", de: "Ei", es: "Huevo",
ja: "卵", ko: "달걀", ru: "Яйцо", pt: "Ovo", it: "Uovo"); ja: "卵", ko: "달걀", ru: "Яйцо", pt: "Ovo", it: "Uovo");
for (int i = 1; i <= 10; i++) for (int i = 1; i <= 10; i++)
@@ -144,6 +144,10 @@ namespace DevourClient.Localization
cn: "老鼠", fr: "Rat", de: "Ratte", es: "Rata", cn: "老鼠", fr: "Rat", de: "Ratte", es: "Rata",
ja: "ネズミ", ko: "쥐", ru: "Крыса", pt: "Rato", it: "Ratto"); ja: "ネズミ", ko: "쥐", ru: "Крыса", pt: "Rato", it: "Ratto");
AddTranslation("Doll",
cn: "玩偶", fr: "Poupée", de: "Puppe", es: "Muñeca",
ja: "人形", ko: "인형", ru: "Кукла", pt: "Boneca", it: "Bambola");
AddTranslation("Pig", AddTranslation("Pig",
cn: "猪", fr: "Cochon", de: "Schwein", es: "Cerdo", cn: "猪", fr: "Cochon", de: "Schwein", es: "Cerdo",
ja: "豚", ko: "돼지", ru: "Свинья", pt: "Porco", it: "Maiale"); ja: "豚", ko: "돼지", ru: "Свинья", pt: "Porco", it: "Maiale");
@@ -180,6 +184,10 @@ namespace DevourClient.Localization
cn: "肿块", fr: "Masse", de: "Klumpen", es: "Bulto", cn: "肿块", fr: "Masse", de: "Klumpen", es: "Bulto",
ja: "塊", ko: "덩어리", ru: "Комок", pt: "Caroço", it: "Grumo"); ja: "塊", ko: "덩어리", ru: "Комок", pt: "Caroço", it: "Grumo");
AddTranslation("DirtyHead",
cn: "污秽头颅", fr: "Tête sale", de: "Schmutziger Kopf", es: "Cabeza sucia",
ja: "汚れた頭", ko: "더러운 머리", ru: "Грязная голова", pt: "Cabeça suja", it: "Testa sporca");
AddTranslation("Monkey", AddTranslation("Monkey",
cn: "猴子", fr: "Singe", de: "Affe", es: "Mono", cn: "猴子", fr: "Singe", de: "Affe", es: "Mono",
ja: "猿", ko: "원숭이", ru: "Обезьяна", pt: "Macaco", it: "Scimmia"); ja: "猿", ko: "원숭이", ru: "Обезьяна", pt: "Macaco", it: "Scimmia");
@@ -444,6 +452,144 @@ namespace DevourClient.Localization
cn: "恶魔透视", fr: "ESP démon", de: "Dämon ESP", es: "ESP demonio", cn: "恶魔透视", fr: "ESP démon", de: "Dämon ESP", es: "ESP demonio",
ja: "悪魔ESP", ko: "악마 ESP", ru: "ESP демона", pt: "ESP demônio", it: "ESP demone"); ja: "悪魔ESP", ko: "악마 ESP", ru: "ESP демона", pt: "ESP demônio", it: "ESP demone");
// ESP type name translations
AddTranslation("First Aid ESP",
cn: "急救包透视", fr: "ESP premiers soins", de: "Erste-Hilfe-ESP", es: "ESP primeros auxilios",
ja: "救急箱ESP", ko: "응급처치 ESP", ru: "ESP аптечки", pt: "ESP primeiros socorros", it: "ESP pronto soccorso");
AddTranslation("Battery ESP",
cn: "电池透视", fr: "ESP batterie", de: "Batterie-ESP", es: "ESP batería",
ja: "バッテリーESP", ko: "배터리 ESP", ru: "ESP батареи", pt: "ESP bateria", it: "ESP batteria");
AddTranslation("Key ESP",
cn: "钥匙透视", fr: "ESP clé", de: "Schlüssel ESP", es: "ESP llave",
ja: "鍵ESP", ko: "열쇠 ESP", ru: "ESP ключа", pt: "ESP chave", it: "ESP chiave");
AddTranslation("Spider ESP",
cn: "蜘蛛透视", fr: "ESP araignée", de: "Spinne ESP", es: "ESP araña",
ja: "蜘蛛ESP", ko: "거미 ESP", ru: "ESP паука", pt: "ESP aranha", it: "ESP ragno");
AddTranslation("Ritual Object ESP",
cn: "仪式物品透视", fr: "ESP objet rituel", de: "Ritualobjekt ESP", es: "ESP objeto ritual",
ja: "儀式オブジェクトESP", ko: "의식 물체 ESP", ru: "ESP ритуального предмета", pt: "ESP objeto ritual", it: "ESP oggetto rituale");
AddTranslation("Medicine ESP",
cn: "药品透视", fr: "ESP médicament", de: "Medizin ESP", es: "ESP medicina",
ja: "薬ESP", ko: "약품 ESP", ru: "ESP лекарства", pt: "ESP remédio", it: "ESP medicina");
AddTranslation("Egg ESP",
cn: "鸡蛋透视", fr: "ESP œuf", de: "Ei ESP", es: "ESP huevo",
ja: "卵ESP", ko: "계란 ESP", ru: "ESP яйца", pt: "ESP ovo", it: "ESP uovo");
// Add translations for all ESP types
AddTranslation("Hay ESP",
cn: "干草透视", fr: "ESP foin", de: "Heu-ESP", es: "ESP heno",
ja: "干し草ESP", ko: "건초 ESP", ru: "ESP сена", pt: "ESP feno", it: "ESP fieno");
AddTranslation("Gasoline ESP",
cn: "汽油透视", fr: "ESP essence", de: "Benzin-ESP", es: "ESP gasolina",
ja: "ガソリンESP", ko: "휘발유 ESP", ru: "ESP бензина", pt: "ESP gasolina", it: "ESP benzina");
AddTranslation("Rotton Food ESP",
cn: "腐烂食物透视", fr: "ESP nourriture pourrie", de: "Verdorbenes-Essen-ESP", es: "ESP comida podrida",
ja: "腐った食べ物ESP", ko: "썩은 음식 ESP", ru: "ESP гнилой еды", pt: "ESP comida podre", it: "ESP cibo marcio");
AddTranslation("Fuse ESP",
cn: "保险丝透视", fr: "ESP fusible", de: "Sicherung-ESP", es: "ESP fusible",
ja: "ヒューズESP", ko: "퓨즈 ESP", ru: "ESP предохранителя", pt: "ESP fusível", it: "ESP fusibile");
AddTranslation("Bleach ESP",
cn: "漂白剂透视", fr: "ESP eau de javel", de: "Bleichmittel-ESP", es: "ESP lejía",
ja: "漂白剤ESP", ko: "표백제 ESP", ru: "ESP отбеливателя", pt: "ESP alvejante", it: "ESP candeggina");
AddTranslation("Ritual Book ESP",
cn: "仪式书透视", fr: "ESP livre rituel", de: "Ritualbuch-ESP", es: "ESP libro ritual",
ja: "儀式の本ESP", ko: "의식서 ESP", ru: "ESP ритуальной книги", pt: "ESP livro ritual", it: "ESP libro rituale");
AddTranslation("Matchbox ESP",
cn: "火柴盒透视", fr: "ESP boîte d'allumettes", de: "Streichholzschachtel-ESP", es: "ESP caja de cerillas",
ja: "マッチ箱ESP", ko: "성냥갑 ESP", ru: "ESP спичек", pt: "ESP caixa de fósforos", it: "ESP scatola di fiammiferi");
AddTranslation("Bone ESP",
cn: "骨头透视", fr: "ESP os", de: "Knochen-ESP", es: "ESP hueso",
ja: "骨ESP", ko: "뼈 ESP", ru: "ESP кости", pt: "ESP osso", it: "ESP osso");
AddTranslation("Cake ESP",
cn: "蛋糕透视", fr: "ESP gâteau", de: "Kuchen-ESP", es: "ESP pastel",
ja: "ケーキESP", ko: "케이크 ESP", ru: "ESP торта", pt: "ESP bolo", it: "ESP torta");
AddTranslation("Clean Head ESP",
cn: "清洁头颅透视", fr: "ESP tête propre", de: "Sauberer-Kopf-ESP", es: "ESP cabeza limpia",
ja: "きれいな頭ESP", ko: "깨끗한 머리 ESP", ru: "ESP чистой головы", pt: "ESP cabeça limpa", it: "ESP testa pulita");
AddTranslation("Spade ESP",
cn: "铲子透视", fr: "ESP pelle", de: "Spaten-ESP", es: "ESP pala",
ja: "シャベルESP", ko: "삽 ESP", ru: "ESP лопаты", pt: "ESP pá", it: "ESP vanga");
AddTranslation("Coin ESP",
cn: "硬币透视", fr: "ESP pièce", de: "Münze-ESP", es: "ESP moneda",
ja: "コインESP", ko: "동전 ESP", ru: "ESP монеты", pt: "ESP moeda", it: "ESP moneta");
AddTranslation("Music Box ESP",
cn: "音乐盒透视", fr: "ESP boîte à musique", de: "Spieluhr-ESP", es: "ESP caja de música",
ja: "オルゴールESP", ko: "오르골 ESP", ru: "ESP музыкальной шкатулки", pt: "ESP caixa de música", it: "ESP carillon");
AddTranslation("Doll Head ESP",
cn: "娃娃头透视", fr: "ESP tête de poupée", de: "Puppenkopf-ESP", es: "ESP cabeza de muñeca",
ja: "人形の頭ESP", ko: "인형 머리 ESP", ru: "ESP головы куклы", pt: "ESP cabeça de boneca", it: "ESP testa di bambola");
AddTranslation("Goat ESP",
cn: "山羊透视", fr: "ESP chèvre", de: "Ziege-ESP", es: "ESP cabra",
ja: "ヤギESP", ko: "염소 ESP", ru: "ESP козы", pt: "ESP cabra", it: "ESP capra");
AddTranslation("Inmates ESP",
cn: "囚犯透视", fr: "ESP détenus", de: "Häftling-ESP", es: "ESP reclusos",
ja: "囚人ESP", ko: "수감자 ESP", ru: "ESP заключенных", pt: "ESP detentos", it: "ESP detenuti");
AddTranslation("Rat ESP",
cn: "老鼠透视", fr: "ESP rat", de: "Ratte-ESP", es: "ESP rata",
ja: "ネズミESP", ko: "쥐 ESP", ru: "ESP крысы", pt: "ESP rato", it: "ESP ratto");
AddTranslation("Ghost ESP",
cn: "幽灵透视", fr: "ESP fantôme", de: "Geist-ESP", es: "ESP fantasma",
ja: "ゴーストESP", ko: "유령 ESP", ru: "ESP призрака", pt: "ESP fantasma", it: "ESP fantasma");
AddTranslation("Corpse ESP",
cn: "尸体透视", fr: "ESP cadavre", de: "Leiche-ESP", es: "ESP cadáver",
ja: "死体ESP", ko: "시체 ESP", ru: "ESP трупа", pt: "ESP cadáver", it: "ESP cadavere");
AddTranslation("Roar ESP",
cn: "咆哮者透视", fr: "ESP rugissement", de: "Brüllen-ESP", es: "ESP rugido",
ja: "咆哮ESP", ko: "으르렁 ESP", ru: "ESP рёва", pt: "ESP rugido", it: "ESP ruggito");
AddTranslation("Pig ESP",
cn: "猪透视", fr: "ESP cochon", de: "Schwein-ESP", es: "ESP cerdo",
ja: "豚ESP", ko: "돼지 ESP", ru: "ESP свиньи", pt: "ESP porco", it: "ESP maiale");
AddTranslation("Crow ESP",
cn: "乌鸦透视", fr: "ESP corbeau", de: "Krähe-ESP", es: "ESP cuervo",
ja: "カラスESP", ko: "까마귀 ESP", ru: "ESP вороны", pt: "ESP corvo", it: "ESP corvo");
AddTranslation("Dirty Head ESP",
cn: "污秽头颅透视", fr: "ESP tête sale", de: "Schmutziger-Kopf-ESP", es: "ESP cabeza sucia",
ja: "汚れた頭ESP", ko: "더러운 머리 ESP", ru: "ESP грязной головы", pt: "ESP cabeça suja", it: "ESP testa sporca");
AddTranslation("Lump ESP",
cn: "肿块透视", fr: "ESP masse", de: "Klumpen-ESP", es: "ESP bulto",
ja: "塊ESP", ko: "덩어리 ESP", ru: "ESP комка", pt: "ESP caroço", it: "ESP grumo");
AddTranslation("Monkey ESP",
cn: "猴子透视", fr: "ESP singe", de: "Affe-ESP", es: "ESP mono",
ja: "サルESP", ko: "원숭이 ESP", ru: "ESP обезьяны", pt: "ESP macaco", it: "ESP scimmia");
AddTranslation("Doll ESP",
cn: "玩偶透视", fr: "ESP poupée", de: "Puppe-ESP", es: "ESP muñeca",
ja: "人形ESP", ko: "인형 ESP", ru: "ESP куклы", pt: "ESP boneca", it: "ESP bambola");
AddTranslation("ESP Settings",
cn: "透视设置", fr: "Paramètres ESP", de: "ESP-Einstellungen", es: "Configuración ESP",
ja: "ESP設定", ko: "ESP 설정", ru: "Настройки ESP", pt: "Configurações ESP", it: "Impostazioni ESP");
AddTranslation("Unlimited Stamina", AddTranslation("Unlimited Stamina",
cn: "无限耐力", fr: "Endurance illimitée", de: "Unbegrenzte Ausdauer", es: "Resistencia ilimitada", cn: "无限耐力", fr: "Endurance illimitée", de: "Unbegrenzte Ausdauer", es: "Resistencia ilimitada",
ja: "無限スタミナ", ko: "무제한 스태미나", ru: "Безлимитная выносливость", pt: "Resistência ilimitada", it: "Resistenza illimitata"); ja: "無限スタミナ", ko: "무제한 스태미나", ru: "Безлимитная выносливость", pt: "Resistência ilimitada", it: "Resistenza illimitata");
@@ -521,8 +667,8 @@ namespace DevourClient.Localization
ja: "プレイヤー", ko: "플레이어", ru: "Игроки", pt: "Jogadores", it: "Giocatori"); ja: "プレイヤー", ko: "플레이어", ru: "Игроки", pt: "Jogadores", it: "Giocatori");
AddTranslation("Teleport to", AddTranslation("Teleport to",
cn: "传送", fr: "Téléporter vers", de: "Teleportieren zu", es: "Teletransportar a", cn: "传送", fr: "Téléporter", de: "Teleportieren", es: "Teletransportar",
ja: "テレポート", ko: "텔레포트", ru: "Телепорт к", pt: "Teletransportar para", it: "Teletrasporta a"); ja: "テレポート", ko: "텔레포트", ru: "Телепорт", pt: "Teletransportar", it: "Teletrasporta");
AddTranslation("Kill", AddTranslation("Kill",
cn: "击杀", fr: "Tuer", de: "Töten", es: "Matar", cn: "击杀", fr: "Tuer", de: "Töten", es: "Matar",
@@ -531,6 +677,26 @@ namespace DevourClient.Localization
AddTranslation("Revive", AddTranslation("Revive",
cn: "复活", fr: "Réanimer", de: "Wiederbeleben", es: "Revivir", cn: "复活", fr: "Réanimer", de: "Wiederbeleben", es: "Revivir",
ja: "蘇生", ko: "부활", ru: "Воскресить", pt: "Reviver", it: "Rianima"); ja: "蘇生", ko: "부활", ru: "Воскресить", pt: "Reviver", it: "Rianima");
AddTranslation("Jumpscare",
cn: "跳吓", fr: "Jumpscare", de: "Jumpscare", es: "Susto",
ja: "ジャンプスケア", ko: "점프스케어", ru: "Пугать", pt: "Susto", it: "Spavento");
AddTranslation("Lock in cage",
cn: "锁在笼子里", fr: "Enfermer en cage", de: "In Käfig sperren", es: "Encerrar en jaula",
ja: "檻に閉じ込める", ko: "우리에 가두기", ru: "Запереть в клетке", pt: "Trancar na gaiola", it: "Rinchiudi in gabbia");
AddTranslation("TP Azazel",
cn: "传送恶魔", fr: "TP Azazel", de: "TP Azazel", es: "TP Azazel",
ja: "Azazel TP", ko: "Azazel TP", ru: "ТП Azazel", pt: "TP Azazel", it: "TP Azazel");
AddTranslation("Shoot Player",
cn: "射击玩家", fr: "Tirer sur le joueur", de: "Spieler erschießen", es: "Disparar al jugador",
ja: "プレイヤーを撃つ", ko: "플레이어 쏘기", ru: "Стрелять в игрока", pt: "Atirar no jogador", it: "Spara al giocatore");
AddTranslation("Waiting for the game to start",
cn: "等待游戏开始", fr: "En attente du démarrage", de: "Warte auf Spielstart", es: "Esperando inicio del juego",
ja: "ゲーム開始を待っています", ko: "게임 시작 대기 중", ru: "Ожидание начала игры", pt: "Aguardando início do jogo", it: "In attesa dell'inizio del gioco");
AddTranslation("Visuals", AddTranslation("Visuals",
cn: "视觉", fr: "Visuels", de: "Visuals", es: "Visuales", cn: "视觉", fr: "Visuels", de: "Visuals", es: "Visuales",
@@ -555,6 +721,62 @@ namespace DevourClient.Localization
AddTranslation("Misc", AddTranslation("Misc",
cn: "杂项", fr: "Divers", de: "Sonstiges", es: "Varios", cn: "杂项", fr: "Divers", de: "Sonstiges", es: "Varios",
ja: "その他", ko: "기타", ru: "Разное", pt: "Diversos", it: "Varie"); ja: "その他", ko: "기타", ru: "Разное", pt: "Diversos", it: "Varie");
AddTranslation("Network",
cn: "网络", fr: "Réseau", de: "Netzwerk", es: "Red",
ja: "ネットワーク", ko: "네트워크", ru: "Сеть", pt: "Rede", it: "Rete");
AddTranslation("Network Info",
cn: "网络信息", fr: "Infos réseau", de: "Netzwerk-Info", es: "Info de red",
ja: "ネットワーク情報", ko: "네트워크 정보", ru: "Сетевая информация", pt: "Info de rede", it: "Info rete");
AddTranslation("Lobby Manager",
cn: "房间管理", fr: "Gestionnaire de lobby", de: "Lobby-Verwaltung", es: "Gestor de lobby",
ja: "ロビー管理", ko: "로비 관리자", ru: "Менеджер лобби", pt: "Gerenciador de lobby", it: "Gestore lobby");
AddTranslation("Region",
cn: "区域", fr: "Région", de: "Region", es: "Región",
ja: "地域", ko: "지역", ru: "Регион", pt: "Região", it: "Regione");
AddTranslation("Lobby Size",
cn: "房间人数", fr: "Taille du lobby", de: "Lobby-Größe", es: "Tamaño del lobby",
ja: "ロビーサイズ", ko: "로비 크기", ru: "Размер лобби", pt: "Tamanho do lobby", it: "Dimensione lobby");
AddTranslation("Private Lobby",
cn: "私人房间", fr: "Lobby privé", de: "Privates Lobby", es: "Lobby privado",
ja: "プライベートロビー", ko: "비공개 로비", ru: "Приватное лобби", pt: "Lobby privado", it: "Lobby privata");
AddTranslation("Create Lobby",
cn: "创建房间", fr: "Créer un lobby", de: "Lobby erstellen", es: "Crear lobby",
ja: "ロビーを作成", ko: "로비 생성", ru: "Создать лобби", pt: "Criar lobby", it: "Crea lobby");
AddTranslation("Lobby Control",
cn: "房间控制", fr: "Contrôle du lobby", de: "Lobby-Steuerung", es: "Control del lobby",
ja: "ロビー制御", ko: "로비 제어", ru: "Управление лобби", pt: "Controle de lobby", it: "Controllo lobby");
AddTranslation("Force Start Game",
cn: "强制开始游戏", fr: "Forcer le démarrage", de: "Spiel erzwingen", es: "Forzar inicio",
ja: "強制開始", ko: "강제 시작", ru: "Принудительный старт", pt: "Forçar início", it: "Forza avvio");
AddTranslation("Host Only",
cn: "仅房主", fr: "Hôte seulement", de: "Nur Host", es: "Solo anfitrión",
ja: "ホストのみ", ko: "호스트만", ru: "Только хост", pt: "Apenas host", it: "Solo host");
AddTranslation("Exit",
cn: "退出", fr: "Quitter", de: "Beenden", es: "Salir",
ja: "終了", ko: "나가기", ru: "Выход", pt: "Sair", it: "Esci");
AddTranslation("Network Stats",
cn: "网络统计", fr: "Statistiques réseau", de: "Netzwerk-Statistiken", es: "Estadísticas de red",
ja: "ネットワーク統計", ko: "네트워크 통계", ru: "Сетевая статистика", pt: "Estatísticas de rede", it: "Statistiche rete");
AddTranslation("Player Count",
cn: "玩家数量", fr: "Nombre de joueurs", de: "Spieleranzahl", es: "Cantidad de jugadores",
ja: "プレイヤー数", ko: "플레이어 수", ru: "Количество игроков", pt: "Contagem de jogadores", it: "Numero giocatori");
AddTranslation("Connection ID",
cn: "连接ID", fr: "ID de connexion", de: "Verbindungs-ID", es: "ID de conexión",
ja: "接続ID", ko: "연결 ID", ru: "ID подключения", pt: "ID de conexão", it: "ID connessione");
AddTranslation("First aid", AddTranslation("First aid",
cn: "急救包", fr: "Premiers soins", de: "Erste Hilfe", es: "Primeros auxilios", cn: "急救包", fr: "Premiers soins", de: "Erste Hilfe", es: "Primeros auxilios",
@@ -579,10 +801,6 @@ namespace DevourClient.Localization
cn: "仪式书", fr: "Livre rituel", de: "Ritualbuch", es: "Libro ritual", cn: "仪式书", fr: "Livre rituel", de: "Ritualbuch", es: "Libro ritual",
ja: "儀式の本", ko: "의식서", ru: "Ритуальная книга", pt: "Livro ritual", it: "Libro rituale"); ja: "儀式の本", ko: "의식서", ru: "Ритуальная книга", pt: "Livro ritual", it: "Libro rituale");
AddTranslation("Doll Head",
cn: "玩偶头", fr: "Tête de poupée", de: "Puppenkopf", es: "Cabeza de muñeca",
ja: "人形の頭", ko: "인형 머리", ru: "Голова куклы", pt: "Cabeça de boneca", it: "Testa di bambola");
AddTranslation("Animal_Gate", AddTranslation("Animal_Gate",
cn: "动物大门", fr: "Porte des animaux", de: "Tiertor", es: "Puerta de animales", cn: "动物大门", fr: "Porte des animaux", de: "Tiertor", es: "Puerta de animales",
ja: "動物のゲート", ko: "동물 문", ru: "Ворота для животных", pt: "Portão de animais", it: "Cancello degli animali"); ja: "動物のゲート", ko: "동물 문", ru: "Ворота для животных", pt: "Portão de animais", it: "Cancello degli animali");
@@ -714,6 +932,79 @@ namespace DevourClient.Localization
AddTranslation("TV", AddTranslation("TV",
cn: "电视", fr: "Télévision", de: "Fernseher", es: "Televisión", cn: "电视", fr: "Télévision", de: "Fernseher", es: "Televisión",
ja: "テレビ", ko: "TV", ru: "Телевизор", pt: "Televisão", it: "Televisione"); ja: "テレビ", ko: "TV", ru: "Телевизор", pt: "Televisão", it: "Televisione");
// ==================== Network - Region Names ====================
// Based on actual available regions (10 regions)
AddTranslation("Asia",
cn: "亚洲", fr: "Asie", de: "Asien", es: "Asia",
ja: "アジア", ko: "아시아", ru: "Азия", pt: "Ásia", it: "Asia");
AddTranslation("Australia",
cn: "澳大利亚", fr: "Australie", de: "Australien", es: "Australia",
ja: "オーストラリア", ko: "호주", ru: "Австралия", pt: "Austrália", it: "Australia");
AddTranslation("Europe",
cn: "欧洲", fr: "Europe", de: "Europa", es: "Europa",
ja: "ヨーロッパ", ko: "유럽", ru: "Европа", pt: "Europa", it: "Europa");
AddTranslation("Japan",
cn: "日本", fr: "Japon", de: "Japan", es: "Japón",
ja: "日本", ko: "일본", ru: "Япония", pt: "Japão", it: "Giappone");
AddTranslation("South America",
cn: "南美洲", fr: "Amérique du Sud", de: "Südamerika", es: "Sudamérica",
ja: "南アメリカ", ko: "남미", ru: "Южная Америка", pt: "América do Sul", it: "Sud America");
AddTranslation("South Korea",
cn: "韩国", fr: "Corée du Sud", de: "Südkorea", es: "Corea del Sur",
ja: "韓国", ko: "한국", ru: "Южная Корея", pt: "Coreia do Sul", it: "Corea del Sud");
AddTranslation("Turkey",
cn: "土耳其", fr: "Turquie", de: "Türkei", es: "Turquía",
ja: "トルコ", ko: "튀르키예", ru: "Турция", pt: "Turquia", it: "Turchia");
AddTranslation("US East",
cn: "美东", fr: "Est des États-Unis", de: "USA Ost", es: "Este de EE.UU.",
ja: "米国東部", ko: "미국 동부", ru: "Восток США", pt: "Leste dos EUA", it: "Est USA");
AddTranslation("US West",
cn: "美西", fr: "Ouest des États-Unis", de: "USA West", es: "Oeste de EE.UU.",
ja: "米国西部", ko: "미국 서부", ru: "Запад США", pt: "Oeste dos EUA", it: "Ovest USA");
AddTranslation("US South Central",
cn: "美国中南部", fr: "Centre-Sud des États-Unis", de: "USA Süd-Zentral", es: "Centro-Sur de EE.UU.",
ja: "米国中南部", ko: "미국 중남부", ru: "Юго-Центральная часть США", pt: "Centro-Sul dos EUA", it: "Centro-Sud USA");
// ==================== Network - Status Messages ====================
AddTranslation("Not connected",
cn: "未连接网络", fr: "Non connecté", de: "Nicht verbunden", es: "No conectado",
ja: "未接続", ko: "연결되지 않음", ru: "Не подключено", pt: "Não conectado", it: "Non connesso");
AddTranslation("Host",
cn: "房主", fr: "Hôte", de: "Host", es: "Anfitrión",
ja: "ホスト", ko: "호스트", ru: "Хост", pt: "Anfitrião", it: "Host");
AddTranslation("Client",
cn: "客户端", fr: "Client", de: "Client", es: "Cliente",
ja: "クライアント", ko: "클라이언트", ru: "Клиент", pt: "Cliente", it: "Client");
AddTranslation("Role",
cn: "角色", fr: "Rôle", de: "Rolle", es: "Rol",
ja: "役割", ko: "역할", ru: "Роль", pt: "Função", it: "Ruolo");
AddTranslation("Player Count",
cn: "玩家数", fr: "Nombre de joueurs", de: "Spieleranzahl", es: "Número de jugadores",
ja: "プレイヤー数", ko: "플레이어 수", ru: "Количество игроков", pt: "Número de jogadores", it: "Numero di giocatori");
AddTranslation("Ping",
cn: "延迟", fr: "Ping", de: "Ping", es: "Ping",
ja: "Ping", ko: "핑", ru: "Пинг", pt: "Ping", it: "Ping");
AddTranslation("Error",
cn: "错误", fr: "Erreur", de: "Fehler", es: "Error",
ja: "エラー", ko: "오류", ru: "Ошибка", pt: "Erro", it: "Errore");
} }
private static void AddTranslation(string english, private static void AddTranslation(string english,

View File

@@ -0,0 +1,212 @@
using System;
using System.Linq;
using Il2Cpp;
using Il2CppPhoton.Bolt;
using Il2CppUdpKit.Platform.Photon;
using MelonLoader;
using UnityEngine;
namespace DevourClient.Network
{
/// <summary>
/// Lobby creation and management class
/// </summary>
public static class LobbyManager
{
/// <summary>
/// Create game lobby/room
/// </summary>
/// <param name="regionCode">Region code (e.g.: "eu", "us", "asia", "usw", "sa", "jp", "au", "ru", "in", "kr")</param>
/// <param name="lobbyLimit">Maximum player limit (1-64)</param>
/// <param name="isPrivate">Whether this is a private room</param>
public static void CreateLobby(string regionCode, int lobbyLimit, bool isPrivate)
{
try
{
// Check if already in game
if (IsInGame())
{
MelonLogger.Warning("[LobbyManager] Already in game, cannot create lobby");
return;
}
// Get PhotonRegion
PhotonRegion region = GetPhotonRegion(regionCode);
if (region == null)
{
MelonLogger.Error($"[LobbyManager] Failed to find region: {regionCode}");
return;
}
// Find Menu controller
Il2CppHorror.Menu menu = FindMenuController();
if (menu == null)
{
MelonLogger.Error("[LobbyManager] Failed to find MenuController");
return;
}
// Set UDP platform/region
menu.SetUDPPlatform(region);
MelonLogger.Msg($"[LobbyManager] Server region set to: {region.City}");
// Get BoltConfig and set connection limit
BoltConfig config = menu.boltConfig;
if (config != null)
{
config.serverConnectionLimit = lobbyLimit;
MelonLogger.Msg($"[LobbyManager] Connection limit set to: {lobbyLimit}");
// Set private lobby option
if (menu.hostPrivateServer != null)
{
menu.hostPrivateServer.Set(isPrivate, true);
MelonLogger.Msg($"[LobbyManager] Private lobby: {isPrivate}");
}
// Start server
BoltLauncher.StartServer(config, null);
// Show loading screen, hide main menu and host screen
if (menu.loadingCanvasGroup != null)
{
menu.ShowCanvasGroup(menu.loadingCanvasGroup, true);
}
if (menu.hostCanvasGroup != null)
{
menu.ShowCanvasGroup(menu.hostCanvasGroup, false);
}
if (menu.mainMenuCanvasGroup != null)
{
menu.ShowCanvasGroup(menu.mainMenuCanvasGroup, false);
}
MelonLogger.Msg("[LobbyManager] Lobby created successfully!");
}
else
{
MelonLogger.Error("[LobbyManager] BoltConfig is null");
}
}
catch (Exception ex)
{
MelonLogger.Error($"[LobbyManager] Error creating lobby: {ex.Message}");
MelonLogger.Error(ex.StackTrace);
}
}
/// <summary>
/// Get PhotonRegion object for specified region
/// </summary>
private static PhotonRegion GetPhotonRegion(string regionCode)
{
try
{
// Use PhotonRegion.GetRegion method
return PhotonRegion.GetRegion(regionCode);
}
catch (Exception ex)
{
MelonLogger.Error($"[LobbyManager] Failed to get PhotonRegion: {ex.Message}");
return null;
}
}
/// <summary>
/// Find Menu controller
/// </summary>
private static Il2CppHorror.Menu FindMenuController()
{
try
{
// Find all Menu objects
var menus = UnityEngine.Object.FindObjectsOfType<Il2CppHorror.Menu>();
// Find object named "MenuController"
foreach (var menu in menus)
{
if (menu.name == "MenuController")
{
return menu;
}
}
// If no specific name found, return first one
return menus.FirstOrDefault();
}
catch (Exception ex)
{
MelonLogger.Error($"[LobbyManager] Failed to find MenuController: {ex.Message}");
return null;
}
}
/// <summary>
/// Check if in game
/// </summary>
private static bool IsInGame()
{
try
{
OptionsHelpers helper = OptionsHelpers.singleton;
if (helper == null) return false;
return helper.inGame;
}
catch
{
return false;
}
}
/// <summary>
/// Force start lobby game (host only)
/// </summary>
public static void ForceLobbyStart()
{
try
{
if (!BoltNetwork.IsServer)
{
MelonLogger.Warning("[LobbyManager] Only host can start game");
return;
}
Il2CppHorror.Menu menu = FindMenuController();
if (menu == null)
{
MelonLogger.Error("[LobbyManager] Failed to find MenuController");
return;
}
// Call start button click event
menu.OnLobbyStartButtonClick();
MelonLogger.Msg("[LobbyManager] Force start game");
}
catch (Exception ex)
{
MelonLogger.Error($"[LobbyManager] Force start failed: {ex.Message}");
}
}
/// <summary>
/// Show message box
/// </summary>
public static void ShowMessageBox(string message)
{
try
{
Il2CppHorror.Menu menu = FindMenuController();
if (menu != null)
{
menu.ShowMessageModal(message);
}
}
catch (Exception ex)
{
MelonLogger.Error($"[LobbyManager] Failed to show message: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,135 @@
using System;
using System.Linq;
using Il2CppPhoton.Bolt;
using MelonLoader;
using DevourClient.Localization;
namespace DevourClient.Network
{
// Network helper class
public static class NetworkHelper
{
// Check if current player is host
public static bool IsHost()
{
try
{
return BoltNetwork.IsServer;
}
catch
{
return false;
}
}
// Get network ping
public static float GetPing()
{
try
{
BoltConnection connection = BoltNetwork.Server;
if (connection != null)
{
float pingSeconds = connection.PingNetwork;
return (float)Math.Round(pingSeconds * 1000.0f);
}
return 0.0f;
}
catch
{
return 0.0f;
}
}
// Get local connection ID
public static uint GetConnectionID()
{
try
{
return NetworkIdAllocator.LocalConnectionId;
}
catch
{
return 0;
}
}
// Get player count
public static int GetPlayerCount()
{
try
{
if (BoltNetwork.IsRunning)
{
UnityEngine.GameObject[] players = UnityEngine.GameObject.FindGameObjectsWithTag("Player");
return players != null ? players.Length : 0;
}
return 0;
}
catch
{
return 0;
}
}
// Is network running
public static bool IsNetworkRunning()
{
try
{
return BoltNetwork.IsRunning;
}
catch
{
return false;
}
}
// Is client
public static bool IsClient()
{
try
{
return BoltNetwork.IsClient;
}
catch
{
return false;
}
}
// Get formatted string of current room information (multilanguage support)
public static string GetRoomInfo()
{
try
{
if (!IsNetworkRunning())
{
return MultiLanguageSystem.Translate("Not connected");
}
string roleText = MultiLanguageSystem.Translate("Role");
string role = IsHost() ? MultiLanguageSystem.Translate("Host") : MultiLanguageSystem.Translate("Client");
string playerCountText = MultiLanguageSystem.Translate("Player Count");
int playerCount = GetPlayerCount();
float ping = IsClient() ? GetPing() : 0;
if (IsHost())
{
return $"{roleText}: {role} | {playerCountText}: {playerCount}";
}
else
{
string pingText = MultiLanguageSystem.Translate("Ping");
return $"{roleText}: {role} | {playerCountText}: {playerCount} | {pingText}: {ping}ms";
}
}
catch (Exception ex)
{
MelonLogger.Error($"[NetworkHelper] Failed to get room info: {ex.Message}");
return MultiLanguageSystem.Translate("Error");
}
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using DevourClient.Localization;
namespace DevourClient.Network
{
// Region helper class
public static class RegionHelper
{
// List of all available regions (English key names)
// Based on actual game PhotonRegion.Regions enum
public static readonly Dictionary<string, string> AvailableRegions = new Dictionary<string, string>()
{
{ "asia", "Asia" },
{ "au", "Australia" },
{ "eu", "Europe" },
{ "jp", "Japan" },
{ "sa", "South America" },
{ "kr", "South Korea" },
{ "tr", "Turkey" },
{ "us", "US East" },
{ "usw", "US West" },
{ "ussc", "US South Central" }
};
// Get region code array (for ImGui Combo etc.)
public static string[] GetRegionCodes()
{
string[] codes = new string[AvailableRegions.Count];
int index = 0;
foreach (var kvp in AvailableRegions)
{
codes[index++] = kvp.Key;
}
return codes;
}
// Get region display name array (multilanguage support)
public static string[] GetRegionDisplayNames()
{
string[] names = new string[AvailableRegions.Count];
int index = 0;
foreach (var kvp in AvailableRegions)
{
// Use MultiLanguageSystem to translate region names
names[index++] = MultiLanguageSystem.Translate(kvp.Value);
}
return names;
}
// Get region code by index
public static string GetRegionCodeByIndex(int index)
{
string[] codes = GetRegionCodes();
if (index >= 0 && index < codes.Length)
{
return codes[index];
}
return "asia"; // Default to Asia
}
// Get display name by region code (multilanguage support)
public static string GetDisplayNameByCode(string code)
{
if (AvailableRegions.TryGetValue(code, out string englishName))
{
// Use MultiLanguageSystem to translate region names
return MultiLanguageSystem.Translate(englishName);
}
return code;
}
// Check if region code is valid
public static bool IsValidRegionCode(string code)
{
return AvailableRegions.ContainsKey(code);
}
}
}

View File

@@ -14,7 +14,6 @@ namespace DevourClient.Settings
public static Color player_esp_color = new Color(0.00f, 1.00f, 0.00f, 1); public static Color player_esp_color = new Color(0.00f, 1.00f, 0.00f, 1);
public static Color azazel_esp_color = new Color(1.00f, 0.00f, 0.00f, 1); public static Color azazel_esp_color = new Color(1.00f, 0.00f, 0.00f, 1);
public static float speed = 1f; public static float speed = 1f;
public const string message_to_spam = "Deez Nutz";
public static KeyCode flyKey = KeyCode.None; public static KeyCode flyKey = KeyCode.None;
public static Vector2 itemsScrollPosition = Vector2.zero; public static Vector2 itemsScrollPosition = Vector2.zero;
public static Vector2 rituelObjectsScrollPosition = Vector2.zero; public static Vector2 rituelObjectsScrollPosition = Vector2.zero;

View File

@@ -53,7 +53,7 @@ Everything about spoofing ehre (steam name, server name, level...) will persist
* Fullbright * Fullbright
* Infinite mirrors (Manor update) * Infinite mirrors (Manor update)
* Switch between realms (Manor update) * Switch between realms (Manor update)
* Due to the game update, I deleted "Steam name spoofer", "Server name spoofer" and "Create a lobby with no player limit" these three functions.For "steam name spoofer", even changed your name by this function, your teamates can still see your name by steam profile, escape button, and your message in game. For "create a lobby with no player limit", if create a lobby with more than four players, the ghost will be stuck or some of the players will not be able to move. So I have to delete this function.(by manafeng) * Due to the game update, I deleted "Steam name spoofer" and "Server name spoofer" these two functions.For "steam name spoofer", even changed your name by this function, your teamates can still see your name by steam profile, escape button, and your message in game.(by manafeng)
## English Installation Tutorial ## English Installation Tutorial
@@ -86,7 +86,7 @@ In order to get all of this working you need to generate the DevourClient.dll fi
4、运行devour → 如果安装成功你会看到一个windows窗口进行各类安装提示后自动进入游戏。点击insert键即可打开和关闭devourclient窗口 4、运行devour → 如果安装成功你会看到一个windows窗口进行各类安装提示后自动进入游戏。点击insert键即可打开和关闭devourclient窗口
ps:有些电脑在安装melonloader之后会出现fatal error的提示这个我目前并没有碰到过。但是出现这个提示的主要原因基本是melonloader安装过程中提取到devour根目录的melonloader文件夹里的文件出现了问题比较简单的解决办法就是1在别人的同系统同位宽x86x32的电脑里拷贝出来他的melonloader文件夹然后直接粘贴到自己的电脑里。2将melonloader文件夹完全删除然后重装。 ps:有些电脑在安装melonloader之后会出现fatal error的提示这个我目前并没有碰到过。但是出现这个提示的主要原因基本是melonloader安装过程中提取到devour根目录的melonloader文件夹里的文件出现了问题比较简单的解决办法就是1在别人的同系统同位宽x86x32的电脑里拷贝出来他的melonloader文件夹然后直接粘贴到自己的电脑里。2将melonloader文件夹完全删除然后重装。(3)在直到游戏完全运行菜单正常工作之前保持VPN线路通畅。
如果你想要对代码进行修改和开发请按照下面的”building from source“的步骤逐步进行 如果你想要对代码进行修改和开发请按照下面的”building from source“的步骤逐步进行