diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index deb811a2b..3d47d3c67 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -5,6 +5,10 @@ on: [push, pull_request] jobs: build: runs-on: ubuntu-latest + permissions: + attestations: write + id-token: write + packages: write steps: - name: Checkout uses: actions/checkout@v4 @@ -14,12 +18,43 @@ jobs: uses: docker/setup-qemu-action@v3 - name: Set up buildx uses: docker/setup-buildx-action@v3 + - name: Login to ghcr.io + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Generate version information + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=schedule + type=ref,event=branch + type=ref,event=tag,enable=${{ !startsWith(github.ref, 'refs/tags/v') }} + type=ref,event=pr + type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }} + type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }} + type=semver,pattern={{major}},enable=${{ startsWith(github.ref, 'refs/tags/v') }} + flavor: | + latest=${{ startsWith(github.ref, 'refs/tags/v') }} - name: Build image - uses: docker/build-push-action@v5 + id: build + uses: docker/build-push-action@v6 with: context: . platforms: linux/amd64,linux/arm64,linux/arm/v7,windows/amd64 - push: false + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} pull: true cache-from: type=gha, scope=${{ github.workflow }} cache-to: type=gha, scope=${{ github.workflow }} + - name: Generate build provenance attestation + if: ${{ github.event_name != 'pull_request' }} + uses: actions/attest-build-provenance@v2 + with: + subject-name: ghcr.io/${{ github.repository }} + subject-digest: ${{ steps.build.outputs.digest }} + push-to-registry: true diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 58c14b1cd..0f5f6e3c8 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -424,7 +424,7 @@ internal Bouncer() }; PlayerAddBuffWhitelist[BuffID.BrainOfConfusionBuff] = new BuffLimit { - MaxTicks = 240, + MaxTicks = 60 * 4, CanBeAddedWithoutHostile = true, CanOnlyBeAppliedToSender = true }; @@ -434,6 +434,12 @@ internal Bouncer() CanBeAddedWithoutHostile = true, CanOnlyBeAppliedToSender = true }; + PlayerAddBuffWhitelist[BuffID.ParryDamageBuff] = new BuffLimit + { + MaxTicks = 60 * 5, + CanBeAddedWithoutHostile = true, + CanOnlyBeAppliedToSender = true + }; #endregion Whitelist } @@ -1878,7 +1884,7 @@ void Reject(bool shouldResync = true) return; } - if (TShock.Players[id] == null) + if (TShock.Players[id] == null || !TShock.Players[id].Active) { TShock.Log.ConsoleDebug(GetString( "Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: target is null", args.Player.Name, @@ -2081,7 +2087,7 @@ internal void OnHealOtherPlayer(object sender, GetDataHandlers.HealOtherPlayerEv short amount = args.Amount; byte plr = args.TargetPlayerIndex; - if (amount <= 0 || Main.player[plr] == null || !Main.player[plr].active) + if (amount <= 0 || TShock.Players[plr] == null || !TShock.Players[plr].Active) { TShock.Log.ConsoleDebug(GetString("Bouncer / OnHealOtherPlayer rejected null checks")); args.Handled = true; @@ -2589,7 +2595,7 @@ internal void OnPlayerDamage(object sender, GetDataHandlers.PlayerDamageEventArg byte direction = args.Direction; PlayerDeathReason reason = args.PlayerDeathReason; - if (id >= Main.maxPlayers || TShock.Players[id] == null) + if (id >= Main.maxPlayers || TShock.Players[id] == null || !TShock.Players[id].Active) { TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerDamage rejected null check")); args.Handled = true; diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index d39b84e0c..1006b50f8 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -3070,12 +3070,12 @@ private static void TPHere(CommandArgs args) args.Player.SendErrorMessage(GetString("You do not have permission to teleport all other players.")); return; } - for (int i = 0; i < Main.maxPlayers; i++) + foreach (var player in TShock.Players) { - if (Main.player[i].active && (Main.player[i] != args.TPlayer)) + if (player != null && player.Active && player.Index != args.Player.Index) { - if (TShock.Players[i].Teleport(args.TPlayer.position.X, args.TPlayer.position.Y)) - TShock.Players[i].SendSuccessMessage(GetString("You were teleported to {0}.", args.Player.Name)); + if (player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y)) + player.SendSuccessMessage(GetString("You were teleported to {0}.", args.Player.Name)); } } args.Player.SendSuccessMessage(GetString("Teleported everyone to yourself.")); @@ -4622,21 +4622,22 @@ private static void Wind(CommandArgs args) { if (args.Parameters.Count != 1) { - args.Player.SendErrorMessage(GetString("Invalid syntax. Proper syntax: {0}wind .", Specifier)); + args.Player.SendErrorMessage(GetString("Invalid syntax. Proper syntax: {0}wind .", Specifier)); return; } - int speed; - if (!int.TryParse(args.Parameters[0], out speed) || speed * 100 < 0) + float mph; + if (!float.TryParse(args.Parameters[0], out mph) || mph is < -40f or > 40f) { - args.Player.SendErrorMessage(GetString("Invalid wind speed.")); + args.Player.SendErrorMessage(GetString("Invalid wind speed (must be between -40 and 40).")); return; } + float speed = mph / 50f; // -40 to 40 mph -> -0.8 to 0.8 Main.windSpeedCurrent = speed; Main.windSpeedTarget = speed; TSPlayer.All.SendData(PacketTypes.WorldInfo); - TSPlayer.All.SendInfoMessage(GetString("{0} changed the wind speed to {1}.", args.Player.Name, speed)); + TSPlayer.All.SendInfoMessage(GetString("{0} changed the wind speed to {1}mph.", args.Player.Name, mph)); } #endregion Time/PvpFun Commands diff --git a/TShockAPI/Rest/Rest.cs b/TShockAPI/Rest/Rest.cs index 58cc23d8f..a6e681e2a 100644 --- a/TShockAPI/Rest/Rest.cs +++ b/TShockAPI/Rest/Rest.cs @@ -351,7 +351,6 @@ protected virtual void OnRequest(object sender, RequestEventArgs e) { str = string.Format("{0}({1});", jsonp, str); } - e.Response.Connection.Type = ConnectionType.Close; e.Response.ContentType = new ContentTypeHeader("application/json; charset=utf-8"); e.Response.Add(serverHeader); var bytes = Encoding.UTF8.GetBytes(str); diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index c41e7767b..b6efd6c5f 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -402,7 +402,7 @@ private object ServerStatusV2(RestRequestArgs args) {"serverversion", Main.versionNumber}, {"tshockversion", TShock.VersionNum}, {"port", TShock.Config.Settings.ServerPort}, - {"playercount", Main.player.Where(p => null != p && p.active).Count()}, + {"playercount", TShock.Utils.GetActivePlayerCount()}, {"maxplayers", TShock.Config.Settings.MaxSlots}, {"world", (TShock.Config.Settings.UseServerName ? TShock.Config.Settings.ServerName : Main.worldName)}, {"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")}, @@ -944,8 +944,8 @@ private object PlayerMute(RestRequestArgs args) [Token] private object PlayerList(RestRequestArgs args) { - var activeplayers = Main.player.Where(p => null != p && p.active).ToList(); - return new RestObject() { { "players", string.Join(", ", activeplayers.Select(p => p.name)) } }; + var activeplayers = TShock.Players.Where(p => null != p && p.Active).Select(p => p.Name); + return new RestObject() { { "players", string.Join(", ", activeplayers) } }; } [Description("Fetches detailed user information on all connected users, and can be filtered by specifying a key value pair filter users where the key is a field and the value is a users field value.")] diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index 9da8cd085..34df3c74c 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -34,7 +34,7 @@ - + diff --git a/TShockAPI/Utils.cs b/TShockAPI/Utils.cs index 4ee41c012..23b1e224a 100644 --- a/TShockAPI/Utils.cs +++ b/TShockAPI/Utils.cs @@ -172,7 +172,7 @@ public void SendLogs(string log, Color color, TSPlayer excludedPlayer = null) foreach (TSPlayer player in TShock.Players) { if (player != null && player != excludedPlayer && player.Active && player.HasPermission(Permissions.logs) && - player.DisplayLogs && TShock.Config.Settings.DisableSpewLogs == false) + player.DisplayLogs && !TShock.Config.Settings.DisableSpewLogs) player.SendMessage(log, color); } } @@ -183,7 +183,7 @@ public void SendLogs(string log, Color color, TSPlayer excludedPlayer = null) /// The number of active players on the server. public int GetActivePlayerCount() { - return Main.player.Where(p => null != p && p.active).Count(); + return TShock.Players.Count(p => null != p && p.Active); } //Random should not be generated in a method diff --git a/TShockLauncher/TShockLauncher.csproj b/TShockLauncher/TShockLauncher.csproj index e3c4ac327..fbe428bb1 100644 --- a/TShockLauncher/TShockLauncher.csproj +++ b/TShockLauncher/TShockLauncher.csproj @@ -30,7 +30,7 @@ - + diff --git a/docs/changelog.md b/docs/changelog.md index 1fd039703..09e2254ba 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -79,12 +79,15 @@ Use past tense when adding new entries; sign your name off when you add or chang ## Upcoming changes * Fixed `/dump-reference-data` mutate the command names. (#2943, @sgkoishi) -* You know the drill +* Added `ParryDamageBuff` (Striking Moment with Brand of the Inferno and shield) for player, updated `CursedInferno` buff for NPC (@sgkoishi, #3005) +* Changed the use of `Player.active` to `TSPlayer.Active` for consistency. (@sgkoishi, #2939) * Fix typo in config for IP bans. (@redchess64) * Updated `TShockAPI.NetItem` (@AgaSpace): -* Added constructor overload with parameter `Terraria.Item`. -* Added the `ToItem` method to get a copy of `Terraria.Item`. -* In the constructor `stack` and `prefix` are now optional parameters. + * Added constructor overload with parameter `Terraria.Item`. + * Added the `ToItem` method to get a copy of `Terraria.Item`. + * In the constructor `stack` and `prefix` are now optional parameters. +* Fixed unable to transfer long response body for REST API. (@sgkoishi, #2925) +* Fixed the `/wind` command not being very helpful. (@punchready) ## TShock 5.2.1 * Updated `TSPlayer.GodMode`. (@AgaSpace) @@ -100,6 +103,7 @@ Use past tense when adding new entries; sign your name off when you add or chang * Fixed bug where when the `UseSqlLogs` config property is true, an empty log file would still get created. (@ZakFahey) * Fixed typo in `/gbuff`. (@sgkoishi, #2955) + ## TShock 5.2 * An additional option `pvpwithnoteam` is added at `PvPMode` to enable PVP with no team. (@CelestialAnarchy, #2617, @ATFGK) * Corrected and updated deserialization of the following packets (@ATFGK): @@ -132,7 +136,6 @@ Use past tense when adding new entries; sign your name off when you add or chang * Relaxed custom death message restrictions to allow Inferno potions in PvP. (@drunderscore) * Allowed Flower Boots to place Ash Flowers on Ash Grass blocks. (@punchready) * Removed unnecessary range check that artifically shortened quick stack reach. (@boddyn, #2885, @bcat) -* Re-wrote tile rect handling from scratch, fixing a certain exploitable flaw in the old code and significantly reducing the potential exploit surface, potentially even down to zero. (@punchready) ## TShock 5.1.3 * Added support for Terraria 1.4.4.9 via OTAPI 3.1.20. (@SignatureBeef) diff --git a/docs/docker.md b/docs/docker.md index ca0185103..afc4bdfc9 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -14,32 +14,27 @@ Open ports can also be passed through using `-p :`. For Example: ```bash -# Building the image using buildx and loading it into docker -docker buildx build -t tshock:latest --load . - -# Running the image docker run -p 7777:7777 -p 7878:7878 \ -v /home/cider/tshock/:/tshock \ -v /home/cider/.local/share/Terraria/Worlds:/worlds \ -v /home/cider/tshock/plugins:/plugins \ - --rm -it tshock:latest \ + --rm -it ghcr.io/pryaxis/tshock:latest \ -world /worlds/backflip.wld -motd "OMFG DOCKER" ``` -## Building for Other Platforms +## Building custom images -Using `docker buildx`, you could build [multi-platform images](https://docs.docker.com/build/building/multi-platform/) for TShock. +Occasionally, it may be necessary to adjust TShock with customizations that are not included in the upstream project. +Therefore, these changes are also not available in the officially provided Docker images. + +To build and load a Docker image from your local checkout, use the following `buildx` command: -For Example: ```bash -# Building the image using buildx and loading it into docker -docker buildx build -t tshock:linux-arm64 --platform linux/arm64 --load . +docker buildx build -t tshock:latest --load . +``` -# Running the image -docker run -p 7777:7777 -p 7878:7878 \ - -v /home/cider/tshock/:/tshock \ - -v /home/cider/.local/share/Terraria/Worlds:/worlds \ - -v /home/cider/tshock/plugins:/plugins \ - --rm -it tshock:linux-arm64 \ - -world /worlds/backflip.wld -motd "ARM64 ftw" +It is also possible to build [multi-platform images](https://docs.docker.com/build/building/multi-platform/) for TShock (e.g. an image targeting `arm64`, on a host that is not `arm64`): + +```bash +docker buildx build -t tshock:linux-arm64 --platform linux/arm64 --load . ``` diff --git a/docs/index.html b/docs/index.html index 2ae1df82e..0cfccf115 100644 --- a/docs/index.html +++ b/docs/index.html @@ -11,12 +11,7 @@
diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 159ec1e22..000000000 --- a/renovate.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:base" - ], - "git-submodules": { - "enabled": true - }, - "packageRules": [ - { - "matchPackageNames": ["OTAPI.Upcoming", "ModFramework", "TerrariaServerAPI"], - "ignoreUnstable": "false", - "bumpVersion": "prerelease", - "groupName": "OTAPI things" - } - ] -}