From 84b4ba69f5092d72846645ff5b5a183caeb77c1a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 28 Apr 2024 13:41:42 +1000 Subject: [PATCH] Update to latest --- .github/actions/notify_success/action.yml | 19 + .github/actions/upload_build/action.yml | 2 +- .github/workflows/build.yml | 142 +++++-- .github/workflows/release.yml | 134 ++++++ CLI/MCGalaxyCLI_dotnet6.csproj | 1 + MCGalaxy/Commands/Overseer.cs | 391 +++++++++++------- MCGalaxy/Commands/SubCommand.cs | 1 - MCGalaxy/Commands/building/CmdMessageBlock.cs | 3 + MCGalaxy/Commands/building/CmdPortal.cs | 1 + MCGalaxy/Database/Backends/Interfaces.cs | 33 +- MCGalaxy/Database/Backends/MySQL.cs | 36 +- MCGalaxy/Database/Backends/SQLite.cs | 6 +- MCGalaxy/Database/Backends/SQLiteBackend.cs | 32 +- MCGalaxy/Database/IDatabaseBackend.cs | 4 +- MCGalaxy/Database/Stats/OnlineStat.cs | 4 + MCGalaxy/Levels/Level.Fields.cs | 2 +- MCGalaxy/MCGalaxy_dotnet.csproj | 2 +- .../Modules/Relay/Discord/DiscordWebsocket.cs | 3 +- MCGalaxy/Player/Pronouns.cs | 16 +- MCGalaxy/Player/SpamChecker.cs | 2 +- 20 files changed, 569 insertions(+), 265 deletions(-) create mode 100644 .github/actions/notify_success/action.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/actions/notify_success/action.yml b/.github/actions/notify_success/action.yml new file mode 100644 index 0000000..9b50d87 --- /dev/null +++ b/.github/actions/notify_success/action.yml @@ -0,0 +1,19 @@ +name: Notify success +description: Sends a notification that a workflow has finished +inputs: + DESTINATION_URL: + description: 'Webhook notification URL' + type: string + WORKFLOW_NAME: + description: 'Workflow name' + required: true + type: string + +runs: + using: "composite" + steps: + - name: Notify failure + if: ${{ inputs.DESTINATION_URL != '' }} + shell: sh + run: | + curl ${{ inputs.DESTINATION_URL }}/${{ inputs.WORKFLOW_NAME }}/${{ github.sha }} \ No newline at end of file diff --git a/.github/actions/upload_build/action.yml b/.github/actions/upload_build/action.yml index 36fc2fc..84f8965 100644 --- a/.github/actions/upload_build/action.yml +++ b/.github/actions/upload_build/action.yml @@ -13,7 +13,7 @@ inputs: runs: using: "composite" steps: - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{ inputs.DEST_NAME }} path: ${{ inputs.SOURCE_FILE }} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b1019d6..b0a14a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,11 +6,47 @@ concurrency: cancel-in-progress: true jobs: - build-mono: +#============================================ +# ============== .NET 2.0 BUILD ============= +# =========================================== + build-mono2: if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Compile MCGalaxy using mono + shell: bash + id: compile + run: | + msbuild MCGalaxy.sln /p:Configuration=Release /p:TargetFrameworkVersion=v2.0 /p:DefineConstants="NET_20" + + - uses: ./.github/actions/notify_failure + if: ${{ always() && steps.compile.outcome == 'failure' }} + with: + NOTIFY_MESSAGE: 'Failed to compile MCGalaxy .NET 2.0 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'bin/Release' + DEST_NAME: 'MCGalaxy_net2.0' + + - uses: ./.github/actions/notify_success + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' + WORKFLOW_NAME: 'net20' + + +#============================================ +# ============== .NET 4.0 BUILD ============= +# =========================================== + build-mono4: + if: github.ref_name == github.event.repository.default_branch + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 - name: Compile MCGalaxy using mono shell: bash id: compile @@ -36,94 +72,120 @@ jobs: if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'bin/Release' - DEST_NAME: 'MCGalaxy-infid' + DEST_NAME: 'MCGalaxy-infid' + + - uses: ./.github/actions/notify_success + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' + WORKFLOW_NAME: 'net40' +#============================================ +# ============== .NET 6.0 BUILD ============= +# =========================================== build-dotnet6: if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 6.0.x - name: Restore dependencies run: dotnet restore CLI/MCGalaxyCLI_dotnet6.csproj - name: Build - id: compile_net + id: compile run: | dotnet build CLI/MCGalaxyCLI_dotnet6.csproj --no-restore - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile_net.outcome == 'failure' }} + if: ${{ always() && steps.compile.outcome == 'failure' }} with: NOTIFY_MESSAGE: 'Failed to compile MCGalaxy dotnet build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile_net.outcome == 'success' }} + if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'CLI/bin/Debug/net6.0' DEST_NAME: 'MCGalaxy-dotnet6.0' + # publish standalone windows binaries + - name: Publish-win64 + run: dotnet publish CLI/MCGalaxyCLI_standalone6.csproj -r win-x64 --self-contained -p:ExtraConstants=MCG_STANDALONE + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'CLI/bin/Debug/net6.0/win-x64/publish' + DEST_NAME: 'MCGalaxy-win64-standalone' + + # publish standalone linux binaries + - name: Publish-linux64 + run: dotnet publish CLI/MCGalaxyCLI_standalone6.csproj -r linux-x64 --self-contained -p:ExtraConstants=MCG_STANDALONE + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'CLI/bin/Debug/net6.0/linux-x64/publish' + DEST_NAME: 'MCGalaxy-linux64-standalone' + + # publish standalone macOS binaries + - name: Publish-mac64 + run: dotnet publish CLI/MCGalaxyCLI_standalone6.csproj -r osx-x64 --self-contained -p:ExtraConstants=MCG_STANDALONE + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'CLI/bin/Debug/net6.0/osx-x64/publish' + DEST_NAME: 'MCGalaxy-mac64-standalone' + + + - uses: ./.github/actions/notify_success + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' + WORKFLOW_NAME: 'net60' + +#============================================ +# ============== .NET 8.0 BUILD ============= +# =========================================== build-dotnet8: if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore CLI/MCGalaxyCLI_dotnet8.csproj - name: Build - id: compile_net + id: compile run: | dotnet build CLI/MCGalaxyCLI_dotnet8.csproj --no-restore - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile_net.outcome == 'failure' }} + if: ${{ always() && steps.compile.outcome == 'failure' }} with: NOTIFY_MESSAGE: 'Failed to compile MCGalaxy dotnet build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile_net.outcome == 'success' }} + if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'CLI/bin/Debug/net8.0' DEST_NAME: 'MCGalaxy-dotnet8.0' - # publish standalone windows binaries - - name: Publish-win64 - run: dotnet publish CLI/MCGalaxyCLI_dotnet8.csproj -r win-x64 --self-contained - - - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile_net.outcome == 'success' }} - with: - SOURCE_FILE: 'CLI/bin/Release/net8.0/win-x64/publish' - DEST_NAME: 'MCGalaxy-win64-standalone' - - # publish standalone linux binaries - - name: Publish-linux64 - run: dotnet publish CLI/MCGalaxyCLI_dotnet8.csproj -r linux-x64 --self-contained - - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile_net.outcome == 'success' }} - with: - SOURCE_FILE: 'CLI/bin/Release/net8.0/linux-x64/publish' - DEST_NAME: 'MCGalaxy-linux64-standalone' - - # publish standalone macOS binaries - - name: Publish-mac64 - run: dotnet publish CLI/MCGalaxyCLI_dotnet8.csproj -r osx-x64 --self-contained - - - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile_net.outcome == 'success' }} + - uses: ./.github/actions/notify_success + if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'CLI/bin/Release/net8.0/osx-x64/publish' - DEST_NAME: 'MCGalaxy-mac64-standalone' + DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' + WORKFLOW_NAME: 'net80' \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3b7048e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,134 @@ +name: Build release +on: [workflow_dispatch] + +concurrency: + group: ${{ github.ref }}-release + cancel-in-progress: true + +jobs: + build: + if: github.ref_name == github.event.repository.default_branch + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Retrieve supporting files + run: | + wget https://raw.githubusercontent.com/ClassiCube/MCGalaxy/master/sqlite3_x32.dll + wget https://raw.githubusercontent.com/ClassiCube/MCGalaxy/master/sqlite3_x64.dll + wget https://raw.githubusercontent.com/ClassiCube/MCGalaxy/master/MySql.Data.dll + + - name: Retrieve .NET 2.0 binaries + run: | + mkdir net20 + wget https://cdn.classicube.net/client/mcg/latest/net20/MCGalaxy_.dll -O net20/MCGalaxy_.dll + wget https://cdn.classicube.net/client/mcg/latest/net20/MCGalaxyCLI.exe -O net20/MCGalaxyCLI.exe + wget https://cdn.classicube.net/client/mcg/latest/net20/MCGalaxy.exe -O net20/MCGalaxy.exe + + - name: Retrieve .NET 4.0 binaries + run: | + mkdir net40 + wget https://cdn.classicube.net/client/mcg/latest/net40/MCGalaxy_.dll -O net40/MCGalaxy_.dll + wget https://cdn.classicube.net/client/mcg/latest/net40/MCGalaxyCLI.exe -O net40/MCGalaxyCLI.exe + wget https://cdn.classicube.net/client/mcg/latest/net40/MCGalaxy.exe -O net40/MCGalaxy.exe + + + - name: Retrieve .NET 4.0 (768 blocks) binaries + run: | + mkdir infid + wget https://cdn.classicube.net/client/mcg/latest/net40/MCGalaxy_infid.dll -O infid/MCGalaxy_.dll + wget https://cdn.classicube.net/client/mcg/latest/net40/MCGalaxyCLI.exe -O infid/MCGalaxyCLI.exe + wget https://cdn.classicube.net/client/mcg/latest/net40/MCGalaxy.exe -O infid/MCGalaxy.exe + + - name: Retrieve standalone binaries + run: | + wget https://cdn.classicube.net/client/mcg/latest/mcg-win64-standalone.exe -O mcg-win64 + wget https://cdn.classicube.net/client/mcg/latest/mcg-mac64-standalone -O mcg-mac64 + wget https://cdn.classicube.net/client/mcg/latest/mcg-linux64-standalone -O mcg-linux64 + + - name: Generate builds + id: compile + shell: bash + run: | + + make_dotnet_zip() { + cp sqlite3_x32.dll $1/sqlite3_x32.dll + cp sqlite3_x64.dll $1/sqlite3_x64.dll + cp MySql.Data.dll $1/MySql.Data.dll + zip -r $1.zip $1 + } + + make_standalone_tar() { + cp $1 MCGalaxy + chmod +x MCGalaxy + tar -zcvf $1.tar.gz MCGalaxy + } + + make_standalone_zip() { + cp $1 MCGalaxy.exe + zip $1.zip MCGalaxy.exe sqlite3_x32.dll sqlite3_x64.dll + } + + make_dotnet_zip net20 + make_dotnet_zip net40 + make_dotnet_zip infid + + make_standalone_zip mcg-win64 + make_standalone_tar mcg-mac64 + make_standalone_tar mcg-linux64 + + find . + + + - uses: ./.github/actions/notify_failure + if: ${{ always() && steps.compile.outcome == 'failure' }} + with: + NOTIFY_MESSAGE: 'Failed to produce release' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + + + # Generate .NET release files + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'net20.zip' + DEST_NAME: 'mcg-net20.zip' + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'net40.zip' + DEST_NAME: 'mcg-net40.zip' + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'infid.zip' + DEST_NAME: 'mcg-infid.zip' + + + # Generate standalone release files + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'mcg-win64.zip' + DEST_NAME: 'mcg-win64.zip' + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'mcg-mac64.tar.gz' + DEST_NAME: 'mcg-mac64.tar.gz' + + - uses: ./.github/actions/upload_build + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + SOURCE_FILE: 'mcg-linux64.tar.gz' + DEST_NAME: 'mcg-linux64.tar.gz' + + + - uses: ./.github/actions/notify_success + if: ${{ always() && steps.compile.outcome == 'success' }} + with: + DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' + WORKFLOW_NAME: 'release' \ No newline at end of file diff --git a/CLI/MCGalaxyCLI_dotnet6.csproj b/CLI/MCGalaxyCLI_dotnet6.csproj index bdba1e8..a8f3532 100644 --- a/CLI/MCGalaxyCLI_dotnet6.csproj +++ b/CLI/MCGalaxyCLI_dotnet6.csproj @@ -4,6 +4,7 @@ net6.0 true true + $(DefineConstants);$(ExtraConstants) diff --git a/MCGalaxy/Commands/Overseer.cs b/MCGalaxy/Commands/Overseer.cs index 9de9bcd..5ee38eb 100644 --- a/MCGalaxy/Commands/Overseer.cs +++ b/MCGalaxy/Commands/Overseer.cs @@ -60,105 +60,105 @@ static string NextLevel(Player p) { p.Message("You have reached the limit for your overseer maps."); return null; } - #region Help messages - - static string[] blockPropsHelp = new string[] { - "&T/os blockprops [id] [action] &H- Changes properties of blocks in your map.", - "&H See &T/Help blockprops &Hfor how to use this command.", - "&H Remember to substitute /blockprops for /os blockprops when using the command based on the help", + static string[] addHelp = new string[] { + "&T/os map add &H- Creates a flat map (128x128x128).", + "&T/os map add [theme] &H- Creates a map with [theme] terrain.", + "&H Use &T/Help newlvl themes &Hfor a list of map themes.", + "&T/os map add [width] [height] [length] [theme]", + "&H Creates a map with custom size and theme.", }; + static void HandleAdd(Player p, string message) { + if (p.group.OverseerMaps == 0) { + p.Message("Your rank is not allowed to create any /{0} maps.", commandShortcut); return; + } - static string[] envHelp = new string[] { - "&T/os env [fog/cloud/sky/shadow/sun] [hex color] &H- Changes env colors of your map.", - "&T/os env level [height] &H- Sets the water height of your map.", - "&T/os env cloudheight [height] &H-Sets cloud height of your map.", - "&T/os env maxfog &H- Sets the max fog distance in your map.", - "&T/os env horizon &H- Sets the \"ocean\" block outside your map.", - "&T/os env border &H- Sets the \"bedrock\" block outside your map.", - "&T/os env weather [sun/rain/snow] &H- Sets weather of your map.", - " Note: If no hex or block is given, the default will be used.", - }; + string level = NextLevel(p); + if (level == null) return; + string[] bits = message.SplitSpaces(); - static string[] gotoHelp = new string[] { - "&T/os go &H- Teleports you to your first map.", - "&T/os go [num] &H- Teleports you to your nth map.", - }; + if (message.Length == 0) message = "128 128 128"; + else if (bits.Length < 3) message = "128 128 128 " + message; + string[] genArgs = (level + " " + message.TrimEnd()).SplitSpaces(6); - static string[] kickHelp = new string[] { - "&T/os kick [name] &H- Removes that player from your map.", - }; + CmdNewLvl newLvl = (CmdNewLvl)Command.Find("NewLvl"); // TODO: this is a nasty hack, find a better way + Level lvl = newLvl.GenerateMap(p, genArgs, p.DefaultCmdData); + if (lvl == null) return; - static string[] kickAllHelp = new string[] { - "&T/os kickall &H- Removes all other players from your map.", - }; + MapGen.SetRealmPerms(p, lvl); + p.Message("Use &T/{0} allow [name] &Sto allow other players to build in the map.", commandShortcut); - static string[] levelBlockHelp = new string[] { - "&T/os lb [action] &H- Manages custom blocks on your map.", - "&H See &T/Help lb &Hfor how to use this command.", - "&H Remember to substitute /lb for /os lb when using the command based on the help", - }; + try { + lvl.Save(true); + } finally { + lvl.Dispose(); + Server.DoGC(); + } + } - static string[] mapHelp = new string[] { - "&T/os map add [type - default is flat] &H- Creates your map (128x128x128)", - "&T/os map add [width] [height] [length] [theme]", - "&H See &T/Help newlvl themes &Hfor a list of map themes.", - "&T/os map physics [level] &H- Sets the physics on your map.", - "&T/os map delete &H- Deletes your map", - "&T/os map restore [num] &H- Restores backup [num] of your map", - "&T/os map resize [width] [height] [length] &H- Resizes your map", - "&T/os map save &H- Saves your map", - "&T/os map pervisit [rank] &H- Sets the pervisit of you map", - "&T/os map perbuild [rank] &H- Sets the perbuild of you map", - "&T/os map texture [url] &H- Sets terrain.png for your map", - "&T/os map texturepack [url] &H- Sets texture pack .zip for your map", - "&T/os map [option] &H- Toggles that map option.", - "&H See &T/Help map &Hfor a list of map options", + static string[] deleteHelp = new string[] { + "&T/os map delete &H- Deletes your map.", }; + static void HandleDelete(Player p, string message) { + if (message.Length > 0) { + p.Message("To delete your current map, type &T/{0} map delete", commandShortcut); + return; + } + UseCommand(p, "DeleteLvl", p.level.name); + } - static string[] presetHelp = new string[] { - "&T/os preset [name] &H- Sets the env settings of your map to that preset's.", + static string[] allowHelp = new string[] { + "&T/os allow [player]", + "&H Allows [player] to build in your map.", }; - - static string[] spawnHelp = new string[] { - "&T/os setspawn &H- Sets the map's spawn point to your current position.", + static void HandleAllow(Player p, string message) { + _HandlePerm(p, message, "allow", "perbuild", "+"); + } + static string[] disallowHelp = new string[] { + "&T/os disallow [player]", + "&H Disallows [player] from building in your map.", }; - - static string[] zoneHelp = new string[] { - "&T/os zone add [name] &H- Allows them to build in your map.", - "&T/os zone del all &H- Deletes all zones in your map.", - "&T/os zone del [name] &H- Prevents them from building in your map.", - "&T/os zone list &H- Shows zones affecting a particular block.", - "&T/os zone block [name] &H- Prevents them from joining your map.", - "&T/os zone unblock [name] &H- Allows them to join your map.", - "&T/os zone blacklist &H- Shows currently blacklisted players.", + static void HandleDisallow(Player p, string message) { + _HandlePerm(p, message, "disallow", "perbuild", "-"); + } + static string[] banHelp = new string[] { + "&T/os ban [player]", + "&H Bans [player] from visiting your map.", }; - - static string[] zonesHelp = new string[] { - "&T/os zones [cmd] [args]", - "&HManages zones in your map. See &T/Help zone", + static void HandleBan(Player p, string message) { + _HandlePerm(p, message, "ban", "pervisit", "-"); + } + static string[] unbanHelp = new string[] { + "&T/os unban [player]", + "&H Unbans [player] from visiting your map.", }; - #endregion - - internal static SubCommandGroup subCommandGroup = new SubCommandGroup(commandShortcut, - new List() { - new SubCommand("BlockProps", HandleBlockProps, blockPropsHelp, true, new string[] { "BlockProperties" }), - new SubCommand("Env", HandleEnv, envHelp), - new SubCommand("Go", HandleGoto, gotoHelp, false), - new SubCommand("Kick", HandleKick, kickHelp), - new SubCommand("KickAll", HandleKickAll, kickAllHelp), - new SubCommand("LB", HandleLevelBlock, levelBlockHelp, true, new string[] {"LevelBlock" }), - new SubCommand("Map", HandleMap, mapHelp, false), - new SubCommand("Preset", HandlePreset, presetHelp), - new SubCommand("SetSpawn", HandleSpawn, spawnHelp, true, new string[] { "Spawn" }), - new SubCommand("Zone", HandleZone, zoneHelp), - new SubCommand("Zones", HandleZones, zonesHelp), } - ); + static void HandleUnban(Player p, string message) { + _HandlePerm(p, message, "unban", "pervisit", "+"); + } + static void _HandlePerm(Player p, string message, string action, string cmd, string prefix) { + if (message.Length == 0) { p.Message("&WYou need to type a player name to {0}.", action); return; } + UseCommand(p, cmd, prefix + message); + } + static string[] blockPropsHelp = new string[] { + "&T/os blockprops [id] [action] &H- Changes properties of blocks in your map.", + "&H See &T/Help blockprops &Hfor how to use this command.", + "&H Remember to substitute /blockprops for /os blockprops when using the command based on the help", + }; static void HandleBlockProps(Player p, string message) { if (message.Length == 0) { p.MessageLines(blockPropsHelp); return; } UseCommand(p, "BlockProperties", "level " + message); } + static string[] envHelp = new string[] { + "&T/os env [fog/cloud/sky/shadow/sun] [hex color] &H- Changes env colors of your map.", + "&T/os env level [height] &H- Sets the water height of your map.", + "&T/os env cloudheight [height] &H-Sets cloud height of your map.", + "&T/os env maxfog &H- Sets the max fog distance in your map.", + "&T/os env horizon &H- Sets the \"ocean\" block outside your map.", + "&T/os env border &H- Sets the \"bedrock\" block outside your map.", + "&T/os env weather [sun/rain/snow] &H- Sets weather of your map.", + " Note: If no hex or block is given, the default will be used.", + }; static void HandleEnv(Player p, string raw) { string[] args = raw.SplitExact(2); Level lvl = p.level; @@ -167,6 +167,10 @@ static void HandleEnv(Player p, string raw) { p.MessageLines(envHelp); } + static string[] gotoHelp = new string[] { + "&T/os go &H- Teleports you to your first map.", + "&T/os go [num] &H- Teleports you to your nth map.", + }; static void HandleGoto(Player p, string map) { byte mapNum = 0; if (map.Length == 0) map = "1"; @@ -182,6 +186,9 @@ static void HandleGoto(Player p, string map) { PlayerActions.ChangeMap(p, map); } + static string[] kickHelp = new string[] { + "&T/os kick [name] &H- Removes that player from your map.", + }; static void HandleKick(Player p, string name) { if (name.Length == 0) { p.Message("You must specify a player to kick."); return; } Player pl = PlayerInfo.FindMatches(p, name); @@ -194,6 +201,9 @@ static void HandleKick(Player p, string name) { } } + static string[] kickAllHelp = new string[] { + "&T/os kickall &H- Removes all other players from your map.", + }; static void HandleKickAll(Player p, string unused) { Player[] players = PlayerInfo.Online.Items; foreach (Player pl in players) { @@ -202,10 +212,19 @@ static void HandleKickAll(Player p, string unused) { } } + static string[] levelBlockHelp = new string[] { + "&T/os lb [action] &H- Manages custom blocks on your map.", + "&H Use &T/Help lb &Hfor how to use this command.", + "&H Remember to substitute /lb for /os lb when using the command based on the help", + }; static void HandleLevelBlock(Player p, string lbArgs) { CustomBlockCommand.Execute(p, lbArgs, p.DefaultCmdData, false, "/os lb"); } + static string[] mapHelp = new string[] { + "&T/os map [option] &H- Toggles that map option.", + "&H See &T/Help map &Hfor a list of map options", + }; static void HandleMap(Player p, string raw) { if (raw.Length == 0) { p.MessageLines(mapHelp); return; @@ -220,8 +239,8 @@ static void HandleMap(Player p, string raw) { LevelOption opt = LevelOptions.Find(cmd); if (opt == null) { - p.Message("Could not find map command or map option \"{0}\".", cmd); - p.Message("See &T/help {0} map &Sto display every command.", commandShortcut); + p.Message("Could not find map option \"{0}\".", cmd); + p.Message("Use &T/help map options &Sto see all."); return; } if (DisallowedMapOption(opt.Name)) { @@ -242,68 +261,53 @@ static bool DisallowedMapOption(string opt) { opt == LevelOptions.Goto || opt == LevelOptions.Unload; } + static void Moved(Player p, string message, string name, string newName = null) { + p.Message("&W---"); + p.Message("The &T{0}&S command has been moved out of /{1} map.", name, commandShortcut); + string args = message.Length == 0 ? "" : message + " "; + if (newName == null) { newName = name; } + p.Message("Use &T/{0} {1} {2}&Sinstead.", commandShortcut, newName, args); + } static SubCommandGroup mapSubCommandGroup = new SubCommandGroup(commandShortcut + " map", new List() { - new SubCommand("Physics", HandleMapPhysics, null), - new SubCommand("Add", HandleMapAdd, null, false, new string[] { "create", "new" } ), - new SubCommand("Delete", HandleMapDelete, null, true , new string[] { "del", "remove" } ), - new SubCommand("Save", (p, unused) => { UseCommand(p, "Save", ""); }, null), - new SubCommand("Restore", (p, arg) => { UseCommand(p, "Restore", arg); }, null), - new SubCommand("Resize", HandleMapResize, null), - new SubCommand("PerVisit", HandleMapPerVisit, null), - new SubCommand("PerBuild", HandleMapPerBuild, null), - new SubCommand("Texture", HandleMapTexture, null, true, new string[] { "texturezip", "texturepack" } ), } + new SubCommand("Physics", (p, arg) => { Moved(p, arg, "physics"); }, null), + new SubCommand("Add", (p, arg) => { Moved(p, arg, "add"); }, null, false, new string[] { "create", "new" } ), + new SubCommand("Delete", (p, arg) => { Moved(p, arg, "delete"); }, null, false , new string[] { "del", "remove" } ), + new SubCommand("Save", (p, arg) => { Moved(p, arg, "save"); }, null), + new SubCommand("Restore", (p, arg) => { Moved(p, arg, "restore"); }, null), + new SubCommand("Resize", (p, arg) => { Moved(p, arg, "resize"); }, null), + new SubCommand("PerVisit", (p, arg) => { Moved(p, arg, "pervisit"); }, null), + new SubCommand("PerBuild", (p, arg) => { Moved(p, arg, "perbuild"); }, null), + new SubCommand("Texture", (p, arg) => { Moved(p, arg, "texture"); }, null, false, new string[] { "texturezip", "texturepack" } ), + } ); - static void HandleMapPhysics(Player p, string message) { + static string[] physicsHelp = new string[] { + "&T/os physics [number]", + "&H Changes the physics settings in your map.", + "&H See &T/help physics &Hfor details." + }; + static void HandlePhysics(Player p, string message) { + if (message.Length == 0) { + p.MessageLines(physicsHelp); + return; + } int level = 0; if (!CommandParser.GetInt(p, message, "Physics level", ref level, 0, 5)) return; CmdPhysics.SetPhysics(p.level, level); } - - static void HandleMapAdd(Player p, string message) { - if (p.group.OverseerMaps == 0) { - p.Message("Your rank is not allowed to create any /{0} maps.", commandShortcut); return; - } - - string level = NextLevel(p); - if (level == null) return; - string[] bits = message.SplitSpaces(); - - if (message.Length == 0) message = "128 128 128"; - else if (bits.Length < 3) message = "128 128 128 " + message; - string[] genArgs = (level + " " + message.TrimEnd()).SplitSpaces(6); - - CmdNewLvl newLvl = (CmdNewLvl)Command.Find("NewLvl"); // TODO: this is a nasty hack, find a better way - Level lvl = newLvl.GenerateMap(p, genArgs, p.DefaultCmdData); - if (lvl == null) return; - MapGen.SetRealmPerms(p, lvl); - p.Message("Use &T/{0} zone add [name] &Sto allow other players to build in the map.", commandShortcut); - - try { - lvl.Save(true); - } finally { - lvl.Dispose(); - Server.DoGC(); - } - } - - static void HandleMapDelete(Player p, string message) { - if (message.Length > 0) { - p.Message("To delete your current map, type &T/{0} map delete", commandShortcut); - return; - } - UseCommand(p, "DeleteLvl", p.level.name); - } - - static void HandleMapResize(Player p, string message) { + static string[] resizeHelp = new string[] { + "&T/os resize [width] [height] [length]", + "&H Resizes your map.", + }; + static void HandleResize(Player p, string message) { message = p.level.name + " " + message; string[] args = message.SplitSpaces(); if (args.Length < 4) { p.Message("Not enough args provided! Usage:"); - p.Message("&T/{0} map resize [width] [height] [length]", commandShortcut); + p.Message("&T/{0} resize [width] [height] [length]", commandShortcut); return; } @@ -311,11 +315,16 @@ static void HandleMapResize(Player p, string message) { if (CmdResizeLvl.DoResize(p, args, p.DefaultCmdData, out needConfirm)) return; if (!needConfirm) return; - p.Message("Type &T/{0} map resize {1} {2} {3} confirm &Sif you're sure.", + p.Message("Type &T/{0} resize {1} {2} {3} confirm &Sif you're sure.", commandShortcut, args[1], args[2], args[3]); } - - static void HandleMapPerVisit(Player p, string message) { + + + static string[] pervisitHelp = new string[] { + "&T/os pervisit [rank]", + "&H Changes the rank required to visit your map.", + }; + static void HandlePervisit(Player p, string message) { // Older realm maps didn't put you on visit whitelist, so make sure we put the owner here AccessController access = p.level.VisitAccess; if (!access.Whitelisted.CaselessContains(p.name)) { @@ -328,8 +337,12 @@ static void HandleMapPerVisit(Player p, string message) { message = p.level.name + " " + message; UseCommand(p, "PerVisit", message); } - - static void HandleMapPerBuild(Player p, string message) { + + static string[] perbuildHelp = new string[] { + "&T/os perbuild [rank]", + "&H Changes the rank required to build in your map.", + }; + static void HandlePerbuild(Player p, string message) { if (message.Length == 0) { p.Message("See &T/help perbuild &Sfor how to use this command, but don't include [level]."); return; @@ -337,57 +350,127 @@ static void HandleMapPerBuild(Player p, string message) { message = p.level.name + " " + message; UseCommand(p, "PerBuild", message); } + + static string[] textureHelp = new string[] { + "&T/os texture [url]", + "&H Changes the textures used in your map.", + }; - static void HandleMapTexture(Player p, string message) { + static void HandleTexture(Player p, string message) { if (message.Length == 0) { message = "normal"; } UseCommand(p, "Texture", "levelzip " + message); } + static string[] presetHelp = new string[] { + "&T/os preset [name] &H- Changes the environment color preset in your map.", + }; static void HandlePreset(Player p, string preset) { string raw = ("preset " + preset).Trim(); HandleEnv(p, raw); } + + static string[] spawnHelp = new string[] { + "&T/os setspawn &H- Sets the map's spawn point to your current position.", + }; static void HandleSpawn(Player p, string unused) { UseCommand(p, "SetSpawn", ""); } + static string[] zoneHelp = new string[] { + "&T/os zone", + "&H This was used for managing permissions in your map.", + "&H It has now been replaced by the following &T/"+commandShortcut+" &Hcommands:", + "&T Allow, Disallow, Ban, Unban" + }; + static string[] zoneHelpBody = new string[] { + zoneHelp[1], + zoneHelp[2], + zoneHelp[3], + }; static void HandleZone(Player p, string raw) { - string[] args = raw.SplitExact(2); - string cmd = args[0]; - string name = args[1]; + string[] args = raw.SplitExact(2); + string cmd = args[0]; + string name = args[1]; + p.Message("&W---"); + p.Message("&T/{0} zone &Shas been replaced.", commandShortcut); cmd = cmd.ToUpper(); if (cmd == "LIST") { - UseCommand(p, "ZoneList", ""); + p.Message("To see a list of zones in a level, use &T/zonelist"); } else if (cmd == "ADD") { - UseCommand(p, "PerBuild", "+" + name); + p.Message("To allow someone to build, use &T/{0} allow [name]", commandShortcut); } else if (Command.IsDeleteAction(cmd)) { - UseCommand(p, "PerBuild", "-" + name); + p.Message("To disallow someone from building, use &T/{0} disallow [name]", commandShortcut); } else if (cmd == "BLOCK") { - UseCommand(p, "PerVisit", "-" + name); + p.Message("To disallow visiting, use &T/{0} ban [name]", commandShortcut); } else if (cmd == "UNBLOCK") { - UseCommand(p, "PerVisit", "+" + name); + p.Message("To allow visiting, use &T/{0} unban [name]", commandShortcut); } else if (cmd == "BLACKLIST") { - List blacklist = p.level.VisitAccess.Blacklisted; - if (blacklist.Count > 0) { - p.Message("Blacklisted players: " + blacklist.Join()); - } else { - p.Message("No players are blacklisted from visiting this map."); - } + p.Message("To see who is disallowed from visiting, use &T/mapinfo"); } else { - p.MessageLines(zoneHelp); + p.MessageLines(zoneHelpBody); } } - static void HandleZones(Player p, string raw) { + static string[] plotHelp = new string[] { + "&T/os plot [args]", + "&H Plots are zones that can change permissions and environment." + + "&H See &T/Help zone &Hto learn what args you can use.", + }; + static void HandlePlot(Player p, string raw) { string[] args = raw.SplitSpaces(2); - + if (args.Length == 1) { - p.Message("Arguments required. See &T/Help zone"); + p.Message("This command is the &T/{0} &Sversion of &T/zone&S.", commandShortcut); + p.Message("To learn how to use it, read &T/help zone&S"); } else { UseCommand(p, "Zone", args[0] + " " + args[1]); } } + + static string[] saveHelp = new string[] { + "&T/os save", + "&H Creates a backup of your map.", + "&H Your map is saved automatically, so this is only useful", + "&H If you want to save a specific state to restore later.", + }; + static string[] restoreHelp = new string[] { + "&T/os restore ", + "&H Restores a backup of your map.", + "&H Use without a number to see total backup count.", + }; + //Placed at the end so that the help arrays aren't null + internal static SubCommandGroup subCommandGroup = new SubCommandGroup(commandShortcut, + new List() { + new SubCommand("Add", HandleAdd, addHelp, false, new string[] { "create", "new" }), + new SubCommand("Go", HandleGoto, gotoHelp, false), + new SubCommand("Allow", HandleAllow, allowHelp), + new SubCommand("Disallow", HandleDisallow, disallowHelp), + new SubCommand("Ban", HandleBan, banHelp), + new SubCommand("Unban", HandleUnban, unbanHelp), + new SubCommand("SetSpawn", HandleSpawn, spawnHelp, true, new string[] { "spawn" }), + new SubCommand("Env", HandleEnv, envHelp), + new SubCommand("Preset", HandlePreset, presetHelp), + new SubCommand("Map", HandleMap, mapHelp, false), + + new SubCommand("Plot", HandlePlot, plotHelp, true, new string[] { "plots" }), + new SubCommand("PerBuild", HandlePerbuild, perbuildHelp), + new SubCommand("PerVisit", HandlePervisit, pervisitHelp), + new SubCommand("Physics", HandlePhysics, physicsHelp), + + new SubCommand("LB", HandleLevelBlock, levelBlockHelp, true, new string[] {"LevelBlock" }), + new SubCommand("BlockProps", HandleBlockProps, blockPropsHelp, true, new string[] { "BlockProperties" }), + new SubCommand("Texture", HandleTexture, textureHelp, true, new string[] { "texturezip", "texturepack" }), + new SubCommand("Kick", HandleKick, kickHelp), + new SubCommand("KickAll", HandleKickAll, kickAllHelp), + new SubCommand("Zone", HandleZone, zoneHelp), + + new SubCommand("Resize", HandleResize, resizeHelp), + new SubCommand("Save", (p, unused) => { UseCommand(p, "Save", ""); }, saveHelp), + new SubCommand("Delete", HandleDelete, deleteHelp, true, new string[] { "del", "remove" } ), + new SubCommand("Restore", (p, arg ) => { UseCommand(p, "Restore", arg); }, restoreHelp), + } + ); } } diff --git a/MCGalaxy/Commands/SubCommand.cs b/MCGalaxy/Commands/SubCommand.cs index 8d16fc1..7a9dbab 100644 --- a/MCGalaxy/Commands/SubCommand.cs +++ b/MCGalaxy/Commands/SubCommand.cs @@ -35,7 +35,6 @@ public class SubCommand /// /// When mapOnly is true, the subcommand can only be used when the player is the realm owner. - /// Args passed to behavior through SubCommandGroup.Use are guaranteed to be the length specified by argCount /// public SubCommand(string name, Behavior behavior, string[] help, bool mapOnly = true, string[] aliases = null) { Name = name; diff --git a/MCGalaxy/Commands/building/CmdMessageBlock.cs b/MCGalaxy/Commands/building/CmdMessageBlock.cs index 992de42..5afb40b 100644 --- a/MCGalaxy/Commands/building/CmdMessageBlock.cs +++ b/MCGalaxy/Commands/building/CmdMessageBlock.cs @@ -92,6 +92,9 @@ bool PlacedMark(Player p, Vec3S32[] marks, object state, BlockID block) { p.level.UpdateBlock(p, x, y, z, args.Block); UpdateDatabase(p, args, x, y, z); p.Message("Message block created."); + if (!p.staticCommands) { + p.Message("To delete message blocks, toggle &T/delete &Smode."); + } } else { p.Message("Failed to create a message block."); } diff --git a/MCGalaxy/Commands/building/CmdPortal.cs b/MCGalaxy/Commands/building/CmdPortal.cs index 0b4693b..9615a27 100644 --- a/MCGalaxy/Commands/building/CmdPortal.cs +++ b/MCGalaxy/Commands/building/CmdPortal.cs @@ -124,6 +124,7 @@ void ExitChange(Player p, ushort x, ushort y, ushort z, BlockID block) { p.Message("&3Exit &Sblock placed"); if (!p.staticCommands) return; + p.Message("To delete portals, toggle &T/delete &Smode."); args.Entries.Clear(); p.blockchangeObject = args; p.Blockchange += EntryChange; diff --git a/MCGalaxy/Database/Backends/Interfaces.cs b/MCGalaxy/Database/Backends/Interfaces.cs index 330b471..6567288 100644 --- a/MCGalaxy/Database/Backends/Interfaces.cs +++ b/MCGalaxy/Database/Backends/Interfaces.cs @@ -20,36 +20,33 @@ permissions and limitations under the Licenses. namespace MCGalaxy.SQL { /// Abstracts a connection to a SQL database - public abstract class ISqlConnection : IDisposable + public interface ISqlConnection : IDisposable { - public abstract ISqlTransaction BeginTransaction(); - public abstract ISqlCommand CreateCommand(string sql); + ISqlTransaction BeginTransaction(); + ISqlCommand CreateCommand(string sql); - public abstract void Open(); - public abstract void ChangeDatabase(string name); - public abstract void Close(); - public abstract void Dispose(); + void Open(); + void ChangeDatabase(string name); + void Close(); } /// Abstracts a SQL command/statement - public abstract class ISqlCommand : IDisposable + public interface ISqlCommand : IDisposable { - public abstract void ClearParameters(); - public abstract void AddParameter(string name, object value); + void ClearParameters(); + void AddParameter(string name, object value); - public abstract void Prepare(); + void Prepare(); /// Executes this command and returns the number of rows affected - public abstract int ExecuteNonQuery(); + int ExecuteNonQuery(); /// Executes this command and returns an ISqlReader for reading the results - public abstract ISqlReader ExecuteReader(); - public abstract void Dispose(); + ISqlReader ExecuteReader(); } - public abstract class ISqlTransaction : IDisposable + public interface ISqlTransaction : IDisposable { - public abstract void Commit(); - public abstract void Rollback(); - public abstract void Dispose(); + void Commit(); + void Rollback(); } /// Abstracts iterating over the results from executing a SQL command diff --git a/MCGalaxy/Database/Backends/MySQL.cs b/MCGalaxy/Database/Backends/MySQL.cs index 0873ee6..879288c 100644 --- a/MCGalaxy/Database/Backends/MySQL.cs +++ b/MCGalaxy/Database/Backends/MySQL.cs @@ -24,7 +24,7 @@ permissions and limitations under the Licenses. namespace MCGalaxy.SQL { - public sealed class MySQLBackend : IDatabaseBackend + public class MySQLBackend : IDatabaseBackend { public static IDatabaseBackend Instance = new MySQLBackend(); public MySQLBackend() { @@ -33,10 +33,10 @@ public MySQLBackend() { CaselessLikeSuffix = ""; } - public override bool EnforcesTextLength { get { return true; } } + public override bool EnforcesTextLength { get { return true; } } public override bool EnforcesIntegerLimits { get { return true; } } public override bool MultipleSchema { get { return true; } } - public override string EngineName { get { return "MySQL"; } } + public override string EngineName { get { return "MySQL"; } } public override ISqlConnection CreateConnection() { const string format = "Data Source={0};Port={1};User ID={2};Password={3};Pooling={4};Treat Tiny As Boolean=false;"; @@ -164,20 +164,20 @@ sealed class MySQLConnection : ISqlConnection public readonly MySqlConnection conn; public MySQLConnection(MySqlConnection conn) { this.conn = conn; } - public override ISqlTransaction BeginTransaction() { + public ISqlTransaction BeginTransaction() { MySqlTransaction trn = conn.BeginTransaction(); return new MySQLTransaction(trn); } - public override ISqlCommand CreateCommand(string sql) { + public ISqlCommand CreateCommand(string sql) { MySqlCommand cmd = new MySqlCommand(sql, conn); return new MySQLCommand(cmd); } - public override void Open() { conn.Open(); } - public override void ChangeDatabase(string name) { conn.ChangeDatabase(name); } - public override void Close() { conn.Close(); } - public override void Dispose() { conn.Dispose(); } + public void Open() { conn.Open(); } + public void ChangeDatabase(string name) { conn.ChangeDatabase(name); } + public void Close() { conn.Close(); } + public void Dispose() { conn.Dispose(); } } sealed class MySQLCommand : ISqlCommand @@ -185,18 +185,18 @@ sealed class MySQLCommand : ISqlCommand readonly MySqlCommand cmd; public MySQLCommand(MySqlCommand cmd) { this.cmd = cmd; } - public override void ClearParameters() { + public void ClearParameters() { cmd.Parameters.Clear(); } - public override void AddParameter(string name, object value) { + public void AddParameter(string name, object value) { cmd.Parameters.AddWithValue(name, value); } - public override void Dispose() { cmd.Dispose(); } - public override void Prepare() { cmd.Prepare(); } - public override int ExecuteNonQuery() { return cmd.ExecuteNonQuery(); } + public void Dispose() { cmd.Dispose(); } + public void Prepare() { cmd.Prepare(); } + public int ExecuteNonQuery() { return cmd.ExecuteNonQuery(); } - public override ISqlReader ExecuteReader() { + public ISqlReader ExecuteReader() { MySqlDataReader rdr = cmd.ExecuteReader(); return new MySQLReader(rdr); } @@ -207,9 +207,9 @@ sealed class MySQLTransaction : ISqlTransaction readonly MySqlTransaction trn; public MySQLTransaction(MySqlTransaction trn) { this.trn = trn; } - public override void Commit() { trn.Commit(); } - public override void Rollback() { trn.Rollback(); } - public override void Dispose() { trn.Dispose(); } + public void Commit() { trn.Commit(); } + public void Rollback() { trn.Rollback(); } + public void Dispose() { trn.Dispose(); } } sealed class MySQLReader : ISqlReader diff --git a/MCGalaxy/Database/Backends/SQLite.cs b/MCGalaxy/Database/Backends/SQLite.cs index f627c91..6f5b1f8 100644 --- a/MCGalaxy/Database/Backends/SQLite.cs +++ b/MCGalaxy/Database/Backends/SQLite.cs @@ -23,7 +23,7 @@ permissions and limitations under the Licenses. namespace MCGalaxy.SQL { - public sealed class SQLiteBackend : IDatabaseBackend + public class SQLiteBackend : IDatabaseBackend { public static IDatabaseBackend Instance = new SQLiteBackend(); public SQLiteBackend() { @@ -31,10 +31,10 @@ public SQLiteBackend() { CaselessLikeSuffix = " COLLATE NOCASE"; } - public override bool EnforcesTextLength { get { return false; } } + public override bool EnforcesTextLength { get { return false; } } public override bool EnforcesIntegerLimits { get { return false; } } public override bool MultipleSchema { get { return false; } } - public override string EngineName { get { return "SQLite"; } } + public override string EngineName { get { return "SQLite"; } } public override ISqlConnection CreateConnection() { return new MCGSQLiteConnection(); diff --git a/MCGalaxy/Database/Backends/SQLiteBackend.cs b/MCGalaxy/Database/Backends/SQLiteBackend.cs index e275f1c..ebca1a3 100644 --- a/MCGalaxy/Database/Backends/SQLiteBackend.cs +++ b/MCGalaxy/Database/Backends/SQLiteBackend.cs @@ -105,13 +105,13 @@ public abstract class SQLiteConnection : ISqlConnection protected abstract bool ConnectionPooling { get; } protected abstract string DBPath { get; } - public override ISqlTransaction BeginTransaction() { + public ISqlTransaction BeginTransaction() { return new SQLiteTransaction(this); } - public override void ChangeDatabase(string databaseName) { } + public void ChangeDatabase(string databaseName) { } - public override ISqlCommand CreateCommand(string sql) { return new SQLiteCommand(sql, this); } + public ISqlCommand CreateCommand(string sql) { return new SQLiteCommand(sql, this); } public long LastInsertRowId { get { @@ -170,7 +170,7 @@ internal SQLiteStatement Prepare(string strSql, ref string strRemain) { } } - public override void Open() { + public void Open() { if (handle != IntPtr.Zero) throw new InvalidOperationException(); try { @@ -226,8 +226,8 @@ internal bool Reset(bool canThrow) { return false; } - public override void Dispose() { Close(false); } - public override void Close() { Close(true); } + public void Dispose() { Close(false); } + public void Close() { Close(true); } void Close(bool canThrow) { if (handle == IntPtr.Zero) return; @@ -291,7 +291,7 @@ void DisposeStatement() { stmt = null; } - public override void Dispose() { + public void Dispose() { conn = null; param_names.Clear(); param_values.Clear(); @@ -316,19 +316,19 @@ internal SQLiteStatement NextStatement() { return stmt; } - public override void Prepare() { } + public void Prepare() { } - public override void ClearParameters() { + public void ClearParameters() { param_names.Clear(); param_values.Clear(); } - public override void AddParameter(string name, object value) { + public void AddParameter(string name, object value) { param_names.Add(name); param_values.Add(value); } - public override ISqlReader ExecuteReader() { + public ISqlReader ExecuteReader() { SQLiteConnection.Check(conn); SQLiteDataReader reader = new SQLiteDataReader(this); @@ -336,7 +336,7 @@ public override ISqlReader ExecuteReader() { return reader; } - public override int ExecuteNonQuery() { + public int ExecuteNonQuery() { using (ISqlReader reader = ExecuteReader()) { while (reader.Read()) { } return reader.RowsAffected; @@ -835,7 +835,7 @@ internal byte[] GetBytes(int index) { } } - public sealed class SQLiteTransaction : ISqlTransaction + public class SQLiteTransaction : ISqlTransaction { SQLiteConnection conn; @@ -855,13 +855,13 @@ internal SQLiteTransaction(SQLiteConnection connection) { } bool disposed; - public override void Dispose() { + public void Dispose() { if (disposed) return; if (IsValid(false)) IssueRollback(false); disposed = true; } - public override void Commit() { + public void Commit() { SQLiteConnection.Check(conn); IsValid(true); @@ -873,7 +873,7 @@ public override void Commit() { conn = null; } - public override void Rollback() { + public void Rollback() { SQLiteConnection.Check(conn); IsValid(true); IssueRollback(true); diff --git a/MCGalaxy/Database/IDatabaseBackend.cs b/MCGalaxy/Database/IDatabaseBackend.cs index 0889110..d6f07de 100644 --- a/MCGalaxy/Database/IDatabaseBackend.cs +++ b/MCGalaxy/Database/IDatabaseBackend.cs @@ -152,7 +152,7 @@ protected string InsertSql(string cmd, string table, string columns, int numArgs #region Raw SQL functions /// Executes an SQL command and returns the number of affected rows. - public int Execute(string sql, object[] parameters, bool createDB) { + public virtual int Execute(string sql, object[] parameters, bool createDB) { int rows = 0; using (ISqlConnection conn = CreateConnection()) { @@ -170,7 +170,7 @@ public int Execute(string sql, object[] parameters, bool createDB) { } /// Excecutes an SQL query, invoking a callback on the returned rows one by one. - public int Iterate(string sql, object[] parameters, ReaderCallback callback) { + public virtual int Iterate(string sql, object[] parameters, ReaderCallback callback) { int rows = 0; using (ISqlConnection conn = CreateConnection()) { diff --git a/MCGalaxy/Database/Stats/OnlineStat.cs b/MCGalaxy/Database/Stats/OnlineStat.cs index cbda0e0..bd2f132 100644 --- a/MCGalaxy/Database/Stats/OnlineStat.cs +++ b/MCGalaxy/Database/Stats/OnlineStat.cs @@ -53,6 +53,10 @@ public static void CoreLine(Player p, Player who) { internal static void CommonCoreLine(Player p, string fullName, string name, Group grp, int messages) { p.Message("{0} &S({1}) has:", fullName, name); p.Message(" Rank of {0}&S, wrote &a{1} &Smessages", grp.ColoredName, messages); + + Pronouns pro = Pronouns.GetFor(name); + if (pro == Pronouns.Default) { return; } + p.Message(" Pronouns: &a{0}", pro.Name); } public static void MiscLine(Player p, string name, int deaths, int money) { diff --git a/MCGalaxy/Levels/Level.Fields.cs b/MCGalaxy/Levels/Level.Fields.cs index 6e6e8cf..6e404e7 100644 --- a/MCGalaxy/Levels/Level.Fields.cs +++ b/MCGalaxy/Levels/Level.Fields.cs @@ -121,6 +121,6 @@ public int WinChance { get { return Config.RoundsPlayed == 0 ? 100 : (Config.RoundsHumanWon * 100) / Config.RoundsPlayed; } } - internal bool hasPortals, hasMessageBlocks; + public bool hasPortals, hasMessageBlocks; } } \ No newline at end of file diff --git a/MCGalaxy/MCGalaxy_dotnet.csproj b/MCGalaxy/MCGalaxy_dotnet.csproj index fd99f66..e0e6448 100644 --- a/MCGalaxy/MCGalaxy_dotnet.csproj +++ b/MCGalaxy/MCGalaxy_dotnet.csproj @@ -6,6 +6,6 @@ - + diff --git a/MCGalaxy/Modules/Relay/Discord/DiscordWebsocket.cs b/MCGalaxy/Modules/Relay/Discord/DiscordWebsocket.cs index 461cdac..85e6e7b 100644 --- a/MCGalaxy/Modules/Relay/Discord/DiscordWebsocket.cs +++ b/MCGalaxy/Modules/Relay/Discord/DiscordWebsocket.cs @@ -34,6 +34,7 @@ public sealed class DiscordSession public int Intents; } public delegate string DiscordGetStatus(); + public delegate void GatewayEventCallback(string eventName, JsonObject data); /// Implements a basic websocket for communicating with Discord's gateway /// https://discord.com/developers/docs/topics/gateway @@ -65,7 +66,7 @@ public sealed class DiscordWebsocket : ClientWebSocket /// Callback invoked when a channel created event has been received public Action OnChannelCreate; /// Callback invoked when a gateway event has been received - public Action OnGatewayEvent; + public GatewayEventCallback OnGatewayEvent; readonly object sendLock = new object(); SchedulerTask heartbeat; diff --git a/MCGalaxy/Player/Pronouns.cs b/MCGalaxy/Player/Pronouns.cs index 1aaee23..86eafad 100644 --- a/MCGalaxy/Player/Pronouns.cs +++ b/MCGalaxy/Player/Pronouns.cs @@ -19,7 +19,6 @@ permissions and limitations under the Licenses. using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using MCGalaxy.Tasks; @@ -36,7 +35,6 @@ public class Pronouns { /// /// Called once to initialize the defaults and write/read the config file as necessary. /// - /// public static void Init(SchedulerTask task) { if (!Directory.Exists(PLAYER_PATH)) { @@ -119,13 +117,15 @@ public static Pronouns GetFor(string playerName) { string myPath = PlayerPath(playerName); try { - string[] lines; + string data; lock (locker) { if (!File.Exists(myPath)) { return Default; } - lines = File.ReadAllLines(myPath); - } - if (lines.Length == 0 || string.IsNullOrWhiteSpace(lines[0])) { return Default; } - Pronouns p = FindExact(lines[0]); + data = File.ReadAllText(myPath); + } + data = data.Trim(); + + if (data.Length == 0) return Default; + Pronouns p = FindExact(data); if (p != null) return p; return Default; @@ -221,7 +221,7 @@ public void SaveFor(Player p) { string path = PlayerPath(p.name); try { //Reduce clutter by simply erasing the file if it's default - if (this.Name == Default.Name) { File.Delete(path); return; } + if (this == Default) { File.Delete(path); return; } File.WriteAllText(path, Name); } catch (Exception e) { diff --git a/MCGalaxy/Player/SpamChecker.cs b/MCGalaxy/Player/SpamChecker.cs index f33d46a..f33c693 100644 --- a/MCGalaxy/Player/SpamChecker.cs +++ b/MCGalaxy/Player/SpamChecker.cs @@ -45,7 +45,7 @@ public bool CheckBlockSpam() { return false; TimeSpan oldestDelta = DateTime.UtcNow - blockLog[0]; - Chat.MessageFromOps(p, "λNICK &Wwas kicked for suspected griefing."); + Chat.MessageFromOps(p, "λNICK &Wwas kicked from " + p.level.name + " for suspected griefing."); Logger.Log(LogType.SuspiciousActivity, "{0} was kicked for block spam ({1} blocks in {2} seconds)",