@@ -38,7 +40,7 @@
/tp <1 to 22> (Teleport)
/model (Change your model between male and female)
-
/outfit [outfit_name] (Change outfit to random or entered value)
+
/outfit <outfitName> (Change outfit to random or entered value)
/veh <modelName> (Spawn a vehicle)
/clearvehicles (Clear your vehicles)
/tune <index> <value> (Tune vehicle)
diff --git a/freeroam-extended/client/html/style.css b/freeroam-extended/client/html/style.css
index 009d879..9ded38c 100644
--- a/freeroam-extended/client/html/style.css
+++ b/freeroam-extended/client/html/style.css
@@ -256,14 +256,7 @@ body {
}
.stress-test-label {
- top: .2em;
- left: 50%;
- transform: translateX(-50%);
- text-align: center;
- width: 100%;
- font-size: .8em;
- position: absolute;
- color: rgba(255, 255, 255, 0.628);
+ font-size: 16px;
}
.weapons-enabled > * {
@@ -307,3 +300,21 @@ body {
.streamed-in > * {
}
+
+.watermark {
+ pointer-events: none;
+ position: fixed;
+ color: rgba(255, 255, 255, 0.75);
+ font-weight: 500;
+ padding: 1em;
+ font-size: 0.9em;
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
+ z-index: 201;
+ opacity: 1;
+
+ font-family: 'Inter';
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ text-align: center;
+}
\ No newline at end of file
diff --git a/freeroam-extended/client/package.json b/freeroam-extended/client/package.json
index ac8adef..f632b2f 100644
--- a/freeroam-extended/client/package.json
+++ b/freeroam-extended/client/package.json
@@ -4,10 +4,10 @@
"main": "index.js",
"license": "MIT",
"devDependencies": {
- "@altv/types-client": "^2.9.2",
+ "@altv/types-client": "^2.9.7",
"@altv/types-natives": "^1.5.4",
- "@altv/types-server": "^2.9.5",
- "@altv/types-shared": "^1.6.0",
+ "@altv/types-server": "^3.0.1",
+ "@altv/types-shared": "^1.6.5",
"@typescript-eslint/eslint-plugin": "^5.50.0",
"@typescript-eslint/parser": "^5.50.0",
"altv-esbuild": "^0.4.3",
diff --git a/freeroam-extended/client/src/chat.ts b/freeroam-extended/client/src/chat.ts
index b01a353..63d5438 100644
--- a/freeroam-extended/client/src/chat.ts
+++ b/freeroam-extended/client/src/chat.ts
@@ -53,8 +53,7 @@ view.on("chatloaded", () => {
})
view.on("chatmessage", (text: string) => {
- if (playerData.chatState)
- alt.emitServer("chat:message", text)
+ alt.emitServer("chat:message", text)
alt.toggleGameControls(true)
view.unfocus()
@@ -65,4 +64,4 @@ view.on("chatmessage", (text: string) => {
}, 200)
})
-pushLine("
alt:V Multiplayer has started")
+pushLine("alt:V Multiplayer has started")
diff --git a/freeroam-extended/client/src/events.ts b/freeroam-extended/client/src/events.ts
index 55803f0..8f5aba6 100644
--- a/freeroam-extended/client/src/events.ts
+++ b/freeroam-extended/client/src/events.ts
@@ -16,23 +16,23 @@ alt.on("connectionComplete", () => {
}, 1000)
})
+alt.on("localMetaChange", (key: string, newValue: any) => {
+ if (key == "godmode")
+ native.setEntityInvincible(alt.Player.local, newValue);
+})
+
alt.onServer("airport_state", setWeaponsUsage)
alt.onServer("chat:message", chat.pushMessage)
alt.onServer("noclip", toggleNoclip)
-alt.onServer("set_chat_state", (state: boolean) => {
- playerData.chatState = state
-})
-
alt.onServer("draw_dmzone", (
centerX: number,
centerY: number,
- radius: number,
- count: number,
+ radius: number
) => {
- drawDMZone(centerX, centerY, radius, count)
+ drawDMZone(centerX, centerY, radius)
})
alt.onServer("announce", (header: string, body: string, time: number) => {
@@ -84,9 +84,9 @@ alt.on("keyup", (key) => {
})
alt.onServer("get_pos", () => {
- const state = alt.getPermissionState(Permission.ClipboardAccess)
+ const state = alt.getPermissionState(Permission.CLIPBOARD_ACCESS)
- if (state !== PermissionState.Allowed) {
+ if (state !== PermissionState.ALLOWED) {
alt.log("get_pos clipboard access is not allowed, state:", state)
return
}
diff --git a/freeroam-extended/client/src/helpers.ts b/freeroam-extended/client/src/helpers.ts
index 88874cc..10ab0b0 100644
--- a/freeroam-extended/client/src/helpers.ts
+++ b/freeroam-extended/client/src/helpers.ts
@@ -132,18 +132,13 @@ export function drawDMZone(
centerX: number,
centerY: number,
radius: number,
- count: number,
): void {
- const steps = 2 * Math.PI / count
- for (let i = 0; i < count; i++) {
- const blipX = radius * Math.cos(steps * i) + centerX
- const blipY = radius * Math.sin(steps * i) + centerY
-
- const blip = new alt.PointBlip(blipX, blipY, 0)
- blip.sprite = 310
- blip.shortRange = true
- native.setBlipHiddenOnLegend(blip.scriptID, true)
- }
+ const blip = new alt.RadiusBlip(centerX, centerY, 0, radius);
+ blip.sprite = 10;
+ blip.shortRange = true;
+ blip.color = 5;
+ blip.isHiddenOnLegend = false;
+ blip.name = "DM zone";
}
let adminMessageEveryTick: number | null = null
diff --git a/freeroam-extended/client/yarn.lock b/freeroam-extended/client/yarn.lock
index db15c2a..cd6d369 100644
--- a/freeroam-extended/client/yarn.lock
+++ b/freeroam-extended/client/yarn.lock
@@ -2,25 +2,25 @@
# yarn lockfile v1
-"@altv/types-client@^2.9.2":
- version "2.9.2"
- resolved "https://registry.npmjs.org/@altv/types-client/-/types-client-2.9.2.tgz"
- integrity sha512-LMGD1EBebN6BjFohhvPijR1Rq8BnU24IGdPb2It7NGFhHXxX/688XnlfX+tquIKlUkQPR8D54imNzZKBUG+BWA==
+"@altv/types-client@^2.9.7":
+ version "2.9.7"
+ resolved "https://registry.yarnpkg.com/@altv/types-client/-/types-client-2.9.7.tgz#9082db1af8dbd7f04bc5f33e8ad67adcf6d9afba"
+ integrity sha512-VCuo56pzGLJedu6oiesAoKtFc7O5ZhAHH7W/WOX1dGU+PXWIM0B6OYbYuIOr6AOLwTCVTv+QpUrKgkN+38WCyA==
"@altv/types-natives@^1.5.4":
version "1.5.4"
resolved "https://registry.npmjs.org/@altv/types-natives/-/types-natives-1.5.4.tgz"
integrity sha512-N4jtJ4f8KFOCi0sxlVvTWF7I7Nz/ylq136sIJMpsHIcBWIlysWF6zdJFdBW5bkquDGWgY8aBYPQ4TU+ayQhukw==
-"@altv/types-server@^2.9.5":
- version "2.9.5"
- resolved "https://registry.npmjs.org/@altv/types-server/-/types-server-2.9.5.tgz"
- integrity sha512-Io4UkkJcbo9e6XqQd/dtQyQfOucko+vYmivQPJC/WemCCrQuMBWd4teqW3AUxcpT81psOnnJkHEVxfth386zmw==
+"@altv/types-server@^3.0.1":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@altv/types-server/-/types-server-3.0.1.tgz#83b41032cab2522cc62ffc6441c5fef08440229e"
+ integrity sha512-dVEGQUCj/IiFAw2oC1jQ3Iiacqtk5ciA2BNXJIETFcY2tz0uVaNMFAszR4B4xNBctWnXY12RDCJRrrvcxrPTMg==
-"@altv/types-shared@^1.6.0":
- version "1.6.0"
- resolved "https://registry.npmjs.org/@altv/types-shared/-/types-shared-1.6.0.tgz"
- integrity sha512-OURm829uVVxKFMPtWx/ZUR9K7cw7ZISCt5qdFzRO0MUdd+HAX3hymJqyy3euksTkxlBpGQXox432I0Sk02aurg==
+"@altv/types-shared@^1.6.5":
+ version "1.6.5"
+ resolved "https://registry.yarnpkg.com/@altv/types-shared/-/types-shared-1.6.5.tgz#f3cd941a2706065e284cd0b053936fc0d0856024"
+ integrity sha512-gOil0Is/T26XCAJ+96H3qEjq7zLc9sG7vGp14UVZD09Vn0ClxUx3EG1xapJcobUuJHUd1uI24j1ODSzZ/pSMtA==
"@esbuild/linux-loong64@0.14.53":
version "0.14.53"
diff --git a/freeroam-extended/server/freeroam-extended/AdminCommands.cs b/freeroam-extended/server/freeroam-extended/AdminCommands.cs
new file mode 100644
index 0000000..1d447a0
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/AdminCommands.cs
@@ -0,0 +1,498 @@
+using System.Numerics;
+using System.Text.Json;
+using AltV.Net;
+using AltV.Net.Async;
+using AltV.Net.Data;
+using AltV.Net.Elements.Entities;
+using AltV.Net.Enums;
+using AltV.Net.Resources.Chat.Api;
+using Freeroam_Extended.Clothes;
+using Freeroam_Extended.Factories;
+
+namespace Freeroam_Extended
+{
+ public class AdminCommands : IScript
+ {
+ private void SendVehListHelp(IAltPlayer player)
+ {
+ player.SendChatMessage("/vehlist mode [blacklist,whitelist] - change vehicle list mode");
+ player.SendChatMessage("/vehlist allow [vehicle model] - allow vehicle (add to whitelist or remove from blacklist)");
+ player.SendChatMessage("/vehlist block [vehicle model] - block vehicle (add to blacklist or remove from whitelist)");
+ player.SendChatMessage("/vehlist clear - remove all vehicles from list");
+ player.SendChatMessage("/vehlist status - show status and vehicle list");
+ }
+
+ [Command("vehlist")]
+ public void VehList(IAltPlayer player, params string[] args)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (args.Length < 1)
+ {
+ SendVehListHelp(player);
+ return;
+ }
+
+ switch (args[0])
+ {
+ case "mode" when args.Length > 1 && args[1] == "blacklist":
+ VehicleController.UpdateState(false);
+ ChatController.BroadcastAdmins($"Vehicle list was changed to blacklist by {player.Serialize()}");
+ break;
+
+ case "mode" when args.Length > 1 && args[1] == "whitelist":
+ VehicleController.UpdateState(true);
+ ChatController.BroadcastAdmins($"Vehicle list was changed to whitelist by {player.Serialize()}");
+ break;
+
+ case "allow" when args.Length > 1:
+ if (!Enum.IsDefined(typeof(VehicleModel), Alt.Hash(args[1])))
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Invalid vehicle model!");
+ return;
+ }
+ VehicleController.Allow(args[1]);
+ ChatController.BroadcastAdmins($"Vehicle {args[1]} was {(VehicleController.IsWhitelist ? "added to whitelist" : "removed from blacklist")} by {player.Serialize()}");
+ break;
+
+ case "block" when args.Length > 1:
+ if (!Enum.IsDefined(typeof(VehicleModel), Alt.Hash(args[1])))
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Invalid vehicle model!");
+ return;
+ }
+ VehicleController.Block(args[1]);
+ ChatController.BroadcastAdmins($"Vehicle {args[1]} was {(VehicleController.IsWhitelist ? "removed from whitelist" : "added to blacklist")} by {player.Serialize()}");
+ break;
+
+ case "clear":
+ VehicleController.Clear();
+ ChatController.BroadcastAdmins($"Vehicle list was cleared by {player.Serialize()}");
+ break;
+
+ case "list":
+ player.SendChatMessage($"{(VehicleController.IsWhitelist ? "Whitelisted" : "Blacklisted")} vehicles: {string.Join(", ", VehicleController.List)}");
+ break;
+
+ default:
+ SendVehListHelp(player);
+ break;
+ }
+ }
+
+ #region Punishments
+ [Command("ban")]
+ public void Ban(IAltPlayer player, int id)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (player.Id == id)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You can't ban yourself!");
+ return;
+ }
+
+ if (Alt.GetPlayerById((uint) id) is not IAltPlayer target)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + $"Player with id {id} not found!");
+ return;
+ }
+
+ var name = target.Serialize();
+ PlayerController.Ban(target);
+ ChatController.BroadcastAdmins($"Player {name} was banned by {player.Serialize()}!");
+ }
+
+ [Command("kick")]
+ public void Kick(IAltPlayer player, int id)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (player.Id == id)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You can't kick yourself!");
+ return;
+ }
+
+ var target = (IAltPlayer) Alt.GetPlayerById((uint) id);
+ if (target == null)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + $"Player with id {id} not found!");
+ return;
+ }
+
+ var name = target.Serialize();
+ target.Kick("You've been kicked from this server!");
+
+ ChatController.BroadcastAdmins($"Player {name} was kicked by {player.Serialize()}!");
+ }
+
+ [Command("mutelist")]
+ public void Mutelist(IAltPlayer player)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var found = new HashSet
();
+ var muted = new List();
+ foreach (var p in Alt.GetAllPlayers())
+ {
+ if (p is not IAltPlayer target || !target.Data.Muted) continue;
+ muted.Add(target.CloudID + " - " + target.Serialize());
+ found.Add(target.CloudID);
+ }
+
+ foreach (var (key, value) in PlayerController.PlayerData)
+ {
+ if (!value.Muted) continue;
+ if (found.Contains(key)) continue;
+ muted.Add(key + " - Offline");
+ }
+
+ player.SendChatMessage("Muted players: " + string.Join(", ", muted));
+ }
+
+ [Command("mute")]
+ public void Mute(IAltPlayer player, int id)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (player.Id == id)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You can't mute yourself!");
+ return;
+ }
+
+ var target = (IAltPlayer) Alt.GetPlayerById((uint) id);
+ if (target == null)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + $"Player with id {id} not found!");
+ return;
+ }
+ PlayerController.Mute(target, player);
+ }
+
+ [Command("unmute")]
+ public void Unmute(IAltPlayer player, int id)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var target = (IAltPlayer) Alt.GetPlayerById((uint) id);
+ if (target == null)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + $"Player with id {id} not found!");
+ return;
+ }
+ PlayerController.Unmute(target, player);
+ }
+ #endregion
+
+ #region Teleports
+ [Command("dimension")]
+ public void Dimension(IAltPlayer player, int dimension = 0)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ player.Dimension = dimension;
+ }
+
+ [Command("tpallhere")]
+ public void TpAllHere(IAltPlayer player)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ foreach (var p in Alt.GetAllPlayers())
+ {
+ if (p is not IAltPlayer target || p.Id == player.Id || target.IsAdmin) continue;
+ target.Position = player.Position;
+ target.SendChatMessage(ChatConstants.SuccessPrefix + "You were teleported to " + player.Serialize() + "!");
+ }
+ }
+
+ [Command("tphere")]
+ public void TpHere(IAltPlayer player, int target)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var targetPlayer = (IAltPlayer)Alt.GetPlayerById((uint) target);
+ if (targetPlayer == null)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Player not found!");
+ return;
+ }
+
+ targetPlayer.Position = player.Position;
+ targetPlayer.SendChatMessage(ChatConstants.SuccessPrefix + "You were teleported to " + player.Serialize() + "!");
+ }
+
+ [Command("tpto")]
+ public void TpTo(IAltPlayer player, int target)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var targetPlayer = (IAltPlayer)Alt.GetPlayerById((uint) target);
+ if (targetPlayer == null)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Player not found!");
+ return;
+ }
+
+ player.Position = targetPlayer.Position;
+ player.SendChatMessage(ChatConstants.SuccessPrefix + "You were teleported to " + targetPlayer.Serialize() + "!");
+ }
+
+ [Command("tpcoords")]
+ public void TpCoords(IAltPlayer player, int x, int y, int z)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ player.Position = new Vector3(x, y, z);
+ player.SendChatMessage(ChatConstants.SuccessPrefix + $"You were teleported to {x}, {y}, {z}!");
+ }
+ #endregion
+
+ #region World state
+ [Command("settime")]
+ public void SetTime(IAltPlayer player, int hour)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (hour > 23 || hour < 0)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Invalid hour!");
+ return;
+ }
+
+ foreach (var p in Alt.GetAllPlayers())
+ {
+ p.SetDateTime(0, 0, 0, hour, 0, 0);
+ }
+
+ ChatController.BroadcastAdmins($"{player.Serialize()} set time to {hour}");
+ }
+
+ [Command("togglechat")]
+ public void ToggleChat(IAltPlayer player)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ ChatController.ChatState = !ChatController.ChatState;
+ player.SendChatMessage(ChatConstants.SuccessPrefix + "Chat is now " + (ChatController.ChatState ? "enabled" : "disabled") + "!");
+ }
+
+ [Command("overridespawnpos")]
+ public void OverrideSpawnPos(IAltPlayer player, bool mode)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (mode)
+ {
+ var pos = player.Position;
+ Misc.AdminOverridedSpawnPos = pos;
+
+ player.SendChatMessage(
+ ChatConstants.SuccessPrefix + $"You overrode spawn position for all players on {pos.X}, {pos.Y}, {pos.Z}!");
+ }
+ else
+ {
+ Misc.AdminOverridedSpawnPos = null;
+ player.SendChatMessage(ChatConstants.ErrorPrefix + $"You reset overridden spawn position!");
+ }
+ }
+
+ [Command("godmodeall")]
+ public void GodmodeAllPlayers(IAltPlayer player, bool mode)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var targets = Alt.GetAllPlayers().ToList();
+
+ foreach (var target in targets)
+ {
+ target.SetLocalMetaData("godmode", mode);
+ target.SendChatMessage(ChatConstants.SuccessPrefix + $"Godmode for all players is {(mode ? "activated" : "deactivated")}!");
+ }
+ }
+ #endregion
+
+ #region Local state
+ [Command("noclip")]
+ public void NoClip(IAltPlayer player)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ player.NoClip = !player.NoClip;
+ player.Streamed = !player.NoClip;
+ player.Visible = !player.NoClip;
+ player.SendChatMessage(ChatConstants.SuccessPrefix + $"NoClip is now {(player.NoClip ? "enabled" : "disabled")}!");
+
+ player.Emit("noclip", player.NoClip);
+ }
+
+ [Command("godmode")]
+ public void Godmode(IAltPlayer player, int id = 0)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var target = id == 0 ? player : Alt.GetPlayerById((uint) id);
+ if (target == null)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + $"Player with id {id} not found!");
+ return;
+ }
+
+ var hadValue = target.GetLocalMetaData("godmode", out bool prevValue);
+ var newValue = !hadValue || !prevValue;
+ target.SetLocalMetaData("godmode", newValue);
+ target.Invincible = !target.Invincible;
+ var msg = ChatConstants.SuccessPrefix + $"Godmode {(newValue ? "on" : "off")}!";
+ target.SendChatMessage(msg);
+
+ if (player.Id != target.Id)
+ player.SendChatMessage(msg);
+ }
+
+ // [Command("esp")]
+ // public void Esp(IAltPlayer player, bool mode)
+ // {
+ // if (!player.IsAdmin)
+ // {
+ // player.SendChatMessage(ChatConstants.NoPermissions);
+ // return;
+ // }
+ //
+ // player.Emit("esp", mode);
+ // }
+
+ [Command("globalvoice")]
+ public void GlobalVoice(IAltPlayer player)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ if (VoiceController.IsGlobalVoiceEnabled(player))
+ {
+ VoiceController.EnableGlobalVoice(player);
+ player.SendChatMessage(ChatConstants.SuccessPrefix + "Global voice enabled!");
+ return;
+ }
+ else
+ {
+ VoiceController.DisableGlobalVoice(player);
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Global voice disabled!");
+ return;
+ }
+ }
+ #endregion
+
+ #region Actions
+ [Command("announce")]
+ public void Announce(IAltPlayer player, string header, int time, params string[] body)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var message = string.Join(" ", body);
+ Alt.EmitAllClients("announce", header.Replace("_", " "), message, time);
+ }
+
+ [Command("clearallvehicles")]
+ public void ClearAllVehicles(IAltPlayer player, int distance = 0)
+ {
+ if (!player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.NoPermissions);
+ return;
+ }
+
+ var distSqr = distance * distance;
+ foreach (var altVehicle in Alt.GetAllVehicles())
+ {
+ var veh = (IAltVehicle) altVehicle;
+ if (distance == 0 || Vector3.DistanceSquared(veh.Position, player.Position) <= distSqr)
+ {
+ if (veh.Owner is { Exists: true })
+ {
+ veh.Owner.SendChatMessage(ChatConstants.ErrorPrefix + "Your vehicle was removed!");
+ }
+
+ veh.Destroy();
+ }
+ }
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Commands.cs b/freeroam-extended/server/freeroam-extended/Commands.cs
index bf828a2..894976f 100644
--- a/freeroam-extended/server/freeroam-extended/Commands.cs
+++ b/freeroam-extended/server/freeroam-extended/Commands.cs
@@ -13,37 +13,52 @@ namespace Freeroam_Extended
public class Commands : IScript
{
private readonly Random _random = new();
-
+
[Command("veh")]
- public void SpawnVeh(IAltPlayer player, string vehicleName)
+ public void SpawnVeh(IAltPlayer player, params string[] args)
{
- if (Misc.BlacklistedVehicle.Contains(Alt.Hash(vehicleName)) && !player.IsAdmin)
+ if (args.Length < 1)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Usage: /veh [vehicle name]");
+ return;
+ }
+
+ var vehicleName = args[0];
+
+ if (player.EnableWeaponUsage)
{
- player.SendChatMessage("{FF0000} Vehicle is blacklisted.");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You cannot spawn vehicles in DM zone!");
return;
}
if (!Enum.IsDefined(typeof(VehicleModel), Alt.Hash(vehicleName)))
{
- player.SendChatMessage("{FF0000} Invalid vehicle model!");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Invalid vehicle model!");
+ return;
+ }
+
+ if (!VehicleController.CheckVehicle(vehicleName) && !player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Vehicle is not available!");
+ if (VehicleController.IsWhitelist) player.SendChatMessage("Available vehicles: " + string.Join(", ", VehicleController.List));
return;
}
-
+
if (player.InteriorLocation != 0)
{
- player.SendChatMessage("{FF0000} You can't spawn vehicles in interiors!");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You can't spawn vehicles in interiors!");
return;
}
if (Alt.GetAllVehicles().Any(veh => veh.Position.Distance(player.Position) < 3))
{
- player.SendChatMessage("{FF0000} You are too close to a vehicle!");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You are too close to a vehicle!");
return;
}
if (player.LastVehicleSpawn.AddSeconds(10) > DateTime.Now)
{
- player.SendChatMessage("{FF0000} You have to wait 10s before spawning a new vehicle!");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You have to wait 10s before spawning a new vehicle!");
return;
}
@@ -52,19 +67,19 @@ public void SpawnVeh(IAltPlayer player, string vehicleName)
var target = player.Vehicles.OrderBy(veh => veh.SpawnTime).First();
player.Vehicles.Remove(target);
target.Destroy();
- player.SendChatMessage("{FF0000} You can't have more than 3 vehicles. We removed your oldest one!");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You can't have more than 3 vehicles. We removed your oldest one!");
}
if (player.IsInVehicle)
{
- player.SendChatMessage("{FF0000} You are already in a vehicle we replaced it for you!");
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You are already in a vehicle we replaced it for you!");
player.Vehicle.Destroy();
return;
}
- lock (StatsHandler.StatsData)
+ lock (StatsController.StatsData)
{
- StatsHandler.StatsData.VehiclesSpawned++;
+ StatsController.StatsData.VehiclesSpawned++;
}
var spawnedVeh = (AltVehicle) Alt.CreateVehicle(Alt.Hash(vehicleName),
@@ -75,25 +90,6 @@ public void SpawnVeh(IAltPlayer player, string vehicleName)
spawnedVeh.Owner = player;
}
- // [Command("spectate")]
- // public void Spectate(IAltPlayer player)
- // {
- // // Disable
- // if (player.GhostMode)
- // {
- // player.SendChatMessage("{00FF00} Spectator Mode disabled! You're no longer invincible.");
- // player.Emit("ghost_mode", false);
- // player.GhostMode = false;
- // player.DeleteStreamSyncedMetaData("spectator");
- // return;
- // }
- // // Enable
- // player.GhostMode = true;
- // player.Emit("ghost_mode", true);
- // player.SendChatMessage("{00FF00} Spectator Mode enabled! You're now invincible.");
- // player.SetStreamSyncedMetaData("spectator", true);
- // }
-
[Command("weapons")]
public void GetWeapons(IAltPlayer player)
{
@@ -105,34 +101,35 @@ public void GetWeapons(IAltPlayer player)
}
}
- [Command("model")]
- public void ChangeModel(IAltPlayer player)
- {
- if (player.Model == Alt.Hash("mp_m_freemode_01"))
- {
- player.Model = Alt.Hash("mp_f_freemode_01");
- }
- else
- {
- player.Model = Alt.Hash("mp_m_freemode_01");
- }
-
- player.RefreshFace();
-
- player.RefreshClothes();
- player.SendChatMessage(
- $"{{00FF00}}Your model changed");
- }
+ // TODO fix in core
+ // [Command("model")]
+ // public async Task ChangeModel(IAltPlayer player)
+ // {
+ // if (player.Model == Alt.Hash("mp_m_freemode_01"))
+ // {
+ // player.Model = Alt.Hash("mp_f_freemode_01");
+ // }
+ // else
+ // {
+ // player.Model = Alt.Hash("mp_m_freemode_01");
+ // }
+ // player.Spawn(player.Position);
+ //
+ // // AppearanceController.RefreshFace(player);
+ // // await AppearanceController.RefreshClothes(player);
+ //
+ // player.SendChatMessage(ChatConstants.SuccessPrefix + $"Your model was changed");
+ // }
[Command("outfit")]
- public void Outfit(IAltPlayer player, string outfitUniqueName = "")
+ public async Task Outfit(IAltPlayer player, string outfitUniqueName = "")
{
if (string.IsNullOrEmpty(outfitUniqueName))
{
- player.RefreshClothes();
+ await AppearanceController.RefreshClothes(player);
return;
}
- player.EquipOutfit(Alt.Hash(outfitUniqueName));
+ AppearanceController.EquipOutfit(player, Alt.Hash(outfitUniqueName));
player.SendChatMessage(
$"{{00FF00}}Your outfit updated");
}
@@ -143,7 +140,7 @@ public void Teleport(IAltPlayer player, int id = 0)
if (id > Misc.SpawnPositions.Length || id <= 0)
{
player.SendChatMessage(
- $"{{FF0000}}Invalid Spawnpoint! (Minimum 1, Maximum: {Misc.SpawnPositions.Length})");
+ ChatConstants.ErrorPrefix + $"Invalid Spawnpoint! (Minimum 1, Maximum: {Misc.SpawnPositions.Length})");
return;
}
@@ -151,63 +148,6 @@ public void Teleport(IAltPlayer player, int id = 0)
player.Position = spawnpoint + new Position(_random.Next(0, 10), _random.Next(0, 10), 0);
}
- [Command("ban")]
- public void Ban(IAltPlayer player, int id)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (player.Id == id)
- {
- player.SendChatMessage("{FF0000} You can't ban yourself!");
- return;
- }
-
- var target = (IAltPlayer)Alt.GetAllPlayers().FirstOrDefault(p => p.Id == id);
- if (target == null)
- {
- player.SendChatMessage($"{{FF0000}}Player with id {id} not found!");
- return;
- }
-
- target.Kick("You've been banned from this server!");
- Misc.BannedPlayers.Add(target.CloudID);
- string json = JsonSerializer.Serialize(Misc.BannedPlayers);
- File.WriteAllText(@"BannedPlayers.json", json);
-
- player.SendChatMessage($"{{00FF00}}Player with id {id} banned!");
- }
-
- [Command("unban")]
- public void Unban(IAltPlayer player, string rsid)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- var target = Misc.BannedPlayers.FirstOrDefault(id => id == rsid);
- if (target == null)
- {
- player.SendChatMessage($"{{FF0000}}Player with rsid {rsid} not found!");
- return;
- }
-
- if (Misc.BannedPlayers.All(id => id != rsid))
- {
- player.SendChatMessage($"{{FF0000}}Player with hwid {rsid} not banned!");
- return;
- }
-
- // remove banned player from list
- Misc.BannedPlayers.Remove(rsid);
- player.SendChatMessage($"{{00FF00}}Player with hwid {rsid} unbanned!");
- }
-
[Command("addcomponent")]
public void WeaponComponent(IAltPlayer player, string name)
{
@@ -255,191 +195,14 @@ public void Dm(IAltPlayer player)
}
}
- [Command("togglechat")]
- public void ToggleChat(IAltPlayer player, bool state)
- {
- // check if player is operator
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- player.SendChatMessage("{00FF00} Chat is now " + (state ? "enabled" : "disabled") + "!");
- Misc.ChatState = state;
- foreach (var p in Alt.GetAllPlayers())
- {
- // check if player is operator
- if (player.IsAdmin) continue;
- p.Emit("set_chat_state", state);
- }
- }
-
- [Command("dimension")]
- public void Dimension(IAltPlayer player, int dimension = 0)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- player.Dimension = dimension;
- }
-
[Command("clearvehicles")]
public void ClearVehicles(IAltPlayer player)
{
- // get all vehicles owned by player
foreach (var veh in player.Vehicles)
{
veh.Destroy();
}
- }
-
- [Command("tpallhere")]
- public void TpAllhere(IAltPlayer player)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- foreach (var p in Alt.GetAllPlayers())
- {
- if (p is not { } target) continue;
- target.Position = player.Position;
- target.SendChatMessage("{00FF00} You were teleported to " + player.Name + "!");
- }
- }
-
- [Command("tphere")]
- public void TpHere(IAltPlayer player, int target)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- var targetPlayer = Alt.GetAllPlayers().FirstOrDefault(p => p.Id == target);
- if (targetPlayer == null)
- {
- player.SendChatMessage("{FF0000} Player not found!");
- return;
- }
-
- targetPlayer.Position = player.Position;
- targetPlayer.SendChatMessage("{00FF00} You were teleported to " + player.Name + "!");
- }
-
- [Command("tpto")]
- public void TpTo(IAltPlayer player, int target)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- var targetPlayer = Alt.GetAllPlayers().FirstOrDefault(p => p.Id == target);
- if (targetPlayer == null)
- {
- player.SendChatMessage("{FF0000} Player not found!");
- return;
- }
-
- player.Position = targetPlayer.Position;
- player.SendChatMessage("{00FF00} You were teleported to " + targetPlayer.Name + "!");
- }
-
- [Command("clearallvehicles")]
- public void ClearAllVehicles(IAltPlayer player, int distance = 0)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (distance == 0)
- {
- foreach (var veh in Alt.GetAllVehicles())
- {
- veh.Destroy();
- }
-
- return;
- }
-
- var distSqr = distance * distance;
- foreach (var veh in Alt.GetAllVehicles())
- {
- // compare squared distance between player and vehicle
- if (Vector3.DistanceSquared(veh.Position, player.Position) <= distSqr) veh.Destroy();
- }
- }
-
- [Command("settime")]
- public void SetTime(IAltPlayer player, int hour)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (hour > 23 || hour < 0)
- {
- player.SendChatMessage("{FF0000} Invalid hour!");
- return;
- }
-
- foreach (var p in Alt.GetAllPlayers())
- {
- p.SetDateTime(0, 0, 0, hour, 0, 0);
- }
- }
-
- [Command("setweather")]
- public void SetWeather(IAltPlayer player, uint weather)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (weather > 14)
- {
- player.SendChatMessage("{FF0000} Invalid weather!");
- return;
- }
-
- foreach (var p in Alt.GetAllPlayers())
- {
- p.SetWeather(weather);
- }
-
- Misc.Weather = weather;
- }
-
- [Command("noclip")]
- public void NoClip(IAltPlayer player)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- player.NoClip = !player.NoClip;
- player.Streamed = !player.NoClip;
- player.Visible = !player.NoClip;
- player.SendChatMessage($"{{00FF00}}NoClip is now {(player.NoClip ? "enabled" : "disabled")}!");
-
- player.Emit("noclip", player.NoClip);
+ player.SendChatMessage(ChatConstants.SuccessPrefix + "You removed all your vehicles!");
}
[Command("revive")]
@@ -448,168 +211,15 @@ public void Respawn(IAltPlayer player)
if (Misc.AdminOverridedSpawnPos is not null) player.Spawn((Position) Misc.AdminOverridedSpawnPos);
else player.Spawn(player.Position);
player.ClearBloodDamage();
+ player.Health = 200;
}
-
- [Command("announce")]
- public void Announce(IAltPlayer player, string header, int time, params string[] body)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- var message = string.Join(" ", body);
- Alt.EmitAllClients("announce", header, message, time);
- }
-
- [Command("tpcoords")]
- public void TpCoords(IAltPlayer player, int x, int y, int z)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- player.Position = new Vector3(x, y, z);
- player.SendChatMessage($"{{00FF00}} You were teleported to {x}, {y}, {z}!");
- }
-
- [Command("kick")]
- public void Kick(IAltPlayer player, int id)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (player.Id == id)
- {
- player.SendChatMessage("{FF0000} You can't kick yourself!");
- return;
- }
-
- var target = Alt.GetAllPlayers().FirstOrDefault(p => p.Id == id);
- if (target == null)
- {
- player.SendChatMessage($"{{FF0000}}Player with id {id} not found!");
- return;
- }
-
- target.Kick("You've been kicked from this server!");
-
- player.SendChatMessage($"{{00FF00}}Player with id {id} kicked!");
- }
-
- [Command("godmode")]
- public void Godmode(IAltPlayer player, int id)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- var target = Alt.GetAllPlayers().FirstOrDefault(p => p.Id == id);
- if (target == null)
- {
- player.SendChatMessage($"{{FF0000}}Player with id {id} not found!");
- return;
- }
-
- target.Invincible = !target.Invincible;
- target.SendChatMessage(
- $"{(target.Invincible ? "{00FF00}" : "{FF0000}")}Godmode {(target.Invincible ? "on" : "off")}!");
-
- if (player.Id != target.Id)
- player.SendChatMessage($"{{00FF00}}Godmode {(target.Invincible ? "on" : "off")}!");
- }
-
- [Command("overridespawnpos")]
- public void OverrideSpawnPos(IAltPlayer player, bool mode)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (mode)
- {
- var pos = player.Position;
- Misc.AdminOverridedSpawnPos = pos;
-
- player.SendChatMessage(
- $"{{00FF00}} You're overrided spawn position for all player on {pos.X}, {pos.Y}, {pos.Z}!");
- }
- else
- {
- Misc.AdminOverridedSpawnPos = null;
- player.SendChatMessage($"{{00FF00}} You're no longer overrided spawn position!");
- }
- }
-
+
[Command("getpos")]
public void GetPosition(IAltPlayer player)
{
var pos = player.Position;
- player.SendChatMessage($"{{00FF00}} Your position is {pos.X}, {pos.Y}, {pos.Z}!");
+ player.SendChatMessage(ChatConstants.SuccessPrefix + $"Your position is {pos.X}, {pos.Y}, {pos.Z}!");
player.Emit("get_pos");
}
-
- [Command("godmodeall")]
- public void GodmodeAllPlayers(IAltPlayer player, bool mode)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- var targets = Alt.GetAllPlayers().ToList();
-
- foreach (var target in targets)
- {
- target.Invincible = mode;
- target.SendChatMessage($"{{00FF00}}Godmode for all players is {(mode ? "activated" : "deactivated")}!");
- }
- }
-
- [Command("esp")]
- public void Esp(IAltPlayer player, bool mode)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- player.Emit("esp", mode);
- }
-
- [Command("globalvoice")]
- public void GlobalVoice(IAltPlayer player)
- {
- if (!player.IsAdmin)
- {
- player.SendChatMessage("{FF0000} No permission!");
- return;
- }
-
- if (Voice.IsGlobalVoiceEnabled(player))
- {
- Voice.EnableGlobalVoice(player);
- player.SendChatMessage("{00FF00} Global voice enabled!");
- return;
- }
- else
- {
- Voice.DisableGlobalVoice(player);
- player.SendChatMessage("{00FFFF} Global voice disabled!");
- return;
- }
- }
}
}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Constants/ChatConstants.cs b/freeroam-extended/server/freeroam-extended/Constants/ChatConstants.cs
new file mode 100644
index 0000000..9d3542f
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Constants/ChatConstants.cs
@@ -0,0 +1,10 @@
+namespace Freeroam_Extended
+{
+ public static class ChatConstants
+ {
+ public static string ErrorPrefix = "{e86f66}";
+ public static string SuccessPrefix = "{52c765}";
+ public static string AdminPrefix = "{e39959}";
+ public static string NoPermissions = ErrorPrefix + "No permissions!";
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Constants/VehicleConstants.cs b/freeroam-extended/server/freeroam-extended/Constants/VehicleConstants.cs
new file mode 100644
index 0000000..2cb86ad
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Constants/VehicleConstants.cs
@@ -0,0 +1,144 @@
+
+namespace Freeroam_Extended
+{
+ public static class VehicleConstants
+ {
+ public static List DefaultWhitelistModels = new();
+ public static List DefaultBlacklistModels = new()
+ {
+ "impaler2",
+ "dinghy",
+ "nokota",
+ "tula",
+ "swift2",
+ "technical2",
+ "akula",
+ "seasparrow2",
+ "issi6",
+ "caracara",
+ "kosatka",
+ "technical3",
+ "paragon2",
+ "toreador",
+ "deluxo",
+ "thruster",
+ "trailerlarge",
+ "issi5",
+ "scarab2",
+ "valkyrie2",
+ "comet4",
+ "molotok",
+ "ardent",
+ "seasparrow3",
+ "imperator2",
+ "pounder2",
+ "strikeforce",
+ "monster3",
+ "slamvan6",
+ "dune3",
+ "cerberus3",
+ "firetruk",
+ "mule4",
+ "frogger2",
+ "brutus3",
+ "menacer",
+ "oppressor2",
+ "insurgent2",
+ "brutus",
+ "avenger",
+ "speedo4",
+ "technical",
+ "slamvan4",
+ "bruiser3",
+ "terbyte",
+ "havok",
+ "impaler3",
+ "insurgent3",
+ "brutus2",
+ "trailersmall2",
+ "insurgent",
+ "volatus",
+ "deathbike2",
+ "microlight",
+ "impaler4",
+ "starling",
+ "bruiser2",
+ "riot2",
+ "supervolito2",
+ "maverick",
+ "valkyrie",
+ "blazer5",
+ "dinghy2",
+ "zr3803",
+ "khanjali",
+ "pyro",
+ "dominator5",
+ "deathbike3",
+ "annihilator2",
+ "dominator6",
+ "lazer",
+ "minitank",
+ "vigilante",
+ "tampa3",
+ "scarab",
+ "zr3802",
+ "dinghy5",
+ "rogue",
+ "cerberus",
+ "polmav",
+ "imperator3",
+ "mogul",
+ "seasparrow",
+ "monster5",
+ "chernobog",
+ "dominator4",
+ "scramjet",
+ "scarab3",
+ "slamvan5",
+ "predator",
+ "revolter",
+ "seabreeze",
+ "viseris",
+ "jb7002",
+ "swift",
+ "patrolboat",
+ "barrage",
+ "avenger2",
+ "limo2",
+ "savage",
+ "hunter",
+ "bombushka",
+ "halftrack",
+ "deathbike",
+ "nightshark",
+ "imperator",
+ "volatol",
+ "dinghy3",
+ "zr380",
+ "apc",
+ "issi4",
+ "bruiser",
+ "cerberus2",
+ "boxville5",
+ "supervolito",
+ "frogger",
+ "buzzard2",
+ "rhino",
+ "buzzard",
+ "annihilator",
+ "monster4",
+ "dinghy4",
+ "oppressor",
+ "stromberg",
+ "savestra",
+ "ruiner2",
+ "hydra",
+ "jet",
+ "titan",
+ "blimp",
+ "cargoplane",
+ "blimp2",
+ "blimp3"
+ };
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Controllers/AppearanceController.cs b/freeroam-extended/server/freeroam-extended/Controllers/AppearanceController.cs
new file mode 100644
index 0000000..c3f8cf4
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Controllers/AppearanceController.cs
@@ -0,0 +1,120 @@
+using Freeroam_Extended.Clothes;
+using Freeroam_Extended.Factories;
+
+namespace Freeroam_Extended;
+
+public class AppearanceController
+{
+
+ public static void RefreshFace(IAltPlayer player)
+ {
+ if (player.Sex == 1)
+ {
+ player.SetHeadBlendData(6, 21, 0, 6, 21, 0, 0.41f, 0.18f, 0.0f);
+ player.SetHeadOverlay(0, 255, 1.0f);
+ player.SetHeadOverlay(1, 255, 1.0f);
+ player.SetHeadOverlay(2, 30, 1.0f);
+ player.SetHeadOverlay(3, 255, 1.0f);
+ player.SetHeadOverlay(4, 14, 1.0f);
+ player.SetHeadOverlay(5, 1, 1.0f);
+ player.SetHeadOverlay(6, 10, 0.85f);
+ player.SetHeadOverlay(7, 255, 1.0f);
+ player.SetHeadOverlay(8, 2, 1.0f);
+ player.SetHeadOverlay(9, 0, 0.0f);
+ player.SetHeadOverlay(10, 255, 1.0f);
+ player.SetHeadOverlay(11, 255, 1.0f);
+ player.SetHeadOverlay(12, 255, 1.0f);
+
+ player.SetHeadOverlayColor(5, 2, 11, 0);
+ player.SetHeadOverlayColor(8, 2, 6, 0);
+
+ int hairs = Misc.RandomInt(1, 23);
+ int hairsColor = Misc.RandomInt(1, 63);
+ int hairsColor2 = Misc.RandomInt(1, 63);
+
+ player.SetClothes(2, (ushort)hairs, 0, 0);
+ player.HairColor = (byte)hairsColor;
+ player.HairHighlightColor = (byte)hairsColor2;
+ player.SetEyeColor(2);
+
+ float[] featureParams = { -0.78f, 0, 0, -0.07f, 0.03f, 0, 0.07f, -0.44f, 0.07f, 0.02f, -0.95f, -0.74f, -1, -0.09f, -0.57f, 0.02f, -0.1f, -0.19f, -1, -1 };
+ for (int i = 0; i < featureParams.Length; i++)
+ {
+ player.SetFaceFeature((byte)i, featureParams[i]);
+ }
+ }
+ else if (player.Sex == 0)
+ {
+ player.SetHeadBlendData(2, 21, 0, 2, 21, 0, 0.5f, 0.72f, 0.0f);
+ player.SetHeadOverlay(0, 255, 1.0f);
+ player.SetHeadOverlay(1, 255, 1.0f);
+ player.SetHeadOverlay(2, 30, 1.0f);
+ player.SetHeadOverlay(3, 255, 1.0f);
+ player.SetHeadOverlay(4, 255, 1.0f);
+ player.SetHeadOverlay(5, 255, 1.0f);
+ player.SetHeadOverlay(6, 255, 1.0f);
+ player.SetHeadOverlay(7, 255, 1.0f);
+ player.SetHeadOverlay(8, 0, 0.15f);
+ player.SetHeadOverlay(9, 255, 1.0f);
+ player.SetHeadOverlay(10, 255, 1.0f);
+ player.SetHeadOverlay(11, 255, 1.0f);
+ player.SetHeadOverlay(12, 255, 1.0f);
+
+ player.SetHeadOverlayColor(5, 2, 32, 0);
+ player.SetHeadOverlayColor(8, 2, 11, 0);
+
+ int hairs = Misc.RandomInt(1, 22);
+ int hairsColor = Misc.RandomInt(1, 63);
+ int hairsColor2 = Misc.RandomInt(1, 63);
+
+ player.SetClothes(2, (ushort)hairs, 0, 0);
+ player.HairColor = (byte)hairsColor;
+ player.HairHighlightColor = (byte)hairsColor2;
+ player.SetEyeColor(3);
+
+ float[] featureParams = { 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 };
+ for (int i = 0; i < featureParams.Length; i++)
+ {
+ player.SetFaceFeature((byte)i, featureParams[i]);
+ }
+ }
+ }
+
+ public static async Task RefreshClothes(IAltPlayer player)
+ {
+ if (!Misc.IsResourceLoaded("c_clothesfit"))
+ return;
+
+ if (player.Sex == 2)
+ return;
+
+ await ClothesFitService.DestroyPlayer(player);
+ await ClothesFitService.InitPlayer(player);
+
+ ulong[] outfits = await ClothesFitService.GetOutfitsBySex(player.Sex);
+
+ int index = Misc.RandomInt(0, outfits.Length - 1);
+ ulong randomElement = outfits[index];
+
+ await ClothesFitService.Equip(player, (uint)randomElement);
+ }
+
+ public static async Task EquipOutfit(IAltPlayer player, uint outfitHash)
+ {
+ if (!Misc.IsResourceLoaded("c_clothesfit"))
+ return;
+
+ if (player.Sex == 2)
+ return;
+
+ await ClothesFitService.DestroyPlayer(player);
+ await ClothesFitService.InitPlayer(player);
+
+ ulong[] outfits = await ClothesFitService.GetOutfitsBySex(player.Sex);
+
+ if (outfits.Contains(outfitHash))
+ {
+ await ClothesFitService.Equip(player, outfitHash);
+ }
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Controllers/ChatController.cs b/freeroam-extended/server/freeroam-extended/Controllers/ChatController.cs
new file mode 100644
index 0000000..14e3915
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Controllers/ChatController.cs
@@ -0,0 +1,62 @@
+using System.Text.Json;
+using AltV.Net;
+using AltV.Net.Elements.Entities;
+using AltV.Net.Resources.Chat.Api;
+using Freeroam_Extended.Factories;
+
+namespace Freeroam_Extended;
+
+public static class ChatController
+{
+ public static void Init()
+ {
+ Alt.OnClient("chat:message", OnChatMessage);
+ }
+
+ public static bool ChatState = false;
+
+ public static void Broadcast(string message)
+ {
+ Alt.EmitAllClients("chat:message", null, (object) message);
+ }
+
+ public static void BroadcastAdmins(string message)
+ {
+ message = ChatConstants.AdminPrefix + message;
+
+ foreach (var p in Alt.GetAllPlayers().Where(e => ((IAltPlayer) e).IsAdmin))
+ {
+ p.SendChatMessage(message);
+ }
+ }
+
+ private static void OnChatMessage(IAltPlayer player, params string[] args)
+ {
+ var message = string.Join("", args);
+ if (args.Length == 0 || message.Length == 0) return;
+ if (args[0].StartsWith("/")) return;
+
+ if (player.Data.Muted)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "You are muted!");
+ return;
+ }
+
+ if (!ChatState && !player.IsAdmin)
+ {
+ player.SendChatMessage(ChatConstants.ErrorPrefix + "Chat is disabled!");
+ return;
+ }
+
+ foreach (var p in Alt.GetAllPlayers())
+ {
+ p.Emit("chat:message", (player.IsAdmin ? "{008736}" : "{FFFFFF}") + player.Serialize(), "{FFFFFF}" + message);
+ }
+ }
+
+ public static void Mute(IAltPlayer player)
+ {
+
+ }
+
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Controllers/PlayerController.cs b/freeroam-extended/server/freeroam-extended/Controllers/PlayerController.cs
new file mode 100644
index 0000000..24a1588
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Controllers/PlayerController.cs
@@ -0,0 +1,105 @@
+using System.Text.Json;
+using AltV.Net;
+using AltV.Net.Elements.Entities;
+using Freeroam_Extended.Factories;
+
+namespace Freeroam_Extended;
+
+public static class PlayerController
+{
+ private static readonly string BannedPlayersFile = "BannedPlayers.json";
+ private static readonly string PlayerDataFile = "PlayersData.json";
+
+ public static HashSet Banned = new();
+ public static Dictionary PlayerData = new();
+
+ public static void Init()
+ {
+ if (File.Exists(PlayerDataFile))
+ {
+ var json = File.ReadAllText(PlayerDataFile);
+ try
+ {
+ PlayerData = JsonSerializer.Deserialize>(json) ?? new();
+ }
+ catch (Exception e)
+ {
+ Alt.LogError("Failed to parse operators file!");
+ Alt.LogError(e.ToString());
+ }
+ }
+
+ if (File.Exists(BannedPlayersFile))
+ {
+ var json = File.ReadAllText(BannedPlayersFile);
+ try
+ {
+ Banned = JsonSerializer.Deserialize>(json) ?? new HashSet();
+ }
+ catch (Exception e)
+ {
+ Alt.LogError("Failed to parse banned players file!");
+ Alt.LogError(e.ToString());
+ }
+ }
+ }
+
+ private static void SaveBanned()
+ {
+ File.WriteAllText(BannedPlayersFile, JsonSerializer.Serialize(Banned));
+ }
+
+ public static void Ban(IAltPlayer player)
+ {
+ player.Kick("You are banned!");
+ Banned.Add(player.CloudID);
+ SaveBanned();
+ }
+
+ public static bool IsBanned(string cloudId)
+ {
+ return Banned.Contains(cloudId);
+ }
+
+ private static void SavePlayerData()
+ {
+ File.WriteAllText(PlayerDataFile, JsonSerializer.Serialize(PlayerData));
+ }
+
+ private static void ApplyPlayerData(IAltPlayer player)
+ {
+ PlayerData[player.CloudID] = player.Data;
+ player.SetLocalMetaData("operator", player.Data.Operator);
+ if (player.Data.Muted) VoiceController.MutePlayer(player);
+ else VoiceController.UnmutePlayer(player);
+ SavePlayerData();
+ }
+
+ public static void Op(IAltPlayer target, IAltPlayer? executor)
+ {
+ target.Data.Operator = true;
+ ApplyPlayerData(target);
+ ChatController.BroadcastAdmins((executor?.Serialize() ?? "SERVER") + " gave " + target.Serialize() + " operator permissions");
+ }
+
+ public static void Deop(IAltPlayer target, IAltPlayer? executor)
+ {
+ target.Data.Operator = false;
+ ApplyPlayerData(target);
+ ChatController.BroadcastAdmins((executor?.Serialize() ?? "SERVER") + " removed " + target.Serialize() + " operator permissions");
+ }
+
+ public static void Mute(IAltPlayer target, IAltPlayer? executor)
+ {
+ target.Data.Muted = true;
+ ApplyPlayerData(target);
+ ChatController.BroadcastAdmins((executor?.Serialize() ?? "SERVER") + " muted " + target.Serialize());
+ }
+
+ public static void Unmute(IAltPlayer target, IAltPlayer? executor)
+ {
+ target.Data.Muted = false;
+ ApplyPlayerData(target);
+ ChatController.BroadcastAdmins((executor?.Serialize() ?? "SERVER") + " unmuted " + target.Serialize());
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Controllers/StatsController.cs b/freeroam-extended/server/freeroam-extended/Controllers/StatsController.cs
new file mode 100644
index 0000000..b914139
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Controllers/StatsController.cs
@@ -0,0 +1,79 @@
+using System.IO;
+using System.Text.Json;
+using System.Threading.Tasks;
+using AltV.Net;
+
+namespace Freeroam_Extended
+{
+ public static class StatsController
+ {
+ private static readonly string UniquePlayersFile = "UniquePlayers.json";
+ private static readonly string StatsFile = "Stats.json";
+
+ public static HashSet UniquePlayers = new();
+ public static Stats StatsData = new ();
+
+ public static void Init()
+ {
+ if (File.Exists(UniquePlayersFile))
+ {
+ var json = File.ReadAllText(UniquePlayersFile);
+ try
+ {
+ UniquePlayers = JsonSerializer.Deserialize>(json) ?? new();
+ }
+ catch (Exception e)
+ {
+ Alt.LogError("Failed to parse unique players file!");
+ Alt.LogError(e.ToString());
+ }
+ }
+
+ if (File.Exists(StatsFile))
+ {
+ var json = File.ReadAllText(StatsFile);
+ try
+ {
+ StatsData = JsonSerializer.Deserialize(json) ?? new();
+ }
+ catch (Exception e)
+ {
+ Alt.LogError("Failed to parse stats file!");
+ Alt.LogError(e.ToString());
+ }
+ }
+ }
+
+ public static void UpdateStats()
+ {
+ File.WriteAllText(StatsFile, JsonSerializer.Serialize(StatsData));
+ }
+
+ public static void UpdateUniquePlayers()
+ {
+ File.WriteAllText(UniquePlayersFile, JsonSerializer.Serialize(UniquePlayers));
+ }
+
+ public static void AddUniquePlayer(string cloudId)
+ {
+ if (!UniquePlayers.Contains(cloudId))
+ {
+ UniquePlayers.Add(cloudId);
+ lock (StatsData)
+ {
+ StatsData.UniquePlayers++;
+ }
+ UpdateUniquePlayers();
+ }
+ }
+ }
+
+ public class Stats
+ {
+ public int VehiclesSpawned { get; set; }
+ public int VehiclesDestroyed { get; set; }
+ public int PlayerDeaths { get; set; }
+ public int PlayerConnections { get; set; }
+ public int UniquePlayers { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Controllers/VehicleController.cs b/freeroam-extended/server/freeroam-extended/Controllers/VehicleController.cs
new file mode 100644
index 0000000..f9e96c2
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Controllers/VehicleController.cs
@@ -0,0 +1,148 @@
+using System.Text.Json;
+using AltV.Net;
+using AltV.Net.Resources.Chat.Api;
+using Freeroam_Extended.Factories;
+
+namespace Freeroam_Extended;
+
+class VehicleListFile
+{
+ public bool IsWhitelist { get; set; }
+ public List List { get; set; }
+}
+
+public static class VehicleController
+{
+ private static readonly string VehicleListFile = "VehicleList.json";
+
+ public static bool IsWhitelist { get; set; }
+ public static string State => IsWhitelist ? "whitelist" : "blacklist";
+
+ public static List List { get; set; } = new();
+ public static HashSet ListHashes { get; set; } = new();
+
+ public static void Init()
+ {
+ IsWhitelist = false;
+ List = VehicleConstants.DefaultBlacklistModels;
+
+ if (File.Exists(VehicleListFile))
+ {
+ var json = File.ReadAllText(VehicleListFile);
+ try
+ {
+ var data = JsonSerializer.Deserialize(json) ?? new();
+ IsWhitelist = data.IsWhitelist;
+ List = data.List;
+ }
+ catch (Exception e)
+ {
+ Alt.LogError("Failed to parse vehicle list file!");
+ Alt.LogError(e.ToString());
+ }
+ }
+
+ UpdateHashes();
+ }
+
+ public static void Save()
+ {
+ var data = new VehicleListFile
+ {
+ IsWhitelist = IsWhitelist,
+ List = List
+ };
+ File.WriteAllText(VehicleListFile, JsonSerializer.Serialize(data));
+ }
+
+ public static bool CheckVehicle(string model)
+ {
+ if (IsWhitelist)
+ {
+ return ListHashes.Contains(Alt.Hash(model));
+ }
+ else
+ {
+ return !ListHashes.Contains(Alt.Hash(model));
+ }
+ }
+
+ public static bool CheckVehicle(uint model)
+ {
+ if (IsWhitelist)
+ {
+ return ListHashes.Contains(model);
+ }
+ else
+ {
+ return !ListHashes.Contains(model);
+ }
+ }
+
+ private static void UpdateHashes()
+ {
+ ListHashes = List.Select(Alt.Hash).ToHashSet();
+ }
+
+ public static void UpdateVehicles()
+ {
+ foreach (var altVehicle in Alt.GetAllVehicles())
+ {
+ var vehicle = (IAltVehicle)altVehicle;
+ if (vehicle.Owner is { IsAdmin: true }) continue;
+ if (CheckVehicle(vehicle.Model)) continue;
+
+ vehicle.Owner.SendChatMessage(ChatConstants.ErrorPrefix + "Your vehicle was removed!");
+ vehicle.Destroy();
+ }
+ }
+
+ public static void Allow(string model)
+ {
+ if (IsWhitelist)
+ {
+ List.Add(model);
+ }
+ else
+ {
+ List.Remove(model);
+ }
+
+ UpdateHashes();
+ Save();
+ UpdateVehicles();
+ }
+
+ public static void Block(string model)
+ {
+ if (IsWhitelist)
+ {
+ List.Remove(model);
+ }
+ else
+ {
+ List.Add(model);
+ }
+
+ UpdateHashes();
+ Save();
+ UpdateVehicles();
+ }
+
+ public static void UpdateState(bool whitelist)
+ {
+ IsWhitelist = whitelist;
+ List = whitelist ? VehicleConstants.DefaultWhitelistModels : VehicleConstants.DefaultBlacklistModels;
+ UpdateHashes();
+ Save();
+ UpdateVehicles();
+ }
+
+ public static void Clear()
+ {
+ List = new();
+ UpdateHashes();
+ Save();
+ UpdateVehicles();
+ }
+}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Controllers/VoiceController.cs b/freeroam-extended/server/freeroam-extended/Controllers/VoiceController.cs
new file mode 100644
index 0000000..6d1217c
--- /dev/null
+++ b/freeroam-extended/server/freeroam-extended/Controllers/VoiceController.cs
@@ -0,0 +1,64 @@
+using AltV.Net.Async;
+using AltV.Net;
+using AltV.Net.Elements.Entities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Freeroam_Extended
+{
+ static internal class VoiceController
+ {
+ public static IVoiceChannel LocalChannel = null!;
+ public static IVoiceChannel GlobalChannel = null!;
+
+ public static void Init()
+ {
+ LocalChannel = Alt.CreateVoiceChannel(true, 100);
+ GlobalChannel = Alt.CreateVoiceChannel(false, 0);
+ }
+
+ public static void AddPlayer(IPlayer player)
+ {
+ LocalChannel.AddPlayer(player);
+ GlobalChannel.AddPlayer(player);
+
+ GlobalChannel.MutePlayer(player);
+ }
+
+ public static void RemovePlayer(IPlayer player)
+ {
+ LocalChannel.RemovePlayer(player);
+ GlobalChannel.RemovePlayer(player);
+
+ GlobalChannel.MutePlayer(player);
+ }
+
+ public static void MutePlayer(IPlayer player)
+ {
+ LocalChannel.MutePlayer(player);
+ }
+
+ public static void UnmutePlayer(IPlayer player)
+ {
+ LocalChannel.UnmutePlayer(player);
+ }
+
+ public static void EnableGlobalVoice(IPlayer player)
+ {
+ GlobalChannel.UnmutePlayer(player);
+ }
+
+ public static void DisableGlobalVoice(IPlayer player)
+ {
+ GlobalChannel.MutePlayer(player);
+ }
+
+ public static bool IsGlobalVoiceEnabled(IPlayer player)
+ {
+ return GlobalChannel.IsPlayerMuted(player);
+ }
+ }
+}
diff --git a/freeroam-extended/server/freeroam-extended/EventHandler.cs b/freeroam-extended/server/freeroam-extended/EventHandler.cs
index 2fe415e..710d8d9 100644
--- a/freeroam-extended/server/freeroam-extended/EventHandler.cs
+++ b/freeroam-extended/server/freeroam-extended/EventHandler.cs
@@ -28,8 +28,13 @@ public EventHandler()
#endif
}
- altPlayer.EventCount++;
- if (altPlayer.EventCount > 100) altPlayer.Kick("Event count exceeded");
+ if (altPlayer.EventCount > 100)
+ {
+ altPlayer.Kick("Event count exceeded");
+ return;
+ }
+
+ altPlayer.IncrementEventCount();
};
}
@@ -38,18 +43,21 @@ public EventHandler()
[AsyncScriptEvent(ScriptEventType.PlayerConnect)]
public async Task OnPlayerConnect(IAltPlayer player, string reason)
{
- string cloudId = await player.RequestCloudId();
- if (cloudId == "invalid")
+ string cloudId = "";
+
+ try
+ {
+ cloudId = await player.RequestCloudId();
+ }
+ catch (Exception e)
{
player.Kick("Authorization error");
AltAsync.Log(
- $"HWID: {player.HardwareIdHash}, RS ID: {cloudId}. Tried to join the server with invalid RS ID.");
- return;
+ $"HWID: {player.HardwareIdHash}. Tried to join the server with invalid RS ID: {e}");
}
-
player.CloudID = cloudId;
- if (Misc.BannedPlayers.Contains(player.CloudID))
+ if (PlayerController.IsBanned(player.CloudID))
{
player.Kick("You're banned from this server!");
AltAsync.Log(
@@ -57,57 +65,48 @@ public async Task OnPlayerConnect(IAltPlayer player, string reason)
return;
}
- if (Misc.Operators.Contains(cloudId))
- player.IsAdmin = true;
+ if (PlayerController.PlayerData.TryGetValue(player.CloudID, out var data))
+ {
+ player.Data = data;
+ }
// select random entry from SpawnPoints
var randomSpawnPoint = Misc.AdminOverridedSpawnPos is not null
? Misc.AdminOverridedSpawnPos
: Misc.SpawnPositions.ElementAt(_random.Next(0, Misc.SpawnPositions.Length));
+
player.Spawn((Position)randomSpawnPoint + new Position(_random.Next(0, 10), _random.Next(0, 10), 0));
player.Model = (uint)PedModel.FreemodeMale01;
player.SetDateTime(DateTime.UtcNow);
player.SetWeather(Misc.Weather);
- player.Emit("draw_dmzone", Misc.DMPos.X, Misc.DMPos.Y, Misc.DMRadius, 150);
-
- if (player.IsAdmin)
- {
- player.Emit("set_chat_state", true);
- }
- else
- {
- player.Emit("set_chat_state", Misc.ChatState);
- }
+ player.Emit("draw_dmzone", Misc.DMPos.X, Misc.DMPos.Y, Misc.DMRadius);
- lock (StatsHandler.StatsData)
+ lock (StatsController.StatsData)
{
- StatsHandler.StatsData.PlayerConnections++;
- if (!Misc.UniquePlayers.Contains(player.CloudID))
- {
- StatsHandler.StatsData.UniquePlayers++;
- Misc.UniquePlayers.Add(player.CloudID);
- File.WriteAllText(@"UniquePlayers.json", JsonSerializer.Serialize(Misc.UniquePlayers));
- }
+ StatsController.StatsData.PlayerConnections++;
}
- Voice.AddPlayer(player);
+ StatsController.AddUniquePlayer(player.CloudID);
+
+ VoiceController.AddPlayer(player);
+ if (player.Data.Muted) VoiceController.MutePlayer(player);
if (Misc.IsResourceLoaded("c_clothesfit"))
{
await ClothesFitService.InitPlayer(player);
}
- player.RefreshFace();
- await player.RefreshClothes();
+ AppearanceController.RefreshFace(player);
+ await AppearanceController.RefreshClothes(player);
}
[ScriptEvent(ScriptEventType.VehicleDestroy)]
public void OnVehicleDestroy(IAltVehicle target)
{
- lock (StatsHandler.StatsData)
+ lock (StatsController.StatsData)
{
- StatsHandler.StatsData.VehiclesDestroyed++;
+ StatsController.StatsData.VehiclesDestroyed++;
}
target.Owner.SendChatMessage("Your Vehicle got destroyed. We removed it for you!");
@@ -117,7 +116,7 @@ public void OnVehicleDestroy(IAltVehicle target)
[ScriptEvent(ScriptEventType.PlayerDisconnect)]
public void OnPlayerDisconnect(IAltPlayer player, string reason)
{
- Voice.RemovePlayer(player);
+ VoiceController.RemovePlayer(player);
var vehicles = player.Vehicles;
@@ -137,77 +136,55 @@ public async Task OnPlayerDead(IAltPlayer player, IEntity killer, uint weapon)
{
var spawnPointPool = player.DmMode ? Misc.AirportSpawnPositions : Misc.SpawnPositions;
- var randomSpawnPoint = spawnPointPool.ElementAt(_random.Next(0, spawnPointPool.Length));
+ var randomSpawnPoint = Misc.AdminOverridedSpawnPos ?? spawnPointPool.ElementAt(_random.Next(0, spawnPointPool.Length));
player.Spawn(randomSpawnPoint + new Position(_random.Next(0, 10), _random.Next(0, 10), 0));
- lock (StatsHandler.StatsData)
+ lock (StatsController.StatsData)
{
- StatsHandler.StatsData.PlayerDeaths++;
+ StatsController.StatsData.PlayerDeaths++;
}
if (killer is not IAltPlayer killerPlayer) return;
if (!Misc.BlacklistedWeapons.Contains(weapon)) return;
- Alt.Core.LogColored(
- $"~r~ Banned Player: {killerPlayer.Name} ({killerPlayer.Id}) for using illegal weapon!");
- Misc.BannedPlayers.Add(killerPlayer.CloudID);
- string json = JsonSerializer.Serialize(Misc.BannedPlayers);
- await File.WriteAllTextAsync(@"BannedPlayers.json", json);
- killerPlayer.Kick("You're banned from this server!");
+
+ var name = killerPlayer.Serialize();
+ PlayerController.Ban(killerPlayer);
+ ChatController.BroadcastAdmins($"Banned player {name} for using illegal weapon!");
}
- [AsyncScriptEvent(ScriptEventType.ConsoleCommand)]
- public async Task OnConsoleCommand(string name, string[] args)
+ [ScriptEvent(ScriptEventType.ConsoleCommand)]
+ public void OnConsoleCommand(string name, string[] args)
{
- var playerPool = Alt.GetAllPlayers();
switch (name)
{
case "op":
+ {
if (args.Length is > 1 or 0)
{
Alt.Log("Usage: op ");
break;
}
- var playerOp = playerPool.FirstOrDefault(x => x.Id == int.Parse(args[0]));
- if (playerOp is not IAltPlayer playerOpAlt) return;
-
-
- if (Misc.Operators.Any(id => id == playerOpAlt.CloudID))
- {
- Alt.Log($"Id {args[0]} already is an operator!");
- break;
- }
-
- Misc.Operators.Add(playerOpAlt.CloudID);
- string json = JsonSerializer.Serialize(Misc.Operators);
- await File.WriteAllTextAsync(@"Operators.json", json);
-
- await playerOpAlt.EmitAsync("set_chat_state", true);
- playerOpAlt.IsAdmin = true;
+ var player = (IAltPlayer)Alt.GetPlayerById(uint.Parse(args[0]));
+ PlayerController.Op(player, null);
+ Alt.Log("Given operator permissions to " + player.Serialize());
break;
+ }
case "deop":
+ {
if (args.Length is > 1 or 0)
{
Alt.Log("Usage: deop ");
break;
}
- var playerDeOp = playerPool.FirstOrDefault(x => x.Id == int.Parse(args[0]));
- if (playerDeOp is not IAltPlayer playerDeOpAlt) return;
-
- if (!Misc.Operators.Any(id =>
- id == playerDeOpAlt.CloudID))
- {
- AltAsync.Log($"Id {args[0]} is not an operator!");
- break;
- }
-
- Misc.Operators.Remove(playerDeOpAlt.CloudID);
- await playerDeOpAlt.EmitAsync("set_chat_state", Misc.ChatState);
- playerDeOpAlt.IsAdmin = false;
+ var player = (IAltPlayer)Alt.GetPlayerById(uint.Parse(args[0]));
+ PlayerController.Deop(player, null);
+ Alt.Log("Removed operator permissions from " + player.Serialize());
break;
+ }
}
}
@@ -215,16 +192,13 @@ public async Task OnConsoleCommand(string name, string[] args)
public async Task OnWeaponDamage(IAltPlayer player, IEntity target, uint weapon, ushort damage,
Position shotOffset, BodyPart bodyPart)
{
+ if (!player.EnableWeaponUsage) return;
+
if (!Misc.BlacklistedWeapons.Contains(weapon) || player is not { } damagePlayer) return;
- Alt.Core.LogColored(
- $"~r~ Banned Player: {damagePlayer.Name} ({damagePlayer.Id}) for using illegal weapon!");
- //Misc.BannedPlayers.Add((damagePlayer.HardwareIdHash, damagePlayer.HardwareIdExHash));
- Misc.BannedPlayers.Add(damagePlayer.CloudID);
- string json = JsonSerializer.Serialize(Misc.BannedPlayers);
- await File.WriteAllTextAsync(@"BannedPlayers.json", json);
-
- player.Kick("You're banned from this server!");
+ var name = player.Serialize();
+ PlayerController.Ban(player);
+ ChatController.BroadcastAdmins($"Banned player {name} for using illegal weapon!");
}
[ScriptEvent(ScriptEventType.ColShape)]
@@ -256,39 +230,19 @@ public bool OnProjectileStart(IAltPlayer player, Position startPosition, Positio
return false;
}
- [ClientEvent("chat:message")]
- public void OnChatMessage(IAltPlayer player, params string[] args)
- {
- var message = string.Join("", args);
- if (args.Length == 0 || message.Length == 0) return;
-
- if (args[0].StartsWith("/")) return;
- if (!Misc.ChatState && !player.IsAdmin)
- {
- player.SendChatMessage("{FF0000}Chat is disabled!");
- return;
- }
-
- foreach (var p in Alt.GetAllPlayers())
- {
- p.SendChatMessage(
- $"{(player.IsAdmin ? "{008736}" : "{FFFFFF}")} {player.Name}({player.Id}): {{FFFFFF}}{message}");
- }
- }
-
[ClientEvent("tp_to_waypoint")]
public void TeleportToWaypoint(IAltPlayer player, int x, int y, int z)
{
if (!player.IsAdmin)
{
- player.SendChatMessage("{FF0000} No permission!");
+ player.SendChatMessage(ChatConstants.NoPermissions);
return;
}
-
+
if (player.IsInVehicle) player.Vehicle.Position = new Vector3(x, y, z);
else player.Position = new Vector3(x, y, z);
- player.SendChatMessage($"{{00FF00}} You were teleported to waypoint on {x}, {y}, {z}!");
+ player.SendChatMessage(ChatConstants.SuccessPrefix + $"You were teleported to waypoint on {x}, {y}, {z}!");
}
[ClientEvent("tp_to_coords")]
@@ -296,7 +250,7 @@ public void TeleportToCoords(IAltPlayer player, int x, int y, int z)
{
if (!player.IsAdmin)
{
- player.SendChatMessage("{FF0000} No permission!");
+ player.SendChatMessage(ChatConstants.NoPermissions);
return;
}
diff --git a/freeroam-extended/server/freeroam-extended/Factories/PlayerFactory.cs b/freeroam-extended/server/freeroam-extended/Factories/PlayerFactory.cs
index 003cfc3..1edb747 100644
--- a/freeroam-extended/server/freeroam-extended/Factories/PlayerFactory.cs
+++ b/freeroam-extended/server/freeroam-extended/Factories/PlayerFactory.cs
@@ -7,7 +7,7 @@
namespace Freeroam_Extended.Factories
{
- public partial interface IAltPlayer : IPlayer, IAsyncConvertible
+ public partial interface IAltPlayer : IPlayer
{
public IList Vehicles { get; set; }
public DateTime LastVehicleSpawn { get; set; }
@@ -15,14 +15,23 @@ public partial interface IAltPlayer : IPlayer, IAsyncConvertible
public bool EnableWeaponUsage { get; set; }
public bool DmMode { get; set; }
public bool NoClip { get; set; }
- public bool IsAdmin { get; set; }
- public int EventCount { get; set; }
+ public bool IsAdmin { get; }
+
+ public int EventCount { get; }
+ void ResetEventCount();
+ void IncrementEventCount();
+
public string CloudID { get; set; }
public long OutfitHash { get; set; }
public uint Sex { get; }
- public Task RefreshClothes();
- public Task EquipOutfit(uint outfitHash);
- public void RefreshFace();
+ public PlayerData Data { get; set; }
+ public string Serialize();
+ }
+
+ public class PlayerData
+ {
+ public bool Operator { get; set; }
+ public bool Muted { get; set; }
}
public partial class AltPlayer : AsyncPlayer, IAltPlayer
@@ -33,8 +42,9 @@ public partial class AltPlayer : AsyncPlayer, IAltPlayer
public bool EnableWeaponUsage { get; set; }
public bool DmMode { get; set; }
public bool NoClip { get; set; }
- public bool IsAdmin { get; set; }
- public int EventCount { get; set; }
+
+ public bool IsAdmin => Data.Operator;
+
public string CloudID { get; set; }
public long OutfitHash { get; set; }
public uint Sex => this.Model switch
@@ -44,124 +54,30 @@ public partial class AltPlayer : AsyncPlayer, IAltPlayer
_ => 2
};
- public AltPlayer(ICore server, IntPtr nativePointer, uint id) : base(server, nativePointer, id)
+ private int _eventCount;
+ public int EventCount => _eventCount;
+
+ public void ResetEventCount()
{
- Vehicles = new List();
+ Interlocked.Exchange(ref _eventCount, 0);
}
-
- public void RefreshFace()
+
+ public void IncrementEventCount()
{
- if (Sex == 1)
- {
- this.SetHeadBlendData(6, 21, 0, 6, 21, 0, 0.41f, 0.18f, 0.0f);
- this.SetHeadOverlay(0, 255, 1.0f);
- this.SetHeadOverlay(1, 255, 1.0f);
- this.SetHeadOverlay(2, 30, 1.0f);
- this.SetHeadOverlay(3, 255, 1.0f);
- this.SetHeadOverlay(4, 14, 1.0f);
- this.SetHeadOverlay(5, 1, 1.0f);
- this.SetHeadOverlay(6, 10, 0.85f);
- this.SetHeadOverlay(7, 255, 1.0f);
- this.SetHeadOverlay(8, 2, 1.0f);
- this.SetHeadOverlay(9, 0, 0.0f);
- this.SetHeadOverlay(10, 255, 1.0f);
- this.SetHeadOverlay(11, 255, 1.0f);
- this.SetHeadOverlay(12, 255, 1.0f);
-
- this.SetHeadOverlayColor(5, 2, 11, 0);
- this.SetHeadOverlayColor(8, 2, 6, 0);
-
- int hairs = Misc.RandomInt(1, 23);
- int hairsColor = Misc.RandomInt(1, 63);
- int hairsColor2 = Misc.RandomInt(1, 63);
-
- this.SetClothes(2, (ushort)hairs, 0, 0);
- this.HairColor = (byte)hairsColor;
- this.HairHighlightColor = (byte)hairsColor2;
- this.SetEyeColor(2);
-
- float[] featureParams = { -0.78f, 0, 0, -0.07f, 0.03f, 0, 0.07f, -0.44f, 0.07f, 0.02f, -0.95f, -0.74f, -1, -0.09f, -0.57f, 0.02f, -0.1f, -0.19f, -1, -1 };
- for (int i = 0; i < featureParams.Length; i++)
- {
- this.SetFaceFeature((byte)i, featureParams[i]);
- }
- }
- else if (Sex == 0)
- {
- this.SetHeadBlendData(2, 21, 0, 2, 21, 0, 0.5f, 0.72f, 0.0f);
- this.SetHeadOverlay(0, 255, 1.0f);
- this.SetHeadOverlay(1, 255, 1.0f);
- this.SetHeadOverlay(2, 30, 1.0f);
- this.SetHeadOverlay(3, 255, 1.0f);
- this.SetHeadOverlay(4, 255, 1.0f);
- this.SetHeadOverlay(5, 255, 1.0f);
- this.SetHeadOverlay(6, 255, 1.0f);
- this.SetHeadOverlay(7, 255, 1.0f);
- this.SetHeadOverlay(8, 0, 0.15f);
- this.SetHeadOverlay(9, 255, 1.0f);
- this.SetHeadOverlay(10, 255, 1.0f);
- this.SetHeadOverlay(11, 255, 1.0f);
- this.SetHeadOverlay(12, 255, 1.0f);
-
- this.SetHeadOverlayColor(5, 2, 32, 0);
- this.SetHeadOverlayColor(8, 2, 11, 0);
-
- int hairs = Misc.RandomInt(1, 22);
- int hairsColor = Misc.RandomInt(1, 63);
- int hairsColor2 = Misc.RandomInt(1, 63);
-
- this.SetClothes(2, (ushort)hairs, 0, 0);
- this.HairColor = (byte)hairsColor;
- this.HairHighlightColor = (byte)hairsColor2;
- this.SetEyeColor(3);
-
- float[] featureParams = { 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1 };
- for (int i = 0; i < featureParams.Length; i++)
- {
- this.SetFaceFeature((byte)i, featureParams[i]);
- }
- }
+ Interlocked.Increment(ref _eventCount);
}
- public async Task RefreshClothes()
- {
- if (!Misc.IsResourceLoaded("c_clothesfit"))
- return;
-
- if (Sex == 2)
- return;
-
- await ClothesFitService.DestroyPlayer(this);
- await ClothesFitService.InitPlayer(this);
+ public PlayerData Data { get; set; } = new();
- ulong[] outfits = await ClothesFitService.GetOutfitsBySex(Sex);
-
- int index = Misc.RandomInt(0, outfits.Length - 1);
- ulong randomElement = outfits[index];
-
- await ClothesFitService.Equip(this, (uint)randomElement);
+ public AltPlayer(ICore server, IntPtr nativePointer, uint id) : base(server, nativePointer, id)
+ {
+ Vehicles = new List();
}
- public async Task EquipOutfit(uint outfitHash)
+ public string Serialize()
{
- if (!Misc.IsResourceLoaded("c_clothesfit"))
- return;
-
- if (Sex == 2)
- return;
-
- await ClothesFitService.DestroyPlayer(this);
- await ClothesFitService.InitPlayer(this);
-
- ulong[] outfits = await ClothesFitService.GetOutfitsBySex(Sex);
-
- if (outfits.Contains(outfitHash))
- {
- await ClothesFitService.Equip(this, outfitHash);
- }
+ return this.Name + " [" + this.Id + "]";
}
-
- public new IAltPlayer ToAsync(IAsyncContext _) => this;
}
public class AltPlayerFactory : IEntityFactory
diff --git a/freeroam-extended/server/freeroam-extended/Freeroam-Extended.csproj b/freeroam-extended/server/freeroam-extended/Freeroam-Extended.csproj
index 0c68f16..7eea201 100644
--- a/freeroam-extended/server/freeroam-extended/Freeroam-Extended.csproj
+++ b/freeroam-extended/server/freeroam-extended/Freeroam-Extended.csproj
@@ -9,8 +9,9 @@
-
-
+
+
+
diff --git a/freeroam-extended/server/freeroam-extended/Main.cs b/freeroam-extended/server/freeroam-extended/Main.cs
index 1dd2aac..d650add 100644
--- a/freeroam-extended/server/freeroam-extended/Main.cs
+++ b/freeroam-extended/server/freeroam-extended/Main.cs
@@ -1,6 +1,8 @@
-using System.Text.Json;
+using System.Numerics;
+using System.Text.Json;
using AltV.Net;
using AltV.Net.Async;
+using AltV.Net.ColoredConsole;
using AltV.Net.Elements.Entities;
using Freeroam_Extended.Factories;
using Timer = System.Timers.Timer;
@@ -9,83 +11,35 @@ namespace Freeroam_Extended
{
public class Main : AsyncResource
{
- public Main() : base(true)
- {
- }
-
public override void OnStart()
{
- Alt.Core.LogColored("~g~ Freeroam-Extended Started!");
+ ChatController.Init();
+ PlayerController.Init();
+ VehicleController.Init();
+ VoiceController.Init();
+ StatsController.Init();
+
// colshape for weapon disabling everywhere but the airport
Alt.CreateColShapeSphere(Misc.DMPos, Misc.DMRadius);
- Voice.Init();
-
- if (!File.Exists(@"BannedPlayers.json"))
- {
- var hashSet = new HashSet>();
- var json = JsonSerializer.Serialize(hashSet);
- File.WriteAllText(@"BannedPlayers.json", json);
- }
- else
- {
- string json = File.ReadAllText(@"BannedPlayers.json") ?? "";
-
- var bannedPlayers = JsonSerializer.Deserialize>(json);
-
- Misc.BannedPlayers = bannedPlayers ?? new HashSet();
- }
-
- if (!File.Exists(@"Operators.json"))
- {
- var hashSet = new HashSet();
- var json = JsonSerializer.Serialize(hashSet);
- File.WriteAllText(@"Operators.json", json);
- }
- else
- {
- string json = File.ReadAllText(@"Operators.json") ?? "";
-
- var operators = JsonSerializer.Deserialize>(json);
-
- Misc.Operators = operators ?? new HashSet();
- }
-
- if (!File.Exists("Stats.json"))
- {
- var json = JsonSerializer.Serialize(StatsHandler.StatsData);
- File.WriteAllText("Stats.json", json);
- }
- else
- {
- var stats = JsonSerializer.Deserialize(File.ReadAllText("Stats.json"));
- if (stats != null) StatsHandler.StatsData = stats;
- }
- if (!File.Exists("UniquePlayers.json"))
- File.WriteAllText("UniquePlayers.json", JsonSerializer.Serialize(Misc.UniquePlayers));
- else
- {
- var uniquePlayers = JsonSerializer.Deserialize>(File.ReadAllText("UniquePlayers.json"));
- if (uniquePlayers != null) Misc.UniquePlayers = uniquePlayers;
- }
-
var fileWriteTimer = new Timer();
fileWriteTimer.Interval = 60000;
fileWriteTimer.Enabled = true;
fileWriteTimer.Elapsed += (sender, args) =>
{
- StatsHandler.UpdateFile();
+ StatsController.UpdateStats();
foreach (var p in Alt.GetAllPlayers())
{
var player = (IAltPlayer)p;
- player.EventCount = 0;
+ player.ResetEventCount();
}
};
+ Alt.LogColored(new ColoredMessage() + TextColor.Green + "Freeroam-Extended Started!");
}
public override void OnStop()
{
- Alt.Core.LogColored("~g~ Freeroam-Extended Stopped!");
+ Alt.LogColored(new ColoredMessage() + TextColor.Green + "Freeroam-Extended Stopped!");
}
public override IEntityFactory GetPlayerFactory()
diff --git a/freeroam-extended/server/freeroam-extended/Misc.cs b/freeroam-extended/server/freeroam-extended/Misc.cs
index 89abe19..fdae845 100644
--- a/freeroam-extended/server/freeroam-extended/Misc.cs
+++ b/freeroam-extended/server/freeroam-extended/Misc.cs
@@ -1,5 +1,6 @@
using AltV.Net;
using AltV.Net.Data;
+using AltV.Net.Enums;
namespace Freeroam_Extended
{
@@ -109,143 +110,6 @@ public static class Misc
4222310262
};
- public static HashSet BlacklistedVehicle = new ()
- {
- 1009171724,
- 1033245328,
- 1036591958,
- 1043222410,
- 1075432268,
- 1180875963,
- 1181327175,
- 1229411063,
- 1239571361,
- 1254014755,
- 1336872304,
- 1356124575,
- 1416466158,
- 1455990255,
- 1483171323,
- 1489874736,
- 1502869817,
- 1537277726,
- 1542143200,
- 1543134283,
- 1561920505,
- 1565978651,
- 159274291,
- 1593933419,
- 1637620610,
- 1653666139,
- 1692272545,
- 1721676810,
- 1742022738,
- 1897744184,
- 1909700336,
- 1938952078,
- 1945374990,
- 1949211328,
- 2038858402,
- 2044532910,
- 2069146067,
- 2071877360,
- 2139203625,
- 2176659152,
- 219613597,
- 2198148358,
- 2233918197,
- 2252616474,
- 2306538597,
- 2310691317,
- 2370166601,
- 2370534026,
- 2403970600,
- 2413121211,
- 2434067162,
- 2449479409,
- 2482017624,
- 2531412055,
- 2550461639,
- 2594093022,
- 2600885406,
- 2601952180,
- 2623428164,
- 2634305738,
- 2694714877,
- 2704629607,
- 276773164,
- 2816263004,
- 2859440138,
- 2908775872,
- 2919906639,
- 2920466844,
- 295054921,
- 3001042683,
- 3013282534,
- 3040635986,
- 3052358707,
- 3084515313,
- 3147997943,
- 3188846534,
- 3314393930,
- 3319621991,
- 3493417227,
- 353883353,
- 3539435063,
- 3545667823,
- 3568198617,
- 3579220348,
- 3602674979,
- 3606777648,
- 3656405053,
- 3715219435,
- 373261600,
- 3806844075,
- 3884762073,
- 3902291871,
- 3903371924,
- 394110044,
- 3955379698,
- 4018222598,
- 4081974053,
- 408970549,
- 4180339789,
- 4212341271,
- 4252008158,
- 4262088844,
- 4262731174,
- 4267640610,
- 433954513,
- 444994115,
- 447548909,
- 509498602,
- 540101442,
- 562680400,
- 628003514,
- 668439077,
- 679453769,
- 682434785,
- 710198397,
- 744705981,
- 745926877,
- 782665360,
- 788747387,
- 837858166,
- 840387324,
- 867467158,
- 884483972,
- 886810209,
- 903794909,
- 941494461,
- 970385471,
- 1058115860,
- 1981688531,
- 4143991942,
- 368211810,
- 3681241380,
- 3987008919,
- };
-
public static readonly Position[] SpawnPositions = {
new (-1734.69885f,-1108.47033f, 14.05346f ), // Pier
new (-2162.94067f, -398.45275f,14.373657f), // Parking Lot at the beach-highway
@@ -297,22 +161,6 @@ public static class Misc
new (-675.2044f, -2378.4658f, 13.087158f),
};
- public static HashSet BannedPlayers = new()
- {
-
- };
-
- public static HashSet Operators = new()
- {
-
- };
-
- public static HashSet UniquePlayers = new()
- {
-
- };
-
- public static bool ChatState = true;
public static int Hour = 11;
public static uint Weather = 0;
diff --git a/freeroam-extended/server/freeroam-extended/StatsHandler.cs b/freeroam-extended/server/freeroam-extended/StatsHandler.cs
deleted file mode 100644
index 16bdc56..0000000
--- a/freeroam-extended/server/freeroam-extended/StatsHandler.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.IO;
-using System.Text.Json;
-using System.Threading.Tasks;
-
-namespace Freeroam_Extended
-{
- public static class StatsHandler
- {
- public static Stats StatsData = new ();
-
- public static Task UpdateFile()
- {
- File.WriteAllText("Stats.json", JsonSerializer.Serialize(StatsData));
- return Task.CompletedTask;
- }
- }
-
- public class Stats
- {
- public int VehiclesSpawned { get; set; }
- public int VehiclesDestroyed { get; set; }
- public int PlayerDeaths { get; set; }
- public int PlayerConnections { get; set; }
- public int UniquePlayers { get; set; }
- }
-}
\ No newline at end of file
diff --git a/freeroam-extended/server/freeroam-extended/Voice.cs b/freeroam-extended/server/freeroam-extended/Voice.cs
deleted file mode 100644
index f04c0e2..0000000
--- a/freeroam-extended/server/freeroam-extended/Voice.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using AltV.Net.Async;
-using AltV.Net;
-using AltV.Net.Elements.Entities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Freeroam_Extended
-{
- static internal class Voice
- {
- static IVoiceChannel localChannel;
- static IVoiceChannel globalChannel;
-
- public static void Init()
- {
- localChannel = Alt.CreateVoiceChannel(true, 100);
- globalChannel = Alt.CreateVoiceChannel(false, 0);
- }
-
- public static void AddPlayer(IPlayer player)
- {
- localChannel.AddPlayer(player);
- globalChannel.AddPlayer(player);
-
- globalChannel.MutePlayer(player);
- }
-
- public static void RemovePlayer(IPlayer player)
- {
- localChannel.RemovePlayer(player);
- globalChannel.RemovePlayer(player);
-
- globalChannel.MutePlayer(player);
- }
-
- public static void EnableGlobalVoice(IPlayer player)
- {
- globalChannel.UnmutePlayer(player);
- }
-
- public static void DisableGlobalVoice(IPlayer player)
- {
- globalChannel.MutePlayer(player);
- }
-
- public static bool IsGlobalVoiceEnabled(IPlayer player)
- {
- return globalChannel.IsPlayerMuted(player);
- }
- }
-}