From 07a7f25730ef5e71277c1307aa0d576688bb1be4 Mon Sep 17 00:00:00 2001 From: hydrant Date: Tue, 7 May 2019 20:55:25 +0200 Subject: [PATCH] add cityhall menu, add self interaction menu (Arrow Down), fix freecam, add group creation, move (faction) invite from commands to menu --- ReallifeGamemode.Client/Gui/cityhall.ts | 70 +++++ .../Interaction/interactionmenu.ts | 123 +++++++++ ReallifeGamemode.Client/Player/freecam.ts | 254 +++++++++--------- ReallifeGamemode.Client/global.d.ts | 9 + ReallifeGamemode.Client/index.ts | 6 + ReallifeGamemode.Client/inputhelper/index.ts | 18 +- .../Commands/FactionCommands.cs | 28 +- .../Commands/GroupCommands.cs | 31 +++ .../Commands/UserCommands.cs | 45 +--- ReallifeGamemode.Server/Events/Key.cs | 121 +++++---- .../Extensions/ClientExtension.cs | 30 +-- ...minLevelExtension.cs => EnumExtensions.cs} | 17 +- ReallifeGamemode.Server/Main.cs | 1 + .../Managers/CityHallManager.cs | 67 +++++ .../Managers/InteractionManager.cs | 106 ++++++++ .../Managers/InteriorManager.cs | 4 +- .../Services/ChatService.cs | 14 + 17 files changed, 666 insertions(+), 278 deletions(-) create mode 100644 ReallifeGamemode.Client/Gui/cityhall.ts create mode 100644 ReallifeGamemode.Client/Interaction/interactionmenu.ts create mode 100644 ReallifeGamemode.Server/Commands/GroupCommands.cs rename ReallifeGamemode.Server/Extensions/{AdminLevelExtension.cs => EnumExtensions.cs} (68%) create mode 100644 ReallifeGamemode.Server/Managers/CityHallManager.cs diff --git a/ReallifeGamemode.Client/Gui/cityhall.ts b/ReallifeGamemode.Client/Gui/cityhall.ts new file mode 100644 index 00000000..12c14b24 --- /dev/null +++ b/ReallifeGamemode.Client/Gui/cityhall.ts @@ -0,0 +1,70 @@ +import * as NativeUI from 'NativeUI'; + +const Menu = NativeUI.Menu; +const UIMenuItem = NativeUI.UIMenuItem; +const UIMenuListItem = NativeUI.UIMenuListItem; +const UIMenuCheckboxItem = NativeUI.UIMenuCheckboxItem; +const BadgeStyle = NativeUI.BadgeStyle; +const Point = NativeUI.Point; +const ItemsCollection = NativeUI.ItemsCollection; +const Color = NativeUI.Color; + +import InputHelper from '../inputhelper'; + +export default function (globalData: GlobalData) { + + var keyBound = false; + var menu: NativeUI.Menu = null; + + mp.events.add("SERVER:CityHall_ShowHelpText", () => { + mp.game.ui.setTextComponentFormat('STRING'); + mp.game.ui.addTextComponentSubstringPlayerName('Drücke ~INPUT_CONTEXT~, um das Stadthallen-Menü zu öffnen'); + mp.game.ui.displayHelpTextFromStringLabel(0, true, true, -1); + + if (!keyBound) { + keyBound = true; + mp.keys.bind(0x45, false, keyPressHandler); + } + }); + + mp.events.add("SERVER:CityHall_ClearHelpText", () => { + mp.game.ui.clearHelp(false); + if (keyBound) { + mp.keys.unbind(0x45, false, keyPressHandler); + keyBound = false; + } + }); + + function keyPressHandler(): void { + if (globalData.InChat || globalData.Interaction) return; + menu = new Menu("Stadthalle", "", new Point(50, 50), null, null); + + globalData.Interaction = true; + mp.gui.chat.show(false); + + var groupCreateItem = new UIMenuItem("Gruppe erstellen", "Erstelle eine neue Gruppe"); + groupCreateItem.SetRightLabel("~g~50.000$"); + menu.AddItem(groupCreateItem); + + var cancelItem = new UIMenuItem("Schließen"); + cancelItem.BackColor = new Color(213, 0, 0); + cancelItem.HighlightedBackColor = new Color(229, 57, 53); + menu.AddItem(cancelItem); + + menu.ItemSelect.on((item, index) => { + if (index === 0) { // Gruppe + var input = new InputHelper("Wie soll die Gruppe heißen?"); + input.show(); + input.getValue((name: string) => { + mp.events.callRemote("CLIENT:CityHall_CreateGroup", name); + }); + } + menu.Close(); + }); + + menu.MenuClose.on(() => { + globalData.Interaction = false; + mp.gui.chat.show(true); + }); + } +} \ No newline at end of file diff --git a/ReallifeGamemode.Client/Interaction/interactionmenu.ts b/ReallifeGamemode.Client/Interaction/interactionmenu.ts new file mode 100644 index 00000000..a3a826b8 --- /dev/null +++ b/ReallifeGamemode.Client/Interaction/interactionmenu.ts @@ -0,0 +1,123 @@ +import * as NativeUI from 'NativeUI'; +import InputHelper from '../inputhelper'; + +const Menu = NativeUI.Menu; +const UIMenuItem = NativeUI.UIMenuItem; +const UIMenuListItem = NativeUI.UIMenuListItem; +const UIMenuCheckboxItem = NativeUI.UIMenuCheckboxItem; +const BadgeStyle = NativeUI.BadgeStyle; +const Point = NativeUI.Point; +const ItemsCollection = NativeUI.ItemsCollection; +const Color = NativeUI.Color; + +export default function (globalData: GlobalData) { + + var menuClose = false; + + var accountItem = new UIMenuItem("Account", "Account Informationen"); + + var factionItem = new UIMenuItem("Fraktion", "Verwalte deine Fraktion"); + var groupItem = new UIMenuItem("Gruppe", "Verwalte deine Gruppe"); + + + mp.events.add("SERVER:InteractionMenu_OpenMenu", (accountDataJson: string, faction: string, group: string, factionInvite: boolean, groupInvite: boolean) => { + var accountData: AccountData = JSON.parse(accountDataJson); + + var menu = getInteractionMenu(); + + menu.AddItem(accountItem); + menu.BindMenuToItem(getAccountMenu(accountData), accountItem); + + if (faction) { + factionItem.SetRightLabel(faction); + menu.AddItem(factionItem); + menu.BindMenuToItem(getFactionMenu(faction), factionItem); + } + + if (group) { + groupItem.SetRightLabel(group); + menu.AddItem(groupItem); + menu.BindMenuToItem(getGroupMenu(group), groupItem); + } + + var items: Array = new Array(); + if (factionInvite) items.push("Fraktion"); + if (groupInvite) items.push("Gruppe"); + var acceptItem = new UIMenuListItem("Einladung annehmen", "", new ItemsCollection(items)); + + if (items.length !== 0) menu.AddItem(acceptItem); + + menu.Visible = true; + mp.gui.chat.show(false); + globalData.Interaction = true; + + menu.MenuClose.on(() => { + globalData.Interaction = false; + mp.gui.chat.show(true); + }) + }); + + function getInteractionMenu(): NativeUI.Menu { + return new Menu("Hauptmenü", "Interaktionen | " + mp.players.local.name, new Point(50, 50), null, null); + } + + function getAccountMenu(data: AccountData): NativeUI.Menu { + var accountMenu = new NativeUI.Menu("Account", mp.players.local.name, new Point(50, 50), null, null); + + var menuItem = new UIMenuItem("Fraktion"); + menuItem.SetRightLabel(data.faction); + accountMenu.AddItem(menuItem); + + menuItem = new UIMenuItem("Fraktionsrang"); + menuItem.SetRightLabel(data.factionRank); + accountMenu.AddItem(menuItem); + + menuItem = new UIMenuItem("Gruppe"); + menuItem.SetRightLabel(data.group); + accountMenu.AddItem(menuItem); + + menuItem = new UIMenuItem("Gruppenrang"); + menuItem.SetRightLabel(data.groupRank); + accountMenu.AddItem(menuItem); + + menuItem = new UIMenuItem("Registrierungsdatum"); + menuItem.SetRightLabel(data.regDate); + accountMenu.AddItem(menuItem); + + menuItem = new UIMenuItem("Adminrang"); + menuItem.SetRightLabel(data.adminLevel); + accountMenu.AddItem(menuItem); + + accountMenu.Visible = false; + return accountMenu; + } + + function getFactionMenu(faction: string): NativeUI.Menu { + var factionMenu = new NativeUI.Menu("Fraktion", faction, new Point(50, 50), null, null); + factionMenu.AddItem(new UIMenuItem("Spieler einladen")); + factionMenu.AddItem(new UIMenuItem("Spieler rauswerfen")); + factionMenu.Visible = false; + + factionMenu.ItemSelect.on((item, index) => { + if (index === 0) { // Inviten + var input = new InputHelper("Welchen Spieler möchtest du inviten (Name / ID)?"); + input.show(); + input.getValue(name => { + mp.events.callRemote("CLIENT:InteractionMenu_InviteFaction", name); + }); + } else if (index === 1) { // Uninviten + } + }) + + return factionMenu; + } + + function getGroupMenu(group: string): NativeUI.Menu { + var groupMenu = new NativeUI.Menu("Gruppe", group, new Point(50, 50), null, null); + groupMenu.AddItem(new UIMenuItem("Spieler einladen")); + groupMenu.AddItem(new UIMenuItem("Spieler rauswerfen")); + groupMenu.Visible = false; + + return groupMenu; + } +} \ No newline at end of file diff --git a/ReallifeGamemode.Client/Player/freecam.ts b/ReallifeGamemode.Client/Player/freecam.ts index 5eb1b2fa..d17f4928 100644 --- a/ReallifeGamemode.Client/Player/freecam.ts +++ b/ReallifeGamemode.Client/Player/freecam.ts @@ -1,135 +1,131 @@ -export default function freeCam() { - const controlsIds = { - F5: 327, - W: 32, // 232 - S: 33, // 31, 219, 233, 268, 269 - A: 34, // 234 - D: 35, // 30, 218, 235, 266, 267 - Space: 321, - LCtrl: 326 +export default function () { + var getNormalizedVector = function (vector) { + var mag = Math.sqrt( + vector.x * vector.x + vector.y * vector.y + vector.z * vector.z + ); + vector.x = vector.x / mag; + vector.y = vector.y / mag; + vector.z = vector.z / mag; + return vector; }; - - var global = { - gameplayCam: undefined, - fly: undefined + var getCrossProduct = function (v1, v2) { + var vector = new mp.Vector3(0, 0, 0); + vector.x = v1.y * v2.z - v1.z * v2.y; + vector.y = v1.z * v2.x - v1.x * v2.z; + vector.z = v1.x * v2.y - v1.y * v2.x; + return vector; }; - - global.fly = { - flying: false, f: 2.0, w: 2.0, h: 2.0, point_distance: 1000, l:0 + var bindVirtualKeys = { + F2: 0x71 }; - global.gameplayCam = mp.cameras.new('gameplay'); - - mp.game.graphics.notify('~r~Fly script loaded!'); - mp.game.graphics.notify('~r~F5~w~ - enable/disable\n~r~F5+Space~w~ - disable without warping to ground\n~r~W/A/S/D/Space/LCtrl~w~ - move'); - mp.game.graphics.notify('~r~/savecam~w~ - save Camera position.'); - - let direction = null; - let coords = null; - - function pointingAt(distance) { - const farAway = new mp.Vector3((direction.x * distance) + (coords.x), (direction.y * distance) + (coords.y), (direction.z * distance) + (coords.z)); - - const result = mp.raycasting.testPointToPoint(coords, farAway, 16); - if (result === undefined) { - return 'undefined'; - } - return result; - } - - mp.events.add('render', () => { - - const controls = mp.game.controls; - const fly = global.fly; - direction = global.gameplayCam.getDirection(); - coords = global.gameplayCam.getCoord(); - - coords.x = coords.x.toFixed(2); - coords.y = coords.y.toFixed(2); - coords.z = coords.z.toFixed(2); - - direction.x = direction.x.toFixed(2); - direction.y = direction.y.toFixed(2); - direction.z = direction.z.toFixed(2); - - //mp.game.graphics.drawText(`Coords: ${JSON.stringify(coords)}`, [0.5, 0.005], { - // font: 0, - // color: [255, 255, 255, 185], - // scale: [0.3, 0.3], - // outline: true, - // centre: false - //}); - - if (controls.isControlJustPressed(0, controlsIds.F5)) { - fly.flying = !fly.flying; - - const player = mp.players.local; - - player.setInvincible(fly.flying); - player.freezePosition(fly.flying); - player.setAlpha(fly.flying ? 0 : 255); - - if (!fly.flying && !controls.isControlPressed(0, controlsIds.Space)) { - const position = mp.players.local.position; - position.z = mp.game.gameplay.getGroundZFor3dCoord(position.x, position.y, position.z, 0.0, false); - mp.players.local.setCoordsNoOffset(position.x, position.y, position.z, 0, 0, 0); - } - - mp.game.graphics.notify(fly.flying ? 'Fly: ~g~Enabled' : 'Fly: ~r~Disabled'); - } else if (fly.flying) { - let updated = false; - const position = mp.players.local.position; - - if (controls.isControlPressed(0, controlsIds.W)) { - if (fly.f < 8.0) { fly.f *= 1.025; } - - position.x += direction.x * fly.f; - position.y += direction.y * fly.f; - position.z += direction.z * fly.f; - updated = true; - } else if (controls.isControlPressed(0, controlsIds.S)) { - if (fly.f < 8.0) { fly.f *= 1.025; } - - position.x -= direction.x * fly.f; - position.y -= direction.y * fly.f; - position.z -= direction.z * fly.f; - updated = true; - } else { - fly.f = 2.0; - } - - if (controls.isControlPressed(0, controlsIds.A)) { - if (fly.l < 8.0) { fly.l *= 1.025; } - - position.x += (-direction.y) * fly.l; - position.y += direction.x * fly.l; - updated = true; - } else if (controls.isControlPressed(0, controlsIds.D)) { - if (fly.l < 8.0) { fly.l *= 1.05; } - - position.x -= -direction.y * fly.l; - position.y -= direction.x * fly.l; - updated = true; - } else { - fly.l = 2.0; - } - - if (controls.isControlPressed(0, controlsIds.Space)) { - if (fly.h < 8.0) { fly.h *= 1.025; } - - position.z += fly.h; - updated = true; - } else if (controls.isControlPressed(0, controlsIds.LCtrl)) { - if (fly.h < 8.0) { fly.h *= 1.05; } - - position.z -= fly.h; - updated = true; - } else { - fly.h = 2.0; - } - - if (updated) { - mp.players.local.setCoordsNoOffset(position.x, position.y, position.z, 0, 0, 0); - } + var bindASCIIKeys = { + Q: 69, + E: 81, + LCtrl: 17, + Shift: 16 + }; + mp.game.graphics.notify('~r~NoClip ~w~by ~b~Morbo'); + var isNoClip = false; + var noClipCamera; + var shiftModifier = false; + var controlModifier = false; + var localPlayer = mp.players.local; + mp.keys.bind(bindVirtualKeys.F2, true, function () { + isNoClip = !isNoClip; + mp.game.ui.displayRadar(!isNoClip); + if (isNoClip) { + startNoClip(); + } else { + stopNoClip(); } }); + function startNoClip() { + mp.game.graphics.notify('NoClip ~g~activated'); + var camPos = new mp.Vector3( + localPlayer.position.x, + localPlayer.position.y, + localPlayer.position.z + ); + var camRot = mp.game.cam.getGameplayCamRot(2); + noClipCamera = mp.cameras.new('default', camPos, camRot, 45); + noClipCamera.setActive(true); + mp.game.cam.renderScriptCams(true, false, 0, true, false); + localPlayer.freezePosition(true); + localPlayer.setInvincible(true); + localPlayer.setVisible(false, false); + localPlayer.setCollision(false, false); + } + function stopNoClip() { + mp.game.graphics.notify('NoClip ~r~disabled'); + if (noClipCamera) { + localPlayer.position = noClipCamera.getCoord(); + localPlayer.setHeading(noClipCamera.getRot(2).z); + noClipCamera.destroy(true); + noClipCamera = null; + } + mp.game.cam.renderScriptCams(false, false, 0, true, false); + localPlayer.freezePosition(false); + localPlayer.setInvincible(false); + localPlayer.setVisible(true, false); + localPlayer.setCollision(true, false); + } + mp.events.add('render', function () { + if (!noClipCamera || mp.gui.cursor.visible) { + return; + } + controlModifier = mp.keys.isDown(bindASCIIKeys.LCtrl); + shiftModifier = mp.keys.isDown(bindASCIIKeys.Shift); + var rot = noClipCamera.getRot(2); + var fastMult = 1; + var slowMult = 1; + if (shiftModifier) { + fastMult = 3; + } else if (controlModifier) { + slowMult = 0.5; + } + var rightAxisX = mp.game.controls.getDisabledControlNormal(0, 220); + var rightAxisY = mp.game.controls.getDisabledControlNormal(0, 221); + var leftAxisX = mp.game.controls.getDisabledControlNormal(0, 218); + var leftAxisY = mp.game.controls.getDisabledControlNormal(0, 219); + var pos = noClipCamera.getCoord(); + var rr = noClipCamera.getDirection(); + var vector = new mp.Vector3(0, 0, 0); + vector.x = rr.x * leftAxisY * fastMult * slowMult; + vector.y = rr.y * leftAxisY * fastMult * slowMult; + vector.z = rr.z * leftAxisY * fastMult * slowMult; + var upVector = new mp.Vector3(0, 0, 1); + var rightVector = getCrossProduct( + getNormalizedVector(rr), + getNormalizedVector(upVector) + ); + rightVector.x *= leftAxisX * 0.5; + rightVector.y *= leftAxisX * 0.5; + rightVector.z *= leftAxisX * 0.5; + var upMovement = 0.0; + if (mp.keys.isDown(bindASCIIKeys.Q)) { + upMovement = 0.5; + } + var downMovement = 0.0; + if (mp.keys.isDown(bindASCIIKeys.E)) { + downMovement = 0.5; + } + mp.players.local.position = new mp.Vector3( + pos.x + vector.x + 1, + pos.y + vector.y + 1, + pos.z + vector.z + 1 + ); + mp.players.local.heading = rr.z; + noClipCamera.setCoord( + pos.x - vector.x + rightVector.x, + pos.y - vector.y + rightVector.y, + pos.z - vector.z + rightVector.z + upMovement - downMovement + ); + noClipCamera.setRot( + rot.x + rightAxisY * -5.0, + 0.0, + rot.z + rightAxisX * -5.0, + 2 + ); + }); + } \ No newline at end of file diff --git a/ReallifeGamemode.Client/global.d.ts b/ReallifeGamemode.Client/global.d.ts index 359d27a7..212bc409 100644 --- a/ReallifeGamemode.Client/global.d.ts +++ b/ReallifeGamemode.Client/global.d.ts @@ -6,6 +6,15 @@ LoggedIn: boolean } +declare interface AccountData { + regDate: string; + adminLevel: string; + faction: string; + factionRank: string; + group: string; + groupRank: string; +} + declare interface FactionRanks { factionId: number, ranks: FactionRank[] diff --git a/ReallifeGamemode.Client/index.ts b/ReallifeGamemode.Client/index.ts index 3b68b547..00b61507 100644 --- a/ReallifeGamemode.Client/index.ts +++ b/ReallifeGamemode.Client/index.ts @@ -12,6 +12,9 @@ let globalData: GlobalData = { LoggedIn: false }; +import cityHall from './Gui/cityhall'; +cityHall(globalData); + import voice from './Voice/main'; voice(globalData); @@ -66,6 +69,9 @@ worldInteraction(); import playerInteraction from './Interaction/playerinteraction'; playerInteraction(globalData); +import interactionMenu from './Interaction/interactionmenu'; +interactionMenu(globalData); + import Login from './Login/main'; Login(globalData); diff --git a/ReallifeGamemode.Client/inputhelper/index.ts b/ReallifeGamemode.Client/inputhelper/index.ts index 6e3c04aa..aa15e12d 100644 --- a/ReallifeGamemode.Client/inputhelper/index.ts +++ b/ReallifeGamemode.Client/inputhelper/index.ts @@ -1,8 +1,8 @@ export default class InputHelper { - title: string; - value: string; - created: boolean; - browser: BrowserMp; + private title: string; + private value: string; + private created: boolean; + private browser: BrowserMp; constructor(title: string) { this.title = title; @@ -23,7 +23,7 @@ mp.events.add('render', this.disableControls); } - disableControls() { + private disableControls() { for (var i = 0; i <= 33; i++) { mp.game.controls.disableAllControlActions(i); } @@ -35,7 +35,7 @@ this.browser = mp.browsers.new('package://assets/html/inputhelper/index.html'); } - finish() { + private finish() { if (this.browser) { mp.events.remove('cef_inputhelper_sendvalue'); mp.events.remove('cef_request_title'); @@ -45,16 +45,16 @@ } } - cefTitleCall() { + private cefTitleCall() { this.browser.execute(`setTitle('${this.title}')`); } - cefCallback(val) { + private cefCallback(val) { this.value = val; this.finish(); } - valueGetter() { + private valueGetter(): Promise { return new Promise(resolve => { setInterval(() => { if (this.value !== undefined) resolve(this.value); diff --git a/ReallifeGamemode.Server/Commands/FactionCommands.cs b/ReallifeGamemode.Server/Commands/FactionCommands.cs index fb7afe16..bebde9d7 100644 --- a/ReallifeGamemode.Server/Commands/FactionCommands.cs +++ b/ReallifeGamemode.Server/Commands/FactionCommands.cs @@ -71,36 +71,10 @@ namespace ReallifeGamemode.Server.Commands } #endregion #region Leader Commands - [Command("invite", "~m~Benutzung: ~s~/invite [Name]")] public void CmdFactionInvite(Client player, string name) { - if (player.GetUser()?.FactionId == null || player.GetUser().FactionLeader == false) - { - ChatService.NotAuthorized(player); - return; - } - - Client target = ClientService.GetClientByNameOrId(name); - if (target == null || !target.IsLoggedIn()) - { - ChatService.PlayerNotFound(player); - return; - } - - if (target.GetUser()?.FactionId != null) - { - ChatService.Error(player, "Dieser Spieler ist schon in einer Fraktion"); - return; - } - - target.SetData("accept_invite", player.Handle); - - player.SendChatMessage("!{02FCFF}Du hast dem Spieler " + target.Name + " eine Einladung in deine Fraktion gesendet."); - target.SendChatMessage("!{02FCFF}Du hast von " + player.Name + " eine Einladung in die Fraktion \"" + player.GetUser().Faction.Name + "\" erhalten."); - target.SendChatMessage("!{02FCFF}Benutze '/accept invite', um die Einladung anzunehmen"); - - return; + } [Command("giverank", "~m~Benutzung: ~s~/giverank [Name] [Rang]", GreedyArg = true)] diff --git a/ReallifeGamemode.Server/Commands/GroupCommands.cs b/ReallifeGamemode.Server/Commands/GroupCommands.cs new file mode 100644 index 00000000..d8620fad --- /dev/null +++ b/ReallifeGamemode.Server/Commands/GroupCommands.cs @@ -0,0 +1,31 @@ +using GTANetworkAPI; +using ReallifeGamemode.Server.Extensions; +using ReallifeGamemode.Server.Services; +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace ReallifeGamemode.Server.Commands +{ + class GroupCommands : Script + { + #region Chat Commands + [Command("g", "~m~Benutzung: ~s~/g [Nachricht]", GreedyArg = true)] + public void CmdGroupG(Client player, string message) + { + Entities.Group group = player.GetUser().Group; + if (group == null) + { + ChatService.NotAuthorized(player); + return; + } + + message = Regex.Replace(message, "(~[a-zA-Z]~{1})|(!{(.*)})", ""); + message = $"{player.Name}: {message}"; + + ChatService.BroadcastGroup(message, group); + } + #endregion + } +} diff --git a/ReallifeGamemode.Server/Commands/UserCommands.cs b/ReallifeGamemode.Server/Commands/UserCommands.cs index b39507d3..c1df6a63 100644 --- a/ReallifeGamemode.Server/Commands/UserCommands.cs +++ b/ReallifeGamemode.Server/Commands/UserCommands.cs @@ -21,40 +21,7 @@ namespace ReallifeGamemode.Server.Commands { case "invite": { - if (!player.HasData("accept_invite")) - { - ChatService.Error(player, "Du hast keine Einladung in eine Fraktion erhalten"); - return; - } - - player.ResetData("accept_data"); - - using (var dbContext = new DatabaseContext()) - { - Client leader = NAPI.Player.GetPlayerFromHandle((NetHandle)player.GetData("accept_invite")); - - if (leader == null) - { - ChatService.Error(player, "Die Einladung ist abgelaufen"); - return; - } - - User u = leader.GetUser(dbContext); - User own = player.GetUser(dbContext); - - own.FactionId = u.FactionId; - own.FactionLeader = false; - own.FactionRankId = dbContext - .FactionRanks - .OrderBy(x => x.Order) - .Where(r => r.FactionId == own.FactionId) - .FirstOrDefault()?.Id ?? null; - - leader.SendChatMessage("!{02FCFF}" + player.Name + " hat die Einladung angenommen."); - player.SendChatMessage("!{02FCFF}Du hast die Einladung angenommen."); - - dbContext.SaveChanges(); - } + break; } } @@ -73,16 +40,10 @@ namespace ReallifeGamemode.Server.Commands if (player.GetUser().IsAdmin(AdminLevel.SUPPORTER)) { player.SendChatMessage("~m~" + ((VehicleHash)pVeh.Model) + " | " + veh.ToString() + " | Farbe 1: " + pVeh.PrimaryColor + " | Farbe 2: " + pVeh.SecondaryColor + " | ID: " + pVeh.Handle.Value); - } - else - { - player.SendChatMessage("~m~" + ((VehicleHash)pVeh.Model) + " | Farbe 1: " + pVeh.PrimaryColor + " | Farbe 2: " + pVeh.SecondaryColor + " | ID: " + pVeh.Handle.Value); + return; } } - else - { - player.SendChatMessage("~m~" + ((VehicleHash)pVeh.Model) + " | Farbe 1: " + pVeh.PrimaryColor + " | Farbe 2: " + pVeh.SecondaryColor + " | ID: " + pVeh.Handle.Value); - } + player.SendChatMessage("~m~" + ((VehicleHash)pVeh.Model) + " | Farbe 1: " + pVeh.PrimaryColor + " | Farbe 2: " + pVeh.SecondaryColor + " | ID: " + pVeh.Handle.Value); } } } diff --git a/ReallifeGamemode.Server/Events/Key.cs b/ReallifeGamemode.Server/Events/Key.cs index c6881b9b..6da7c8cb 100644 --- a/ReallifeGamemode.Server/Events/Key.cs +++ b/ReallifeGamemode.Server/Events/Key.cs @@ -46,6 +46,7 @@ namespace ReallifeGamemode.Server.Events GroundItem.PickUpGroundItem(player); } + [RemoteEvent("keyPress:UP_ARROW")] public void KeyPressUpArrow(Client player) { @@ -55,6 +56,7 @@ namespace ReallifeGamemode.Server.Events ATMManager.ShowAtmUi(player, player.GetData("nearATM")); } } + [RemoteEvent("keyPress:LEFT_ARROW")] public void KeyPressLeftArrow(Client player) { @@ -78,6 +80,7 @@ namespace ReallifeGamemode.Server.Events player.TriggerEvent("showPlayerInteraction", JsonConvert.SerializeObject(nearbyPlayerList)); } } + [RemoteEvent("keyPress:RIGHT_ARROW")] public void KeyPressRightArrow(Client player) { @@ -92,6 +95,30 @@ namespace ReallifeGamemode.Server.Events } } + [RemoteEvent("keyPress:DOWN_ARROW")] + public void KeyPressDownArrow(Client player) + { + User u = player.GetUser(); + if (u == null) return; + + var accountData = new + { + regDate = u.RegistrationDate.ToShortDateString(), + adminLevel = u.AdminLevel.GetName(), + faction = u.Faction?.Name ?? "Zivilist", + factionRank = u.GetFactionRank().RankName, + group = u.Group?.Name ?? "Keine", + groupRank = u.GroupRank.GetName() + }; + + string faction = u.FactionLeader ? u.Faction.Name : null; + string group = u.Group?.Name ?? null; + bool factionInvite = player.HasData("accept_faction_invite"); + bool groupInvite = player.HasData("accept_group_invite"); + + player.TriggerEvent("SERVER:InteractionMenu_OpenMenu", JsonConvert.SerializeObject(accountData), faction, group, factionInvite, groupInvite); + } + [RemoteEvent("keyPress:E")] public void KeyPressE(Client player) { @@ -99,78 +126,77 @@ namespace ReallifeGamemode.Server.Events var user = player.GetUser(); if (user?.FactionId != null) { - DutyPoint nearest = PositionManager.DutyPoints.Find(d => d.Position.DistanceTo(player.Position) <= 1.5); + DutyPoint nearest = PositionManager.DutyPoints.Find(d => d.Position.DistanceTo(player.Position) <= 1.5 && d.FactionId == user.FactionId); if (nearest == null) return; - if (player.Position.DistanceTo(nearest.Position) <= 1.5 && nearest.FactionId == user.FactionId) + var nameTagColor = new Color(0, 0, 0); + var factionId = user.FactionId; + + if (player.GetData("duty") == false) { - var nameTagColor = new Color(0, 0, 0); - var factionId = user.FactionId; - - if (player.GetData("duty") == false) + player.SetData("duty", true); + player.SendNotification("Du bist nun ~g~im Dienst."); + if (player.GetUser().FactionId == 2) //Fire Department { - player.SetData("duty", true); - player.SendNotification("Du bist nun ~g~im Dienst."); - if (player.GetUser().FactionId == 2) //Fire Department + int medicCount = 0; + foreach (Client c in NAPI.Pools.GetAllPlayers()) { - int medicCount = 0; - foreach (Client c in NAPI.Pools.GetAllPlayers()) + if ((c.GetUser()?.Faction.Id ?? 0) == 2) { - if ((c.GetUser()?.Faction.Id ?? 0) == 2) - { - medicCount++; - } + medicCount++; } - NAPI.ClientEvent.TriggerClientEventForAll("updateDutyMedics", medicCount); } - switch (factionId) - { - //LSPD - case 1: - nameTagColor = new Color(28, 134, 238); - break; - } - player.NametagColor = nameTagColor; - using (var context = new DatabaseContext()) - { - List clothes = context.CharacterClothes.Where(u => u.UserId == user.Id && u.Duty == true).ToList(); + NAPI.ClientEvent.TriggerClientEventForAll("updateDutyMedics", medicCount); + } + switch (factionId) + { + //LSPD + case 1: + nameTagColor = new Color(28, 134, 238); + break; + } + player.NametagColor = nameTagColor; + using (var context = new DatabaseContext()) + { + List clothes = context.CharacterClothes.Where(u => u.UserId == user.Id && u.Duty == true).ToList(); - foreach (var cloth in clothes) + foreach (var cloth in clothes) + { + if (cloth.SlotType == 0) { - if (cloth.SlotType == 0) + player.SetClothes(cloth.SlotId, cloth.ClothId, 0); + } + else + { + if (cloth.ClothId != -1) { - player.SetClothes(cloth.SlotId, cloth.ClothId, 0); + player.SetAccessories(cloth.SlotId, cloth.ClothId, 0); } else { - if (cloth.ClothId != -1) - { - player.SetAccessories(cloth.SlotId, cloth.ClothId, 0); - } - else - { - player.ClearAccessory(cloth.SlotId); - } + player.ClearAccessory(cloth.SlotId); } } } } - else - { - player.SetData("duty", false); - player.SendNotification("Du bist nun ~r~außer Dienst."); - NAPI.ClientEvent.TriggerClientEventForAll("updateDutyMedics", false); - player.NametagColor = new Color(255, 255, 255); - UpdateCharacterCloth.LoadCharacterDefaults(player); - } + } + else + { + player.SetData("duty", false); + player.SendNotification("Du bist nun ~r~außer Dienst."); + NAPI.ClientEvent.TriggerClientEventForAll("updateDutyMedics", false); + player.NametagColor = new Color(255, 255, 255); + UpdateCharacterCloth.LoadCharacterDefaults(player); } } } + [RemoteEvent("keyPress:I")] public void KeyPressI(Client player) { if (!player.IsLoggedIn()) return; InventoryManager.GetUserItems(player); } + [RemoteEvent("keyPress:J")] public void KeyPressJ(Client player) { @@ -191,6 +217,7 @@ namespace ReallifeGamemode.Server.Events } player.TriggerEvent("fetchPlayerList", JsonConvert.SerializeObject(ListPlayers)); } + [RemoteEvent("keyPress:K")] public void KeyPressK(Client player) { @@ -244,12 +271,14 @@ namespace ReallifeGamemode.Server.Events } } + [RemoteEvent("keyPress:L")] public void KeyPressL(Client player) { if (!player.IsLoggedIn()) return; DoorManager.ChangeDoorState(player); } + [RemoteEvent("keyPress:N")] public void KeyPressN(Client player) { diff --git a/ReallifeGamemode.Server/Extensions/ClientExtension.cs b/ReallifeGamemode.Server/Extensions/ClientExtension.cs index b6ee4455..aca50c9e 100644 --- a/ReallifeGamemode.Server/Extensions/ClientExtension.cs +++ b/ReallifeGamemode.Server/Extensions/ClientExtension.cs @@ -24,29 +24,15 @@ namespace ReallifeGamemode.Server.Extensions /// public static User GetUser(this Client client, DatabaseContext context = null) { + context = context ?? new DatabaseContext(); if (!client.IsLoggedIn()) return null; - if (context == null) - { - using (context = new DatabaseContext()) - { - return context - .Users - .Include(u => u.Faction) - .Include(u => u.FactionRank) - .Include(u => u.Group) - .Where(u => u.Name == client.Name) - .FirstOrDefault(); - } - } - else - { - return context - .Users - .Include(u => u.Faction) - .Include(u => u.FactionRank) - .Where(u => u.Name == client.Name) - .FirstOrDefault(); - } + return context + .Users + .Include(u => u.Faction) + .Include(u => u.FactionRank) + .Include(u => u.Group) + .Where(u => u.Name == client.Name) + .FirstOrDefault(); } public static Character GetCharacter(this User user, DatabaseContext context = null) diff --git a/ReallifeGamemode.Server/Extensions/AdminLevelExtension.cs b/ReallifeGamemode.Server/Extensions/EnumExtensions.cs similarity index 68% rename from ReallifeGamemode.Server/Extensions/AdminLevelExtension.cs rename to ReallifeGamemode.Server/Extensions/EnumExtensions.cs index df1b65ef..df2bde5b 100644 --- a/ReallifeGamemode.Server/Extensions/AdminLevelExtension.cs +++ b/ReallifeGamemode.Server/Extensions/EnumExtensions.cs @@ -6,7 +6,7 @@ using System.Text; namespace ReallifeGamemode.Server.Extensions { - public static class AdminLevelExtension + public static class EnumExtensions { /// /// Gibt den richtigen Namen eines Admin Levels zurück @@ -31,5 +31,20 @@ namespace ReallifeGamemode.Server.Extensions return "Spieler"; } } + + public static string GetName(this GroupRank rank) + { + switch(rank) + { + case GroupRank.OWNER: + return "Besitzer"; + case GroupRank.MANAGER: + return "Manager"; + case GroupRank.MEMBER: + return "Mitglied"; + default: + return "Keiner"; + } + } } } diff --git a/ReallifeGamemode.Server/Main.cs b/ReallifeGamemode.Server/Main.cs index 2f50ceeb..58f40e53 100644 --- a/ReallifeGamemode.Server/Main.cs +++ b/ReallifeGamemode.Server/Main.cs @@ -46,6 +46,7 @@ namespace ReallifeGamemode.Server InteriorManager.LoadInteriors(); DoorManager.LoadDoors(); ATMManager.InitATMs(); + CityHallManager.LoadCityHall(); TempBlip tempBlip = new TempBlip() diff --git a/ReallifeGamemode.Server/Managers/CityHallManager.cs b/ReallifeGamemode.Server/Managers/CityHallManager.cs new file mode 100644 index 00000000..56be6fbe --- /dev/null +++ b/ReallifeGamemode.Server/Managers/CityHallManager.cs @@ -0,0 +1,67 @@ +using GTANetworkAPI; +using ReallifeGamemode.Server.Entities; +using ReallifeGamemode.Server.Extensions; +using ReallifeGamemode.Server.Models; +using ReallifeGamemode.Server.Services; +using ReallifeGamemode.Server.Util; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ReallifeGamemode.Server.Managers +{ + class CityHallManager : Script + { + private static readonly Vector3 _cityHallPosition = new Vector3(273.22, -278.14, 53.9); + + public static void LoadCityHall() + { + NAPI.Marker.CreateMarker(MarkerType.VerticalCylinder, _cityHallPosition.Subtract(new Vector3(0, 0, 1.7)), new Vector3(), new Vector3(), 1.0f, new Color(255, 255, 255)); + NAPI.TextLabel.CreateTextLabel("~y~Stadthalle~s~\nDrücke ~o~E~s~, um das Menü zu öffnen", _cityHallPosition, 5.0f, 1f, 0, new Color(255, 255, 255)); + var colShape = NAPI.ColShape.CreateSphereColShape(_cityHallPosition, 1.0f); + colShape.OnEntityEnterColShape += (s, c) => + { + c.TriggerEvent("SERVER:CityHall_ShowHelpText"); + }; + + colShape.OnEntityExitColShape += (s, c) => + { + c.TriggerEvent("SERVER:CityHall_ClearHelpText"); + }; + } + + [RemoteEvent("CLIENT:CityHall_CreateGroup")] + public void CreateGroup(Client player, string name) + { + using (var dbContext = new DatabaseContext()) + { + User u = player.GetUser(dbContext); + if(u.Group != null) + { + ChatService.Error(player, "Du bist schon in einer Gruppe"); + return; + } + if(dbContext.Groups.Any(g => g.Name.ToLower() == name.ToLower())) + { + ChatService.Error(player, "Dieser Name ist schon vergeben"); + return; + } + + Group group = new Group + { + Name = name + }; + + dbContext.Groups.Add(group); + + u.Group = group; + u.GroupRank = GroupRank.OWNER; + + dbContext.SaveChanges(); + + ChatService.BroadcastGroup($"Die Gruppe \"{name}\" wurde erfolgreich erstellt.", group); + } + } + } +} diff --git a/ReallifeGamemode.Server/Managers/InteractionManager.cs b/ReallifeGamemode.Server/Managers/InteractionManager.cs index 0c707632..f4b33eaa 100644 --- a/ReallifeGamemode.Server/Managers/InteractionManager.cs +++ b/ReallifeGamemode.Server/Managers/InteractionManager.cs @@ -1,9 +1,13 @@ using GTANetworkAPI; using Newtonsoft.Json; +using ReallifeGamemode.Server.Entities; using ReallifeGamemode.Server.Extensions; +using ReallifeGamemode.Server.Models; using ReallifeGamemode.Server.Services; +using ReallifeGamemode.Server.Util; using System; using System.Collections.Generic; +using System.Linq; using System.Text; /** @@ -19,6 +23,108 @@ namespace ReallifeGamemode.Server.Managers #region Umgebungsinteraktionen PFEILTASTE-HOCH #endregion #region Eigeninteraktionen PFEILTASTE-RUNTER + [RemoteEvent("CLIENT:InteractionMenu_AcceptInvite")] + public void InteractionMenuAcceptInvite(Client player, string type) + { + if (type != "Fraktion" || type != "Gruppe") return; + + if (type == "Fraktion") // Fraktions Invite annehmen + { + if (!player.HasData("accept_faction_invite")) + { + ChatService.Error(player, "Du hast keine Einladung in eine Fraktion erhalten"); + return; + } + + Client leader = NAPI.Player.GetPlayerFromHandle((NetHandle)player.GetData("accept_faction_invite")); + player.ResetData("accept_faction_invite"); + + if (leader == null) + { + ChatService.Error(player, "Die Einladung ist abgelaufen"); + return; + } + + using (var dbContext = new DatabaseContext()) + { + User u = leader.GetUser(dbContext); + User own = player.GetUser(dbContext); + + own.FactionId = u.FactionId; + own.FactionLeader = false; + own.FactionRankId = dbContext + .FactionRanks + .OrderBy(x => x.Order) + .Where(r => r.FactionId == own.FactionId) + .FirstOrDefault()?.Id ?? null; + + leader.SendChatMessage("!{02FCFF}" + player.Name + " hat die Einladung angenommen."); + player.SendChatMessage("!{02FCFF}Du hast die Einladung angenommen."); + + dbContext.SaveChanges(); + } + } + else if (type == "Gruppe") // Gruppen Einladung annehmen + { + if (!player.HasData("accept_group_invite")) + { + ChatService.Error(player, "Du hast keine Einladung in eine Gruppe erhalten"); + return; + } + + Client leader = NAPI.Player.GetPlayerFromHandle((NetHandle)player.GetData("accept_group_invite")); + player.ResetData("accept_group_invite"); + + if (leader == null) + { + ChatService.Error(player, "Die Einladung ist abgelaufen"); + return; + } + + using (var dbContext = new DatabaseContext()) + { + User u = leader.GetUser(dbContext); + User own = player.GetUser(dbContext); + + own.Group = u.Group; + own.GroupRank = GroupRank.MEMBER; + + leader.SendChatMessage("!{02FCFF}" + player.Name + " hat die Einladung angenommen."); + player.SendChatMessage("!{02FCFF}Du hast die Einladung angenommen."); + + dbContext.SaveChanges(); + } + } + } + + [RemoteEvent("CLIENT:InteractionMenu_InviteFaction")] + public void InteractionMenuInviteFaction(Client player, string nameOrId) + { + if (player.GetUser()?.FactionId == null || player.GetUser().FactionLeader == false) + { + ChatService.NotAuthorized(player); + return; + } + + Client target = ClientService.GetClientByNameOrId(nameOrId); + if (target == null || !target.IsLoggedIn()) + { + ChatService.PlayerNotFound(player); + return; + } + + if (target.GetUser()?.FactionId != null) + { + ChatService.Error(player, "Dieser Spieler ist schon in einer Fraktion"); + return; + } + + target.SetData("accept_faction_invite", player.Handle); + + player.SendChatMessage("!{02FCFF}Du hast dem Spieler " + target.Name + " eine Einladung in deine Fraktion gesendet."); + target.SendChatMessage("!{02FCFF}Du hast von " + player.Name + " eine Einladung in die Fraktion \"" + player.GetUser().Faction.Name + "\" erhalten."); + target.SendChatMessage("!{02FCFF}Benutze das Interaktionsmenü, um die Einladung anzunehmen"); + } #endregion #region Spielerinteraktionen PFEILTASTE-LINKS [RemoteEvent("openTradeInventory")] diff --git a/ReallifeGamemode.Server/Managers/InteriorManager.cs b/ReallifeGamemode.Server/Managers/InteriorManager.cs index 9598d9c6..f3fd1cc9 100644 --- a/ReallifeGamemode.Server/Managers/InteriorManager.cs +++ b/ReallifeGamemode.Server/Managers/InteriorManager.cs @@ -61,7 +61,7 @@ namespace ReallifeGamemode.Server.Managers if (interior.EnterPosition != null) { _interiorEnterTextLabels[interior.Id] = NAPI.TextLabel.CreateTextLabel("~y~" + interior.Name + "\n~s~Eingang", interior.EnterPosition, 10f, 1f, 0, new Color(255, 255, 255)); - _interiorEnterMarkers[interior.Id] = NAPI.Marker.CreateMarker(MarkerType.VerticalCylinder, interior.EnterPosition.Subtract(new Vector3(0, 0, 1.7)), new Vector3(), new Vector3(), 2.0f, new Color(255, 255, 255, 100)); + _interiorEnterMarkers[interior.Id] = NAPI.Marker.CreateMarker(MarkerType.VerticalCylinder, interior.EnterPosition.Subtract(new Vector3(0, 0, 1.7)), new Vector3(), new Vector3(), 1.6f, new Color(255, 255, 255, 100)); _interiorEnterColShapes[interior.Id] = NAPI.ColShape.CreateSphereColShape(interior.EnterPosition, 1.5f); } @@ -69,7 +69,7 @@ namespace ReallifeGamemode.Server.Managers { _interiorExitTextLabels[interior.Id] = NAPI.TextLabel.CreateTextLabel("~y~" + interior.Name + "\n~s~Ausgang", interior.ExitPosition, 10f, 1f, 0, new Color(255, 255, 255)); _interiorExitMarkers[interior.Id] = NAPI.Marker.CreateMarker(MarkerType.VerticalCylinder, interior.ExitPosition.Subtract(new Vector3(0, 0, 1.7)), new Vector3(), new Vector3(), 1.6f, new Color(255, 255, 255, 100)); - _interiorExitColShapes[interior.Id] = NAPI.ColShape.CreateSphereColShape(interior.ExitPosition, 1.3f); + _interiorExitColShapes[interior.Id] = NAPI.ColShape.CreateSphereColShape(interior.ExitPosition, 1.5f); } } diff --git a/ReallifeGamemode.Server/Services/ChatService.cs b/ReallifeGamemode.Server/Services/ChatService.cs index 5d76f299..bcc4cb8f 100644 --- a/ReallifeGamemode.Server/Services/ChatService.cs +++ b/ReallifeGamemode.Server/Services/ChatService.cs @@ -74,5 +74,19 @@ namespace ReallifeGamemode.Server.Services } }); } + + public static void BroadcastGroup(string message, Group group) + { + message = $"!{{FF8080}}** Gruppe: {message}"; + + NAPI.Pools.GetAllPlayers().ForEach(p => + { + Group pGroup = p.GetUser()?.Group; + if (pGroup?.Id == group.Id) + { + p.SendChatMessage(message); + } + }); + } } }