Merge branch 'general-devel' into feature/properly-seed-group-names-in-database
This commit is contained in:
commit
329fce0089
45 changed files with 3391 additions and 2148 deletions
|
|
@ -1,15 +1,20 @@
|
||||||
# ignore every file
|
# Ignore all Git metadata and build output (in all directories).
|
||||||
*
|
**/.git*
|
||||||
|
**/bin/
|
||||||
|
**/obj/
|
||||||
|
|
||||||
# except for the ones required for building
|
# Ignore other specific files that aren't needed for the build itself.
|
||||||
!i18n/
|
/.all-contributorsrc
|
||||||
!prebuilts/
|
/.dockerignore
|
||||||
!TerrariaServerAPI/
|
/.editorconfig
|
||||||
!TShockAPI/
|
/.vscode
|
||||||
!TShockLauncher/
|
/appveyor.yml
|
||||||
!TShockLauncher.Tests/
|
/COPYING
|
||||||
!TShock.sln
|
/crowdin.yml
|
||||||
|
/Dockerfile
|
||||||
# but exclude build artifacts
|
/docs
|
||||||
*/bin/
|
/README.md
|
||||||
*/obj/
|
/README_cn.md
|
||||||
|
/renovate.json
|
||||||
|
/scripts
|
||||||
|
/SECURITY.md
|
||||||
|
|
|
||||||
2
.github/CODE_OF_CONDUCT.md
vendored
2
.github/CODE_OF_CONDUCT.md
vendored
|
|
@ -1,3 +1,5 @@
|
||||||
> By participating in the TShock for Terraria community, all members will adhere to maintaining decorum with respect to all humans, in and out of the community. Members will not engage in discussion that inappropriately disparages or marginalizes any group of people or any individual. Members will not attempt to further or advance an agenda to the point of being overbearing or close minded (such as through spreading FUD). Members will not abuse services provided to them and will follow the guidance of community leaders on a situational basis about what abuse consists of. Members will adhere to United States and international law. If members notice a violation of this code of conduct, they will not engage but will instead contact the leadership team on either the forums or Discord.
|
> By participating in the TShock for Terraria community, all members will adhere to maintaining decorum with respect to all humans, in and out of the community. Members will not engage in discussion that inappropriately disparages or marginalizes any group of people or any individual. Members will not attempt to further or advance an agenda to the point of being overbearing or close minded (such as through spreading FUD). Members will not abuse services provided to them and will follow the guidance of community leaders on a situational basis about what abuse consists of. Members will adhere to United States and international law. If members notice a violation of this code of conduct, they will not engage but will instead contact the leadership team on either the forums or Discord.
|
||||||
|
|
||||||
> Do not attempt to circumvent or bypass the code of conduct by using clever logic or reasoning (e.g., insulting Facepunch members, because they weren't directly mentioned here).
|
> Do not attempt to circumvent or bypass the code of conduct by using clever logic or reasoning (e.g., insulting Facepunch members, because they weren't directly mentioned here).
|
||||||
|
|
||||||
|
> Do not abuse GitHub services by generating useless emails to all people who watch the repo. This includes unnecessary PR approvals and off-topic discussion, issue, and PR comments that serve no purpose. Due to the high visibility nature of actions that create emails, you may be blocked temporarily as your first warning.
|
||||||
|
|
|
||||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
|
@ -1,2 +1,2 @@
|
||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
github: [SignatureBeef, hakusaro, Stealownz, QuiCM]
|
github: [SignatureBeef, QuiCM]
|
||||||
|
|
|
||||||
60
.github/workflows/ci-docker.yml
vendored
Normal file
60
.github/workflows/ci-docker.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
name: CI (Docker image)
|
||||||
|
|
||||||
|
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
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
- name: Set up QEMU
|
||||||
|
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
|
||||||
|
id: build
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7,windows/amd64
|
||||||
|
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
|
||||||
4
.github/workflows/ci-otapi3.yml
vendored
4
.github/workflows/ci-otapi3.yml
vendored
|
|
@ -63,14 +63,14 @@ jobs:
|
||||||
tar -cvf ../../../../../../TShock-Beta-${{ matrix.arch }}-Release.tar *
|
tar -cvf ../../../../../../TShock-Beta-${{ matrix.arch }}-Release.tar *
|
||||||
|
|
||||||
- name: Upload artifact (non-Windows)
|
- name: Upload artifact (non-Windows)
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
if: ${{ matrix.arch != 'win-x64' }}
|
if: ${{ matrix.arch != 'win-x64' }}
|
||||||
with:
|
with:
|
||||||
name: TShock-Beta-${{ matrix.arch }}-Release
|
name: TShock-Beta-${{ matrix.arch }}-Release
|
||||||
path: TShock-Beta-${{ matrix.arch }}-Release.tar
|
path: TShock-Beta-${{ matrix.arch }}-Release.tar
|
||||||
|
|
||||||
- name: Upload artifact (Windows)
|
- name: Upload artifact (Windows)
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
if: ${{ matrix.arch == 'win-x64' }}
|
if: ${{ matrix.arch == 'win-x64' }}
|
||||||
with:
|
with:
|
||||||
name: TShock-Beta-${{ matrix.arch }}-Release
|
name: TShock-Beta-${{ matrix.arch }}-Release
|
||||||
|
|
|
||||||
10
Dockerfile
10
Dockerfile
|
|
@ -1,10 +1,8 @@
|
||||||
ARG TARGETPLATFORM=linux/amd64
|
# TARGETPLATFORM and BUILDPLATFORM are automatically filled in by Docker buildx.
|
||||||
ARG BUILDPLATFORM=${TARGETPLATFORM}
|
# They should not be set in the global scope manually.
|
||||||
|
|
||||||
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/dotnet/sdk:6.0 AS builder
|
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/dotnet/sdk:6.0 AS builder
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
|
|
||||||
# Copy build context
|
# Copy build context
|
||||||
WORKDIR /TShock
|
WORKDIR /TShock
|
||||||
COPY . ./
|
COPY . ./
|
||||||
|
|
@ -12,6 +10,10 @@ COPY . ./
|
||||||
# Build and package release based on target architecture
|
# Build and package release based on target architecture
|
||||||
RUN dotnet build -v m
|
RUN dotnet build -v m
|
||||||
WORKDIR /TShock/TShockLauncher
|
WORKDIR /TShock/TShockLauncher
|
||||||
|
|
||||||
|
# Make TARGETPLATFORM available to the container.
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
case "${TARGETPLATFORM}" in \
|
case "${TARGETPLATFORM}" in \
|
||||||
"linux/amd64") export ARCH="linux-x64" \
|
"linux/amd64") export ARCH="linux-x64" \
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://tshock.co/newlogo.png" alt="TShock for Terraria"><br />
|
<img src="https://tshock.s3.us-west-001.backblazeb2.com/newlogo.png" alt="TShock for Terraria"><br />
|
||||||
<a href="https://ci.appveyor.com/project/hakusaro/tshock">
|
<a href="https://ci.appveyor.com/project/hakusaro/tshock">
|
||||||
<img src="https://ci.appveyor.com/api/projects/status/chhe61q227lqdlg1?svg=true" alt="AppVeyor Build Status">
|
<img src="https://ci.appveyor.com/api/projects/status/chhe61q227lqdlg1?svg=true" alt="AppVeyor Build Status">
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://tshock.co/newlogo.png" alt="TShock for Terraria"><br />
|
<img src="https://tshock.s3.us-west-001.backblazeb2.com/newlogo.png" alt="TShock for Terraria"><br />
|
||||||
<a href="https://ci.appveyor.com/project/hakusaro/tshock">
|
<a href="https://ci.appveyor.com/project/hakusaro/tshock">
|
||||||
<img src="https://ci.appveyor.com/api/projects/status/chhe61q227lqdlg1?svg=true" alt="AppVeyor Build Status">
|
<img src="https://ci.appveyor.com/api/projects/status/chhe61q227lqdlg1?svg=true" alt="AppVeyor Build Status">
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -424,7 +424,7 @@ namespace TShockAPI
|
||||||
};
|
};
|
||||||
PlayerAddBuffWhitelist[BuffID.BrainOfConfusionBuff] = new BuffLimit
|
PlayerAddBuffWhitelist[BuffID.BrainOfConfusionBuff] = new BuffLimit
|
||||||
{
|
{
|
||||||
MaxTicks = 240,
|
MaxTicks = 60 * 4,
|
||||||
CanBeAddedWithoutHostile = true,
|
CanBeAddedWithoutHostile = true,
|
||||||
CanOnlyBeAppliedToSender = true
|
CanOnlyBeAppliedToSender = true
|
||||||
};
|
};
|
||||||
|
|
@ -434,6 +434,12 @@ namespace TShockAPI
|
||||||
CanBeAddedWithoutHostile = true,
|
CanBeAddedWithoutHostile = true,
|
||||||
CanOnlyBeAppliedToSender = true
|
CanOnlyBeAppliedToSender = true
|
||||||
};
|
};
|
||||||
|
PlayerAddBuffWhitelist[BuffID.ParryDamageBuff] = new BuffLimit
|
||||||
|
{
|
||||||
|
MaxTicks = 60 * 5,
|
||||||
|
CanBeAddedWithoutHostile = true,
|
||||||
|
CanOnlyBeAppliedToSender = true
|
||||||
|
};
|
||||||
|
|
||||||
#endregion Whitelist
|
#endregion Whitelist
|
||||||
}
|
}
|
||||||
|
|
@ -498,6 +504,14 @@ namespace TShockAPI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!float.IsFinite(pos.X) || !float.IsFinite(pos.Y))
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleInfo(GetString("Bouncer / OnPlayerUpdate force kicked (attempted to set position to infinity or NaN) from {0}", args.Player.Name));
|
||||||
|
args.Player.Kick(GetString("Detected DOOM set to ON position."), true, true);
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos.X < 0 || pos.Y < 0 || pos.X >= Main.maxTilesX * 16 - 16 || pos.Y >= Main.maxTilesY * 16 - 16)
|
if (pos.X < 0 || pos.Y < 0 || pos.X >= Main.maxTilesX * 16 - 16 || pos.Y >= Main.maxTilesY * 16 - 16)
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerUpdate rejected from (position check) {0}", args.Player.Name));
|
TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerUpdate rejected from (position check) {0}", args.Player.Name));
|
||||||
|
|
@ -1066,6 +1080,22 @@ namespace TShockAPI
|
||||||
bool noDelay = args.NoDelay;
|
bool noDelay = args.NoDelay;
|
||||||
short type = args.Type;
|
short type = args.Type;
|
||||||
|
|
||||||
|
if (!float.IsFinite(pos.X) || !float.IsFinite(pos.Y))
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleInfo(GetString("Bouncer / OnItemDrop force kicked (attempted to set position to infinity or NaN) from {0}", args.Player.Name));
|
||||||
|
args.Player.Kick(GetString("Detected DOOM set to ON position."), true, true);
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!float.IsFinite(vel.X) || !float.IsFinite(vel.Y))
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleInfo(GetString("Bouncer / OnItemDrop force kicked (attempted to set velocity to infinity or NaN) from {0}", args.Player.Name));
|
||||||
|
args.Player.Kick(GetString("Detected DOOM set to ON position."), true, true);
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// player is attempting to crash clients
|
// player is attempting to crash clients
|
||||||
if (type < -48 || type >= Terraria.ID.ItemID.Count)
|
if (type < -48 || type >= Terraria.ID.ItemID.Count)
|
||||||
{
|
{
|
||||||
|
|
@ -1169,6 +1199,22 @@ namespace TShockAPI
|
||||||
int index = args.Index;
|
int index = args.Index;
|
||||||
float[] ai = args.Ai;
|
float[] ai = args.Ai;
|
||||||
|
|
||||||
|
if (!float.IsFinite(pos.X) || !float.IsFinite(pos.Y))
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleInfo(GetString("Bouncer / OnNewProjectile force kicked (attempted to set position to infinity or NaN) from {0}", args.Player.Name));
|
||||||
|
args.Player.Kick(GetString("Detected DOOM set to ON position."), true, true);
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!float.IsFinite(vel.X) || !float.IsFinite(vel.Y))
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleInfo(GetString("Bouncer / OnNewProjectile force kicked (attempted to set velocity to infinity or NaN) from {0}", args.Player.Name));
|
||||||
|
args.Player.Kick(GetString("Detected DOOM set to ON position."), true, true);
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (index > Main.maxProjectiles)
|
if (index > Main.maxProjectiles)
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug(GetString("Bouncer / OnNewProjectile rejected from above projectile limit from {0}", args.Player.Name));
|
TShock.Log.ConsoleDebug(GetString("Bouncer / OnNewProjectile rejected from above projectile limit from {0}", args.Player.Name));
|
||||||
|
|
@ -1878,7 +1924,7 @@ namespace TShockAPI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TShock.Players[id] == null)
|
if (TShock.Players[id] == null || !TShock.Players[id].Active)
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug(GetString(
|
TShock.Log.ConsoleDebug(GetString(
|
||||||
"Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: target is null", args.Player.Name,
|
"Bouncer / OnPlayerBuff rejected {0} ({1}) applying buff {2} to {3} for {4} ticks: target is null", args.Player.Name,
|
||||||
|
|
@ -2081,7 +2127,7 @@ namespace TShockAPI
|
||||||
short amount = args.Amount;
|
short amount = args.Amount;
|
||||||
byte plr = args.TargetPlayerIndex;
|
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"));
|
TShock.Log.ConsoleDebug(GetString("Bouncer / OnHealOtherPlayer rejected null checks"));
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|
@ -2589,7 +2635,7 @@ namespace TShockAPI
|
||||||
byte direction = args.Direction;
|
byte direction = args.Direction;
|
||||||
PlayerDeathReason reason = args.PlayerDeathReason;
|
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"));
|
TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerDamage rejected null check"));
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|
@ -2659,9 +2705,12 @@ namespace TShockAPI
|
||||||
* If the player was not specified, that is, the player index is -1, then it is definitely a custom cause, as you can only deal damage with a projectile or another player.
|
* If the player was not specified, that is, the player index is -1, then it is definitely a custom cause, as you can only deal damage with a projectile or another player.
|
||||||
* This is how everything else works. If an NPC is specified, its value is not -1, which is a custom cause.
|
* This is how everything else works. If an NPC is specified, its value is not -1, which is a custom cause.
|
||||||
*
|
*
|
||||||
|
* An exception to this is damage dealt by the Inferno potion to other players -- it is only identified by the other index value of 16,
|
||||||
|
* even lacking a source player index.
|
||||||
|
*
|
||||||
* Checking whether this damage came from the player is necessary, because the damage from the player can come even when it is hit by a NPC
|
* Checking whether this damage came from the player is necessary, because the damage from the player can come even when it is hit by a NPC
|
||||||
*/
|
*/
|
||||||
if (TShock.Config.Settings.DisableCustomDeathMessages && id != args.Player.Index &&
|
if (TShock.Config.Settings.DisableCustomDeathMessages && id != args.Player.Index && reason._sourceOtherIndex != 16 &&
|
||||||
(reason._sourcePlayerIndex == -1 || reason._sourceNPCIndex != -1 || reason._sourceOtherIndex != -1 || reason._sourceCustomReason != null))
|
(reason._sourcePlayerIndex == -1 || reason._sourceNPCIndex != -1 || reason._sourceOtherIndex != -1 || reason._sourceCustomReason != null))
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerDamage rejected custom death message from {0}", args.Player.Name));
|
TShock.Log.ConsoleDebug(GetString("Bouncer / OnPlayerDamage rejected custom death message from {0}", args.Player.Name));
|
||||||
|
|
@ -2851,7 +2900,7 @@ namespace TShockAPI
|
||||||
{ BuffID.Poisoned, 3600 }, // BuffID: 20
|
{ BuffID.Poisoned, 3600 }, // BuffID: 20
|
||||||
{ BuffID.OnFire, 1200 }, // BuffID: 24
|
{ BuffID.OnFire, 1200 }, // BuffID: 24
|
||||||
{ BuffID.Confused, short.MaxValue }, // BuffID: 31 Brain of Confusion Internal Item ID: 3223
|
{ BuffID.Confused, short.MaxValue }, // BuffID: 31 Brain of Confusion Internal Item ID: 3223
|
||||||
{ BuffID.CursedInferno, 420 }, // BuffID: 39
|
{ BuffID.CursedInferno, 600 }, // BuffID: 39
|
||||||
{ BuffID.Frostburn, 900 }, // BuffID: 44
|
{ BuffID.Frostburn, 900 }, // BuffID: 44
|
||||||
{ BuffID.Ichor, 1200 }, // BuffID: 69
|
{ BuffID.Ichor, 1200 }, // BuffID: 69
|
||||||
{ BuffID.Venom, 1800 }, // BuffID: 70
|
{ BuffID.Venom, 1800 }, // BuffID: 70
|
||||||
|
|
|
||||||
|
|
@ -148,24 +148,29 @@ namespace TShockAPI
|
||||||
Permissions = new List<string>();
|
Permissions = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Run(string msg, bool silent, TSPlayer ply, List<string> parms)
|
public bool Run(CommandArgs args)
|
||||||
{
|
{
|
||||||
if (!CanRun(ply))
|
if (!CanRun(args.Player))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CommandDelegate(new CommandArgs(msg, silent, ply, parms));
|
CommandDelegate(args);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ply.SendErrorMessage(GetString("Command failed, check logs for more details."));
|
args.Player.SendErrorMessage(GetString("Command failed, check logs for more details."));
|
||||||
TShock.Log.Error(e.ToString());
|
TShock.Log.Error(e.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Run(string msg, bool silent, TSPlayer ply, List<string> parms)
|
||||||
|
{
|
||||||
|
return Run(new CommandArgs(msg, silent, ply, parms));
|
||||||
|
}
|
||||||
|
|
||||||
public bool Run(string msg, TSPlayer ply, List<string> parms)
|
public bool Run(string msg, TSPlayer ply, List<string> parms)
|
||||||
{
|
{
|
||||||
return Run(msg, false, ply, parms);
|
return Run(msg, false, ply, parms);
|
||||||
|
|
@ -704,7 +709,12 @@ namespace TShockAPI
|
||||||
TShock.Utils.SendLogs(GetString("{0} executed: {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdText), Color.PaleVioletRed, player);
|
TShock.Utils.SendLogs(GetString("{0} executed: {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdText), Color.PaleVioletRed, player);
|
||||||
else
|
else
|
||||||
TShock.Utils.SendLogs(GetString("{0} executed (args omitted): {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdName), Color.PaleVioletRed, player);
|
TShock.Utils.SendLogs(GetString("{0} executed (args omitted): {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdName), Color.PaleVioletRed, player);
|
||||||
cmd.Run(cmdText, silent, player, args);
|
|
||||||
|
CommandArgs arguments = new CommandArgs(cmdText, silent, player, args);
|
||||||
|
bool handled = PlayerHooks.OnPrePlayerCommand(cmd, ref arguments);
|
||||||
|
if (!handled)
|
||||||
|
cmd.Run(arguments);
|
||||||
|
PlayerHooks.OnPostPlayerCommand(cmd, arguments, handled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1176,7 +1186,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TShock.UserAccounts.SetUserGroup(account, args.Parameters[2]);
|
TShock.UserAccounts.SetUserGroup(args.Player, account, args.Parameters[2]);
|
||||||
TShock.Log.ConsoleInfo(GetString("{0} changed account {1} to group {2}.", args.Player.Name, account.Name, args.Parameters[2]));
|
TShock.Log.ConsoleInfo(GetString("{0} changed account {1} to group {2}.", args.Player.Name, account.Name, args.Parameters[2]));
|
||||||
args.Player.SendSuccessMessage(GetString("Account {0} has been changed to group {1}.", account.Name, args.Parameters[2]));
|
args.Player.SendSuccessMessage(GetString("Account {0} has been changed to group {1}.", account.Name, args.Parameters[2]));
|
||||||
|
|
||||||
|
|
@ -1193,6 +1203,10 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
args.Player.SendErrorMessage(GetString($"User {account.Name} does not exist."));
|
args.Player.SendErrorMessage(GetString($"User {account.Name} does not exist."));
|
||||||
}
|
}
|
||||||
|
catch (UserGroupUpdateLockedException)
|
||||||
|
{
|
||||||
|
args.Player.SendErrorMessage(GetString("Hook blocked the attempt to change the user group."));
|
||||||
|
}
|
||||||
catch (UserAccountManagerException e)
|
catch (UserAccountManagerException e)
|
||||||
{
|
{
|
||||||
args.Player.SendErrorMessage(GetString($"User {account.Name} could not be added. Check console for details."));
|
args.Player.SendErrorMessage(GetString($"User {account.Name} could not be added. Check console for details."));
|
||||||
|
|
@ -2044,6 +2058,7 @@ namespace TShockAPI
|
||||||
private static void OffNoSave(CommandArgs args)
|
private static void OffNoSave(CommandArgs args)
|
||||||
{
|
{
|
||||||
string reason = ((args.Parameters.Count > 0) ? GetString("Server shutting down: ") + String.Join(" ", args.Parameters) : GetString("Server shutting down."));
|
string reason = ((args.Parameters.Count > 0) ? GetString("Server shutting down: ") + String.Join(" ", args.Parameters) : GetString("Server shutting down."));
|
||||||
|
Netplay.SaveOnServerExit = false;
|
||||||
TShock.Utils.StopServer(false, reason);
|
TShock.Utils.StopServer(false, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3070,12 +3085,12 @@ namespace TShockAPI
|
||||||
args.Player.SendErrorMessage(GetString("You do not have permission to teleport all other players."));
|
args.Player.SendErrorMessage(GetString("You do not have permission to teleport all other players."));
|
||||||
return;
|
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))
|
if (player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y))
|
||||||
TShock.Players[i].SendSuccessMessage(GetString("You were teleported to {0}.", args.Player.Name));
|
player.SendSuccessMessage(GetString("You were teleported to {0}.", args.Player.Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args.Player.SendSuccessMessage(GetString("Teleported everyone to yourself."));
|
args.Player.SendSuccessMessage(GetString("Teleported everyone to yourself."));
|
||||||
|
|
@ -4622,21 +4637,22 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (args.Parameters.Count != 1)
|
if (args.Parameters.Count != 1)
|
||||||
{
|
{
|
||||||
args.Player.SendErrorMessage(GetString("Invalid syntax. Proper syntax: {0}wind <speed>.", Specifier));
|
args.Player.SendErrorMessage(GetString("Invalid syntax. Proper syntax: {0}wind <speed in mph>.", Specifier));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speed;
|
float mph;
|
||||||
if (!int.TryParse(args.Parameters[0], out speed) || speed * 100 < 0)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float speed = mph / 50f; // -40 to 40 mph -> -0.8 to 0.8
|
||||||
Main.windSpeedCurrent = speed;
|
Main.windSpeedCurrent = speed;
|
||||||
Main.windSpeedTarget = speed;
|
Main.windSpeedTarget = speed;
|
||||||
TSPlayer.All.SendData(PacketTypes.WorldInfo);
|
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
|
#endregion Time/PvpFun Commands
|
||||||
|
|
@ -5347,7 +5363,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
foreach (TSPlayer ply in TShock.Players)
|
foreach (TSPlayer ply in TShock.Players)
|
||||||
{
|
{
|
||||||
if (ply != null && ply.Active)
|
if (ply != null && ply.Active && ply.FinishedHandshake)
|
||||||
{
|
{
|
||||||
if (displayIdsRequested)
|
if (displayIdsRequested)
|
||||||
if (ply.Account != null)
|
if (ply.Account != null)
|
||||||
|
|
@ -6462,7 +6478,7 @@ namespace TShockAPI
|
||||||
if (target == user)
|
if (target == user)
|
||||||
user.SendSuccessMessage(GetString($"You buffed yourself with {TShock.Utils.GetBuffName(id)} ({TShock.Utils.GetBuffDescription(id)}) for {time} seconds."));
|
user.SendSuccessMessage(GetString($"You buffed yourself with {TShock.Utils.GetBuffName(id)} ({TShock.Utils.GetBuffDescription(id)}) for {time} seconds."));
|
||||||
else
|
else
|
||||||
target.SendSuccessMessage(GetString($"You have buffed {user.Name} with {TShock.Utils.GetBuffName(id)} ({TShock.Utils.GetBuffDescription(id)}) for {time} seconds!"));
|
user.SendSuccessMessage(GetString($"You have buffed {target.Name} with {TShock.Utils.GetBuffName(id)} ({TShock.Utils.GetBuffDescription(id)}) for {time} seconds!"));
|
||||||
if (!args.Silent && target != user)
|
if (!args.Silent && target != user)
|
||||||
target.SendSuccessMessage(GetString($"{user.Name} has buffed you with {TShock.Utils.GetBuffName(id)} ({TShock.Utils.GetBuffDescription(id)}) for {time} seconds!"));
|
target.SendSuccessMessage(GetString($"{user.Name} has buffed you with {TShock.Utils.GetBuffName(id)} ({TShock.Utils.GetBuffDescription(id)}) for {time} seconds!"));
|
||||||
}
|
}
|
||||||
|
|
@ -6740,10 +6756,6 @@ namespace TShockAPI
|
||||||
|
|
||||||
playerToGod.GodMode = !playerToGod.GodMode;
|
playerToGod.GodMode = !playerToGod.GodMode;
|
||||||
|
|
||||||
var godPower = CreativePowerManager.Instance.GetPower<CreativePowers.GodmodePower>();
|
|
||||||
|
|
||||||
godPower.SetEnabledState(playerToGod.Index, playerToGod.GodMode);
|
|
||||||
|
|
||||||
if (playerToGod != args.Player)
|
if (playerToGod != args.Player)
|
||||||
{
|
{
|
||||||
args.Player.SendSuccessMessage(playerToGod.GodMode
|
args.Player.SendSuccessMessage(playerToGod.GodMode
|
||||||
|
|
|
||||||
|
|
@ -320,8 +320,8 @@ namespace TShockAPI.Configuration
|
||||||
[Description("The reason given if banning a mediumcore player on death.")]
|
[Description("The reason given if banning a mediumcore player on death.")]
|
||||||
public string MediumcoreBanReason = GetString("Death results in a ban");
|
public string MediumcoreBanReason = GetString("Death results in a ban");
|
||||||
|
|
||||||
/// <summary>Disbales IP bans by default, if no arguments are passed to the ban command.</summary>
|
/// <summary>Disables IP bans by default, if no arguments are passed to the ban command.</summary>
|
||||||
[Description("Disbales IP bans by default, if no arguments are passed to the ban command.")]
|
[Description("Disables IP bans by default, if no arguments are passed to the ban command.")]
|
||||||
public bool DisableDefaultIPBan;
|
public bool DisableDefaultIPBan;
|
||||||
|
|
||||||
/// <summary>Enable or disable the whitelist based on IP addresses in the whitelist.txt file.</summary>
|
/// <summary>Enable or disable the whitelist based on IP addresses in the whitelist.txt file.</summary>
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ namespace TShockAPI.DB
|
||||||
|
|
||||||
public PlayerData GetPlayerData(TSPlayer player, int acctid)
|
public PlayerData GetPlayerData(TSPlayer player, int acctid)
|
||||||
{
|
{
|
||||||
PlayerData playerData = new PlayerData(player);
|
PlayerData playerData = new PlayerData(false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -189,6 +189,9 @@ namespace TShockAPI.DB
|
||||||
if (!player.IsLoggedIn)
|
if (!player.IsLoggedIn)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (player.State < 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (player.HasPermission(Permissions.bypassssc) && !fromCommand)
|
if (player.HasPermission(Permissions.bypassssc) && !fromCommand)
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleInfo(GetParticularString("{0} is a player name", $"Skipping SSC save (due to tshock.ignore.ssc) for {player.Account.Name}"));
|
TShock.Log.ConsoleInfo(GetParticularString("{0} is a player name", $"Skipping SSC save (due to tshock.ignore.ssc) for {player.Account.Name}"));
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ using MySql.Data.MySqlClient;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using BCrypt.Net;
|
using BCrypt.Net;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using TShockAPI.Hooks;
|
||||||
|
|
||||||
namespace TShockAPI.DB
|
namespace TShockAPI.DB
|
||||||
{
|
{
|
||||||
|
|
@ -166,7 +167,41 @@ namespace TShockAPI.DB
|
||||||
if (null == grp)
|
if (null == grp)
|
||||||
throw new GroupNotExistsException(group);
|
throw new GroupNotExistsException(group);
|
||||||
|
|
||||||
if (_database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", group, account.Name) == 0)
|
if (AccountHooks.OnAccountGroupUpdate(account, ref grp))
|
||||||
|
throw new UserGroupUpdateLockedException(account.Name);
|
||||||
|
|
||||||
|
if (_database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", grp.Name, account.Name) == 0)
|
||||||
|
throw new UserAccountNotExistException(account.Name);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Update player group reference for any logged in player
|
||||||
|
foreach (var player in TShock.Players.Where(p => p != null && p.Account != null && p.Account.Name == account.Name))
|
||||||
|
{
|
||||||
|
player.Group = grp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new UserAccountManagerException(GetString("SetUserGroup SQL returned an error"), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the group for a given username
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="author">Who changes the group</param>
|
||||||
|
/// <param name="account">The user account</param>
|
||||||
|
/// <param name="group">The user account group to be set</param>
|
||||||
|
public void SetUserGroup(TSPlayer author, UserAccount account, string group)
|
||||||
|
{
|
||||||
|
Group grp = TShock.Groups.GetGroupByName(group);
|
||||||
|
if (null == grp)
|
||||||
|
throw new GroupNotExistsException(group);
|
||||||
|
|
||||||
|
if (AccountHooks.OnAccountGroupUpdate(account, author, ref grp))
|
||||||
|
throw new UserGroupUpdateLockedException(account.Name);
|
||||||
|
|
||||||
|
if (_database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", grp.Name, account.Name) == 0)
|
||||||
throw new UserAccountNotExistException(account.Name);
|
throw new UserAccountNotExistException(account.Name);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -619,7 +654,7 @@ namespace TShockAPI.DB
|
||||||
public class UserAccountNotExistException : UserAccountManagerException
|
public class UserAccountNotExistException : UserAccountManagerException
|
||||||
{
|
{
|
||||||
/// <summary>Creates a new UserAccountNotExistException object, with the user account name in the message.</summary>
|
/// <summary>Creates a new UserAccountNotExistException object, with the user account name in the message.</summary>
|
||||||
/// <param name="name">The user account name to be pasesd in the message.</param>
|
/// <param name="name">The user account name to be passed in the message.</param>
|
||||||
/// <returns>A new UserAccountNotExistException object with a message containing the user account name that does not exist.</returns>
|
/// <returns>A new UserAccountNotExistException object with a message containing the user account name that does not exist.</returns>
|
||||||
public UserAccountNotExistException(string name)
|
public UserAccountNotExistException(string name)
|
||||||
: base(GetString($"User account {name} does not exist"))
|
: base(GetString($"User account {name} does not exist"))
|
||||||
|
|
@ -627,6 +662,20 @@ namespace TShockAPI.DB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>The UserGroupUpdateLockedException used when the user group update failed and the request failed as a result.</summary>.
|
||||||
|
[Serializable]
|
||||||
|
public class UserGroupUpdateLockedException : UserAccountManagerException
|
||||||
|
{
|
||||||
|
/// <summary>Creates a new UserGroupUpdateLockedException object.</summary>
|
||||||
|
/// <param name="name">The name of the user who failed to change the group.</param>
|
||||||
|
/// <returns>New UserGroupUpdateLockedException object with a message containing the name of the user account that failed to change the group.</returns>
|
||||||
|
public UserGroupUpdateLockedException(string name) :
|
||||||
|
base(GetString($"Unable to update group of user {name}."))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>A GroupNotExistsException, used when a group does not exist.</summary>
|
/// <summary>A GroupNotExistsException, used when a group does not exist.</summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class GroupNotExistsException : UserAccountManagerException
|
public class GroupNotExistsException : UserAccountManagerException
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ namespace TShockAPI
|
||||||
{ PacketTypes.TileSendSquare, HandleSendTileRect },
|
{ PacketTypes.TileSendSquare, HandleSendTileRect },
|
||||||
{ PacketTypes.ItemDrop, HandleItemDrop },
|
{ PacketTypes.ItemDrop, HandleItemDrop },
|
||||||
{ PacketTypes.ItemOwner, HandleItemOwner },
|
{ PacketTypes.ItemOwner, HandleItemOwner },
|
||||||
|
{ PacketTypes.NpcItemStrike, HandleNpcItemStrike },
|
||||||
{ PacketTypes.ProjectileNew, HandleProjectileNew },
|
{ PacketTypes.ProjectileNew, HandleProjectileNew },
|
||||||
{ PacketTypes.NpcStrike, HandleNpcStrike },
|
{ PacketTypes.NpcStrike, HandleNpcStrike },
|
||||||
{ PacketTypes.ProjectileDestroy, HandleProjectileKill },
|
{ PacketTypes.ProjectileDestroy, HandleProjectileKill },
|
||||||
|
|
@ -2248,6 +2249,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
var args = new SyncTilePickingEventArgs
|
var args = new SyncTilePickingEventArgs
|
||||||
{
|
{
|
||||||
|
Player = player,
|
||||||
PlayerIndex = playerIndex,
|
PlayerIndex = playerIndex,
|
||||||
TileX = tileX,
|
TileX = tileX,
|
||||||
TileY = tileY,
|
TileY = tileY,
|
||||||
|
|
@ -2618,9 +2620,9 @@ namespace TShockAPI
|
||||||
private static bool HandleConnecting(GetDataHandlerArgs args)
|
private static bool HandleConnecting(GetDataHandlerArgs args)
|
||||||
{
|
{
|
||||||
var account = TShock.UserAccounts.GetUserAccountByName(args.Player.Name);//
|
var account = TShock.UserAccounts.GetUserAccountByName(args.Player.Name);//
|
||||||
args.Player.DataWhenJoined = new PlayerData(args.Player);
|
args.Player.DataWhenJoined = new PlayerData(false);
|
||||||
args.Player.DataWhenJoined.CopyCharacter(args.Player);
|
args.Player.DataWhenJoined.CopyCharacter(args.Player);
|
||||||
args.Player.PlayerData = new PlayerData(args.Player);
|
args.Player.PlayerData = new PlayerData(false);
|
||||||
args.Player.PlayerData.CopyCharacter(args.Player);
|
args.Player.PlayerData.CopyCharacter(args.Player);
|
||||||
|
|
||||||
if (account != null && !TShock.Config.Settings.DisableUUIDLogin)
|
if (account != null && !TShock.Config.Settings.DisableUUIDLogin)
|
||||||
|
|
@ -2718,49 +2720,71 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
byte player = args.Data.ReadInt8();
|
byte player = args.Data.ReadInt8();
|
||||||
short spawnx = args.Data.ReadInt16();
|
short spawnX = args.Data.ReadInt16();
|
||||||
short spawny = args.Data.ReadInt16();
|
short spawnY = args.Data.ReadInt16();
|
||||||
int respawnTimer = args.Data.ReadInt32();
|
int respawnTimer = args.Data.ReadInt32();
|
||||||
short numberOfDeathsPVE = args.Data.ReadInt16();
|
short numberOfDeathsPVE = args.Data.ReadInt16();
|
||||||
short numberOfDeathsPVP = args.Data.ReadInt16();
|
short numberOfDeathsPVP = args.Data.ReadInt16();
|
||||||
PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte();
|
PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte();
|
||||||
|
|
||||||
if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, numberOfDeathsPVE, numberOfDeathsPVP, context))
|
args.Player.FinishedHandshake = true;
|
||||||
|
|
||||||
|
if (OnPlayerSpawn(args.Player, args.Data, player, spawnX, spawnY, respawnTimer, numberOfDeathsPVE, numberOfDeathsPVP, context))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ((Main.ServerSideCharacter) && (spawnx == -1 && spawny == -1)) //this means they want to spawn to vanilla spawn
|
args.Player.Dead = respawnTimer > 0;
|
||||||
{
|
|
||||||
args.Player.sX = Main.spawnTileX;
|
|
||||||
args.Player.sY = Main.spawnTileY;
|
|
||||||
args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48);
|
|
||||||
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleSpawn force teleport 'vanilla spawn' {0}", args.Player.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY)))
|
if (Main.ServerSideCharacter)
|
||||||
{
|
{
|
||||||
args.Player.sX = args.TPlayer.SpawnX;
|
// As long as the player has not changed his spawnpoint since initial connection,
|
||||||
args.Player.sY = args.TPlayer.SpawnY;
|
// we should not use the client's spawnpoint value. This is because the spawnpoint
|
||||||
|
// value is not saved on the client when SSC is enabled. Hence, we have to assert
|
||||||
|
// the server-saved spawnpoint value until we can detect that the player has changed
|
||||||
|
// his spawn. Once we detect the spawnpoint changed, the client's spawnpoint value
|
||||||
|
// becomes the correct one to use.
|
||||||
|
//
|
||||||
|
// Note that spawnpoint changes (right-clicking beds) are not broadcasted to the
|
||||||
|
// server. Hence, the only way to detect spawnpoint changes is from the
|
||||||
|
// PlayerSpawn packet.
|
||||||
|
|
||||||
if (((Main.tile[args.Player.sX, args.Player.sY - 1].active() && Main.tile[args.Player.sX, args.Player.sY - 1].type == TileID.Beds)) && (WorldGen.StartRoomCheck(args.Player.sX, args.Player.sY - 1)))
|
// handle initial connection
|
||||||
|
if (args.Player.State == 3)
|
||||||
{
|
{
|
||||||
args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48);
|
// server saved spawnpoint value
|
||||||
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleSpawn force teleport phase 1 {0}", args.Player.Name));
|
args.Player.initialSpawn = true;
|
||||||
}
|
args.Player.initialServerSpawnX = args.TPlayer.SpawnX;
|
||||||
}
|
args.Player.initialServerSpawnY = args.TPlayer.SpawnY;
|
||||||
|
|
||||||
else if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0))
|
// initial client spawn point, do not use this to spawn the player
|
||||||
{
|
// we only use it to detect if the spawnpoint has changed during this session
|
||||||
if (((Main.tile[args.Player.sX, args.Player.sY - 1].active() && Main.tile[args.Player.sX, args.Player.sY - 1].type == TileID.Beds)) && (WorldGen.StartRoomCheck(args.Player.sX, args.Player.sY - 1)))
|
args.Player.initialClientSpawnX = spawnX;
|
||||||
|
args.Player.initialClientSpawnY = spawnY;
|
||||||
|
|
||||||
|
// we first let the game handle completing the connection (state 3 => 10),
|
||||||
|
// then we will spawn the player at the saved spawnpoint in the next second,
|
||||||
|
// by reasserting the correct spawnpoint value
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// once we detect the client has changed his spawnpoint in the current session,
|
||||||
|
// the client spawnpoint value will be correct for the rest of the session
|
||||||
|
if (args.Player.spawnSynced || args.Player.initialClientSpawnX != spawnX || args.Player.initialClientSpawnY != spawnY)
|
||||||
{
|
{
|
||||||
args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48);
|
// Player has changed his spawnpoint, client and server TPlayer.Spawn{X,Y} is now synced
|
||||||
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleSpawn force teleport phase 2 {0}", args.Player.Name));
|
args.Player.spawnSynced = true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (respawnTimer > 0)
|
// the player has not changed his spawnpoint yet, so we assert the server-saved spawnpoint
|
||||||
args.Player.Dead = true;
|
// by teleporting the player instead of letting the game use the client's incorrect spawnpoint.
|
||||||
else
|
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleSpawn force ssc teleport for {0} at ({1},{2})", args.Player.Name, args.TPlayer.SpawnX, args.TPlayer.SpawnY));
|
||||||
args.Player.Dead = false;
|
args.Player.TeleportSpawnpoint();
|
||||||
|
|
||||||
|
args.TPlayer.respawnTimer = respawnTimer;
|
||||||
|
args.TPlayer.numberOfDeathsPVE = numberOfDeathsPVE;
|
||||||
|
args.TPlayer.numberOfDeathsPVP = numberOfDeathsPVP;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2941,6 +2965,13 @@ namespace TShockAPI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool HandleNpcItemStrike(GetDataHandlerArgs args)
|
||||||
|
{
|
||||||
|
// Never sent by vanilla client, ignore this
|
||||||
|
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleNpcItemStrike surprise packet! Someone tell the TShock team! {0}", args.Player.Name));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool HandleProjectileNew(GetDataHandlerArgs args)
|
private static bool HandleProjectileNew(GetDataHandlerArgs args)
|
||||||
{
|
{
|
||||||
short ident = args.Data.ReadInt16();
|
short ident = args.Data.ReadInt16();
|
||||||
|
|
@ -4444,6 +4475,11 @@ namespace TShockAPI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't modify the player data if it isn't there.
|
||||||
|
// This is the case whilst the player is connecting, as we receive the SyncLoadout packet before the ContinueConnecting2 packet.
|
||||||
|
if (args.Player.PlayerData == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
// The client does not sync slot changes when changing loadouts, it only tells the server the loadout index changed,
|
// The client does not sync slot changes when changing loadouts, it only tells the server the loadout index changed,
|
||||||
// and the server will replicate the changes the client did. This means that PlayerData.StoreSlot is never called, so we need to
|
// and the server will replicate the changes the client did. This means that PlayerData.StoreSlot is never called, so we need to
|
||||||
// swap around the PlayerData items ourself.
|
// swap around the PlayerData items ourself.
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -52,17 +54,17 @@ namespace TShockAPI
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The group that this group inherits permissions from.
|
/// The group that this group inherits permissions from.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Group Parent { get; set; }
|
public virtual Group Parent { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The chat prefix for this group.
|
/// The chat prefix for this group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Prefix { get; set; }
|
public virtual string Prefix { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The chat suffix for this group.
|
/// The chat suffix for this group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Suffix { get; set; }
|
public virtual string Suffix { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the parent, not particularly sure why this is here.
|
/// The name of the parent, not particularly sure why this is here.
|
||||||
|
|
@ -164,6 +166,20 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte B = 255;
|
public byte B = 255;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simplifies work with the <see cref="R"/>, <see cref="G"/>, <see cref="B"/> properties.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Color Color
|
||||||
|
{
|
||||||
|
get => new Color(R, G, B);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
R = value.R;
|
||||||
|
G = value.G;
|
||||||
|
B = value.B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default group attributed to unregistered users.
|
/// The default group attributed to unregistered users.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -242,7 +258,7 @@ namespace TShockAPI
|
||||||
/// Adds a permission to the list of negated permissions.
|
/// Adds a permission to the list of negated permissions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="permission">The permission to negate.</param>
|
/// <param name="permission">The permission to negate.</param>
|
||||||
public void NegatePermission(string permission)
|
public virtual void NegatePermission(string permission)
|
||||||
{
|
{
|
||||||
// Avoid duplicates
|
// Avoid duplicates
|
||||||
if (!negatedpermissions.Contains(permission))
|
if (!negatedpermissions.Contains(permission))
|
||||||
|
|
@ -256,7 +272,7 @@ namespace TShockAPI
|
||||||
/// Adds a permission to the list of permissions.
|
/// Adds a permission to the list of permissions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="permission">The permission to add.</param>
|
/// <param name="permission">The permission to add.</param>
|
||||||
public void AddPermission(string permission)
|
public virtual void AddPermission(string permission)
|
||||||
{
|
{
|
||||||
if (permission.StartsWith("!"))
|
if (permission.StartsWith("!"))
|
||||||
{
|
{
|
||||||
|
|
@ -276,7 +292,7 @@ namespace TShockAPI
|
||||||
/// will parse "!permission" and add it to the negated permissions.
|
/// will parse "!permission" and add it to the negated permissions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="permission">The new list of permissions to associate with the group.</param>
|
/// <param name="permission">The new list of permissions to associate with the group.</param>
|
||||||
public void SetPermission(List<string> permission)
|
public virtual void SetPermission(List<string> permission)
|
||||||
{
|
{
|
||||||
permissions.Clear();
|
permissions.Clear();
|
||||||
negatedpermissions.Clear();
|
negatedpermissions.Clear();
|
||||||
|
|
@ -288,7 +304,7 @@ namespace TShockAPI
|
||||||
/// where "!permission" will remove a negated permission.
|
/// where "!permission" will remove a negated permission.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="permission"></param>
|
/// <param name="permission"></param>
|
||||||
public void RemovePermission(string permission)
|
public virtual void RemovePermission(string permission)
|
||||||
{
|
{
|
||||||
if (permission.StartsWith("!"))
|
if (permission.StartsWith("!"))
|
||||||
{
|
{
|
||||||
|
|
@ -302,7 +318,7 @@ namespace TShockAPI
|
||||||
/// Assigns all fields of this instance to another.
|
/// Assigns all fields of this instance to another.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="otherGroup">The other instance.</param>
|
/// <param name="otherGroup">The other instance.</param>
|
||||||
public void AssignTo(Group otherGroup)
|
public virtual void AssignTo(Group otherGroup)
|
||||||
{
|
{
|
||||||
otherGroup.Name = Name;
|
otherGroup.Name = Name;
|
||||||
otherGroup.Parent = Parent;
|
otherGroup.Parent = Parent;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
using TShockAPI.DB;
|
using TShockAPI.DB;
|
||||||
namespace TShockAPI.Hooks
|
namespace TShockAPI.Hooks
|
||||||
{
|
{
|
||||||
|
|
@ -39,6 +40,31 @@ namespace TShockAPI.Hooks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class AccountGroupUpdateEventArgs : HandledEventArgs
|
||||||
|
{
|
||||||
|
public string AccountName { get; private set; }
|
||||||
|
public Group Group { get; set; }
|
||||||
|
|
||||||
|
public AccountGroupUpdateEventArgs(string accountName, Group group)
|
||||||
|
{
|
||||||
|
this.AccountName = accountName;
|
||||||
|
this.Group = group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccountGroupUpdateByPlayerEventArgs : AccountGroupUpdateEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The player who updated the user's group
|
||||||
|
/// </summary>
|
||||||
|
public TSPlayer Player { get; private set; }
|
||||||
|
|
||||||
|
public AccountGroupUpdateByPlayerEventArgs(TSPlayer player, string accountName, Group group) : base(accountName, group)
|
||||||
|
{
|
||||||
|
this.Player = player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class AccountHooks
|
public class AccountHooks
|
||||||
{
|
{
|
||||||
public delegate void AccountCreateD(AccountCreateEventArgs e);
|
public delegate void AccountCreateD(AccountCreateEventArgs e);
|
||||||
|
|
@ -62,5 +88,25 @@ namespace TShockAPI.Hooks
|
||||||
|
|
||||||
AccountDelete(new AccountDeleteEventArgs(u));
|
AccountDelete(new AccountDeleteEventArgs(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public delegate void AccountGroupUpdateD(AccountGroupUpdateEventArgs e);
|
||||||
|
public static event AccountGroupUpdateD AccountGroupUpdate;
|
||||||
|
|
||||||
|
public static bool OnAccountGroupUpdate(UserAccount account, TSPlayer author, ref Group group)
|
||||||
|
{
|
||||||
|
AccountGroupUpdateEventArgs args = new AccountGroupUpdateByPlayerEventArgs(author, account.Name, group);
|
||||||
|
AccountGroupUpdate?.Invoke(args);
|
||||||
|
group = args.Group;
|
||||||
|
|
||||||
|
return args.Handled;
|
||||||
|
}
|
||||||
|
public static bool OnAccountGroupUpdate(UserAccount account, ref Group group)
|
||||||
|
{
|
||||||
|
AccountGroupUpdateEventArgs args = new AccountGroupUpdateEventArgs(account.Name, group);
|
||||||
|
AccountGroupUpdate?.Invoke(args);
|
||||||
|
group = args.Group;
|
||||||
|
|
||||||
|
return args.Handled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using TShockAPI.DB;
|
using TShockAPI.DB;
|
||||||
|
|
@ -119,6 +120,49 @@ namespace TShockAPI.Hooks
|
||||||
public string CommandPrefix { get; set; }
|
public string CommandPrefix { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventArgs used for the <see cref="PlayerHooks.PrePlayerCommand"/> event.
|
||||||
|
/// </summary>
|
||||||
|
public class PrePlayerCommandEventArgs : HandledEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The command entered by the player.
|
||||||
|
/// </summary>
|
||||||
|
public Command Command { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Command arguments.
|
||||||
|
/// </summary>
|
||||||
|
public CommandArgs Arguments { get; set; }
|
||||||
|
|
||||||
|
public PrePlayerCommandEventArgs(Command command, CommandArgs args)
|
||||||
|
{
|
||||||
|
Command = command;
|
||||||
|
Arguments = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventArgs used for the <see cref="PlayerHooks.PostPlayerCommand"/> event.
|
||||||
|
/// </summary>
|
||||||
|
public class PostPlayerCommandEventArgs : HandledEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The command entered by the player.
|
||||||
|
/// </summary>
|
||||||
|
public Command Command { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Command arguments.
|
||||||
|
/// </summary>
|
||||||
|
public CommandArgs Arguments { get; }
|
||||||
|
|
||||||
|
public PostPlayerCommandEventArgs(Command command, CommandArgs arguments, bool handled)
|
||||||
|
{
|
||||||
|
Command = command;
|
||||||
|
Arguments = arguments;
|
||||||
|
Handled = handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// EventArgs used for the <see cref="PlayerHooks.PlayerChat"/> event.
|
/// EventArgs used for the <see cref="PlayerHooks.PlayerChat"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -343,6 +387,26 @@ namespace TShockAPI.Hooks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static event PlayerCommandD PlayerCommand;
|
public static event PlayerCommandD PlayerCommand;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The delegate of the <see cref="PrePlayerCommand"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">The EventArgs for this event.</param>
|
||||||
|
public delegate void PrePlayerCommandD(PrePlayerCommandEventArgs e);
|
||||||
|
/// <summary>
|
||||||
|
/// Fired before a command is run.
|
||||||
|
/// </summary>
|
||||||
|
public static event PrePlayerCommandD PrePlayerCommand;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The delegate of the <see cref="PostPlayerCommand"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">The EventArgs for this event.</param>
|
||||||
|
public delegate void PostPlayerCommandD(PostPlayerCommandEventArgs e);
|
||||||
|
/// <summary>
|
||||||
|
/// Fired after a command is run.
|
||||||
|
/// </summary>
|
||||||
|
public static event PostPlayerCommandD PostPlayerCommand;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The delegate of the <see cref="PlayerChat"/> event.
|
/// The delegate of the <see cref="PlayerChat"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -449,6 +513,40 @@ namespace TShockAPI.Hooks
|
||||||
return playerCommandEventArgs.Handled;
|
return playerCommandEventArgs.Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires the <see cref="PrePlayerCommand"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cmd">Command to be executed</param>
|
||||||
|
/// <param name="arguments">Command arguments</param>
|
||||||
|
/// <returns>True if the event has been handled.</returns>
|
||||||
|
public static bool OnPrePlayerCommand(Command cmd, ref CommandArgs arguments)
|
||||||
|
{
|
||||||
|
if (PrePlayerCommand == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PrePlayerCommandEventArgs args = new PrePlayerCommandEventArgs(cmd, arguments);
|
||||||
|
|
||||||
|
PrePlayerCommand(args);
|
||||||
|
|
||||||
|
arguments = args.Arguments;
|
||||||
|
return args.Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires the <see cref="PostPlayerCommand"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cmd">Executed command.</param>
|
||||||
|
/// <param name="arguments">Command arguments.</param>
|
||||||
|
/// <param name="handled">Is the command executed.</param>
|
||||||
|
public static void OnPostPlayerCommand(Command cmd, CommandArgs arguments, bool handled)
|
||||||
|
{
|
||||||
|
if (PostPlayerCommand == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PostPlayerCommandEventArgs args = new PostPlayerCommandEventArgs(cmd, arguments, handled);
|
||||||
|
PostPlayerCommand(args);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires the <see cref="PlayerPreLogin"/> event.
|
/// Fires the <see cref="PlayerPreLogin"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,12 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LanguageManager.Instance.ActiveCulture == GameCulture.DefaultCulture)
|
||||||
|
{
|
||||||
|
var bf = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static;
|
||||||
|
// LanguageManager.SetLanguage will change this so we need to reset it back to null
|
||||||
|
typeof(CultureInfo).GetField("s_currentThreadUICulture", bf)?.SetValue(null, null);
|
||||||
|
}
|
||||||
return CultureInfo.CurrentUICulture;
|
return CultureInfo.CurrentUICulture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Terraria;
|
using Terraria;
|
||||||
|
using Terraria.Initializers;
|
||||||
using Terraria.Localization;
|
using Terraria.Localization;
|
||||||
|
using Terraria.UI.Chat;
|
||||||
|
|
||||||
namespace TShockAPI.Localization
|
namespace TShockAPI.Localization
|
||||||
{
|
{
|
||||||
|
|
@ -37,6 +39,8 @@ namespace TShockAPI.Localization
|
||||||
|
|
||||||
private static readonly Dictionary<int, string> Buffs = new Dictionary<int, string>();
|
private static readonly Dictionary<int, string> Buffs = new Dictionary<int, string>();
|
||||||
|
|
||||||
|
private static readonly Dictionary<string,string> VanillaCommandsPrefixs = new Dictionary<string, string>();
|
||||||
|
|
||||||
internal static void Initialize()
|
internal static void Initialize()
|
||||||
{
|
{
|
||||||
var culture = Language.ActiveCulture;
|
var culture = Language.ActiveCulture;
|
||||||
|
|
@ -71,6 +75,15 @@ namespace TShockAPI.Localization
|
||||||
var i = (int)field.GetValue(null);
|
var i = (int)field.GetValue(null);
|
||||||
Prefixs.Add(i, Lang.prefix[i].Value);
|
Prefixs.Add(i, Lang.prefix[i].Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatInitializer.Load();
|
||||||
|
foreach (var command in ChatManager.Commands._localizedCommands)
|
||||||
|
{
|
||||||
|
if (VanillaCommandsPrefixs.ContainsKey(command.Value._name))
|
||||||
|
continue;
|
||||||
|
VanillaCommandsPrefixs.Add(command.Value._name,command.Key.Value);
|
||||||
|
}
|
||||||
|
ChatManager.Commands._localizedCommands.Clear();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -136,5 +149,18 @@ namespace TShockAPI.Localization
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get vanilla command prefix in English
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">vanilla command name</param>
|
||||||
|
/// <returns>vanilla command prefix in English</returns>
|
||||||
|
public static string GetCommandPrefixByName(string name)
|
||||||
|
{
|
||||||
|
string commandText;
|
||||||
|
if (VanillaCommandsPrefixs.TryGetValue(name, out commandText))
|
||||||
|
return commandText;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -155,13 +155,39 @@ namespace TShockAPI
|
||||||
/// <param name="netId">The net ID.</param>
|
/// <param name="netId">The net ID.</param>
|
||||||
/// <param name="stack">The stack.</param>
|
/// <param name="stack">The stack.</param>
|
||||||
/// <param name="prefixId">The prefix ID.</param>
|
/// <param name="prefixId">The prefix ID.</param>
|
||||||
public NetItem(int netId, int stack, byte prefixId)
|
public NetItem(int netId, int stack = 1, byte prefixId = 0)
|
||||||
{
|
{
|
||||||
_netId = netId;
|
_netId = netId;
|
||||||
_stack = stack;
|
_stack = stack;
|
||||||
_prefixId = prefixId;
|
_prefixId = prefixId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="NetItem"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Item in the game.</param>
|
||||||
|
public NetItem(Item item)
|
||||||
|
{
|
||||||
|
_netId = item.netID;
|
||||||
|
_stack = item.stack;
|
||||||
|
_prefixId = item.prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates <see cref="Terraria.Item"/> based on data from this structure.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A copy of the item.</returns>
|
||||||
|
public Item ToItem()
|
||||||
|
{
|
||||||
|
Item item = new Item();
|
||||||
|
|
||||||
|
item.netDefaults(_netId);
|
||||||
|
item.stack = _stack;
|
||||||
|
item.prefix = _prefixId;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts the <see cref="NetItem"/> to a string.
|
/// Converts the <see cref="NetItem"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -529,18 +529,9 @@ namespace TShockAPI
|
||||||
field.GetCustomAttributes(false).FirstOrDefault(o => o is DescriptionAttribute) as DescriptionAttribute;
|
field.GetCustomAttributes(false).FirstOrDefault(o => o is DescriptionAttribute) as DescriptionAttribute;
|
||||||
var desc = descattr != null && !string.IsNullOrWhiteSpace(descattr.Description) ? descattr.Description : GetString("No description available.");
|
var desc = descattr != null && !string.IsNullOrWhiteSpace(descattr.Description) ? descattr.Description : GetString("No description available.");
|
||||||
|
|
||||||
var commands = GetCommands(name);
|
var strs = GetCommands(name).Select(c => c.Names.Count > 1
|
||||||
foreach (var c in commands)
|
? $"/{c.Name} (/{string.Join(" /", c.Names.Skip(1))})"
|
||||||
{
|
: $"/{c.Name}");
|
||||||
for (var i = 0; i < c.Names.Count; i++)
|
|
||||||
{
|
|
||||||
c.Names[i] = "/" + c.Names[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var strs =
|
|
||||||
commands.Select(
|
|
||||||
c =>
|
|
||||||
c.Name + (c.Names.Count > 1 ? " ({0})".SFormat(string.Join(" ", c.Names.ToArray(), 1, c.Names.Count - 1)) : ""));
|
|
||||||
|
|
||||||
sb.AppendLine($"## {name}");
|
sb.AppendLine($"## {name}");
|
||||||
sb.AppendLine($"{desc}");
|
sb.AppendLine($"{desc}");
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ using Terraria.Localization;
|
||||||
using Terraria.GameContent.NetModules;
|
using Terraria.GameContent.NetModules;
|
||||||
using Terraria.Net;
|
using Terraria.Net;
|
||||||
using Terraria.ID;
|
using Terraria.ID;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
|
|
@ -63,18 +64,27 @@ namespace TShockAPI
|
||||||
public int unlockedSuperCart;
|
public int unlockedSuperCart;
|
||||||
public int enabledSuperCart;
|
public int enabledSuperCart;
|
||||||
|
|
||||||
public PlayerData(TSPlayer player)
|
/// <summary>
|
||||||
|
/// Sets the default values for the inventory.
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("The player argument is not used.")]
|
||||||
|
public PlayerData(TSPlayer player) : this(true) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the default values for the inventory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="includingStarterInventory">Is it necessary to load items from TShock's config</param>
|
||||||
|
public PlayerData(bool includingStarterInventory = true)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NetItem.MaxInventory; i++)
|
for (int i = 0; i < NetItem.MaxInventory; i++)
|
||||||
{
|
|
||||||
this.inventory[i] = new NetItem();
|
this.inventory[i] = new NetItem();
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < TShock.ServerSideCharacterConfig.Settings.StartingInventory.Count; i++)
|
if (includingStarterInventory)
|
||||||
{
|
for (int i = 0; i < TShock.ServerSideCharacterConfig.Settings.StartingInventory.Count; i++)
|
||||||
var item = TShock.ServerSideCharacterConfig.Settings.StartingInventory[i];
|
{
|
||||||
StoreSlot(i, item.NetId, item.PrefixId, item.Stack);
|
var item = TShock.ServerSideCharacterConfig.Settings.StartingInventory[i];
|
||||||
}
|
StoreSlot(i, item.NetId, item.PrefixId, item.Stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -86,12 +96,22 @@ namespace TShockAPI
|
||||||
/// <param name="stack"></param>
|
/// <param name="stack"></param>
|
||||||
public void StoreSlot(int slot, int netID, byte prefix, int stack)
|
public void StoreSlot(int slot, int netID, byte prefix, int stack)
|
||||||
{
|
{
|
||||||
if (slot > (this.inventory.Length - 1)) //if the slot is out of range then dont save
|
StoreSlot(slot, new NetItem(netID, stack, prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores an item at the specific storage slot
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slot"></param>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
public void StoreSlot(int slot, NetItem item)
|
||||||
|
{
|
||||||
|
if (slot > (this.inventory.Length - 1) || slot < 0) //if the slot is out of range then dont save
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inventory[slot] = new NetItem(netID, stack, prefix);
|
this.inventory[slot] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -104,16 +124,8 @@ namespace TShockAPI
|
||||||
this.maxHealth = player.TPlayer.statLifeMax;
|
this.maxHealth = player.TPlayer.statLifeMax;
|
||||||
this.mana = player.TPlayer.statMana;
|
this.mana = player.TPlayer.statMana;
|
||||||
this.maxMana = player.TPlayer.statManaMax;
|
this.maxMana = player.TPlayer.statManaMax;
|
||||||
if (player.sX > 0 && player.sY > 0)
|
this.spawnX = player.TPlayer.SpawnX;
|
||||||
{
|
this.spawnY = player.TPlayer.SpawnY;
|
||||||
this.spawnX = player.sX;
|
|
||||||
this.spawnY = player.sY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.spawnX = player.TPlayer.SpawnX;
|
|
||||||
this.spawnY = player.TPlayer.SpawnY;
|
|
||||||
}
|
|
||||||
extraSlot = player.TPlayer.extraAccessory ? 1 : 0;
|
extraSlot = player.TPlayer.extraAccessory ? 1 : 0;
|
||||||
this.skinVariant = player.TPlayer.skinVariant;
|
this.skinVariant = player.TPlayer.skinVariant;
|
||||||
this.hair = player.TPlayer.hair;
|
this.hair = player.TPlayer.hair;
|
||||||
|
|
@ -266,8 +278,6 @@ namespace TShockAPI
|
||||||
player.TPlayer.statManaMax = this.maxMana;
|
player.TPlayer.statManaMax = this.maxMana;
|
||||||
player.TPlayer.SpawnX = this.spawnX;
|
player.TPlayer.SpawnX = this.spawnX;
|
||||||
player.TPlayer.SpawnY = this.spawnY;
|
player.TPlayer.SpawnY = this.spawnY;
|
||||||
player.sX = this.spawnX;
|
|
||||||
player.sY = this.spawnY;
|
|
||||||
player.TPlayer.hairDye = this.hairDye;
|
player.TPlayer.hairDye = this.hairDye;
|
||||||
player.TPlayer.anglerQuestsFinished = this.questsCompleted;
|
player.TPlayer.anglerQuestsFinished = this.questsCompleted;
|
||||||
player.TPlayer.UsingBiomeTorches = this.usingBiomeTorches == 1;
|
player.TPlayer.UsingBiomeTorches = this.usingBiomeTorches == 1;
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,6 @@ namespace Rests
|
||||||
{
|
{
|
||||||
str = string.Format("{0}({1});", jsonp, str);
|
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.ContentType = new ContentTypeHeader("application/json; charset=utf-8");
|
||||||
e.Response.Add(serverHeader);
|
e.Response.Add(serverHeader);
|
||||||
var bytes = Encoding.UTF8.GetBytes(str);
|
var bytes = Encoding.UTF8.GetBytes(str);
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,7 @@ namespace TShockAPI
|
||||||
{"serverversion", Main.versionNumber},
|
{"serverversion", Main.versionNumber},
|
||||||
{"tshockversion", TShock.VersionNum},
|
{"tshockversion", TShock.VersionNum},
|
||||||
{"port", TShock.Config.Settings.ServerPort},
|
{"port", TShock.Config.Settings.ServerPort},
|
||||||
{"playercount", Main.player.Where(p => null != p && p.active).Count()},
|
{"playercount", TShock.Utils.GetActivePlayerCount()},
|
||||||
{"maxplayers", TShock.Config.Settings.MaxSlots},
|
{"maxplayers", TShock.Config.Settings.MaxSlots},
|
||||||
{"world", (TShock.Config.Settings.UseServerName ? TShock.Config.Settings.ServerName : Main.worldName)},
|
{"world", (TShock.Config.Settings.UseServerName ? TShock.Config.Settings.ServerName : Main.worldName)},
|
||||||
{"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")},
|
{"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")},
|
||||||
|
|
@ -555,7 +555,8 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TShock.UserAccounts.SetUserGroup(account, group);
|
TShock.UserAccounts.SetUserGroup(new TSRestPlayer(args.TokenData.Username, TShock.Groups.GetGroupByName(args.TokenData.UserGroupName)),
|
||||||
|
account, group);
|
||||||
response.Add("group-response", "Group updated successfully");
|
response.Add("group-response", "Group updated successfully");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
@ -944,8 +945,8 @@ namespace TShockAPI
|
||||||
[Token]
|
[Token]
|
||||||
private object PlayerList(RestRequestArgs args)
|
private object PlayerList(RestRequestArgs args)
|
||||||
{
|
{
|
||||||
var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
|
var activeplayers = TShock.Players.Where(p => null != p && p.Active).Select(p => p.Name);
|
||||||
return new RestObject() { { "players", string.Join(", ", activeplayers.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.")]
|
[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.")]
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ using TShockAPI.Hooks;
|
||||||
using TShockAPI.Net;
|
using TShockAPI.Net;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Terraria.GameContent.Creative;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
|
|
@ -176,8 +177,13 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int RPPending = 0;
|
public int RPPending = 0;
|
||||||
|
|
||||||
public int sX = -1;
|
|
||||||
public int sY = -1;
|
public bool initialSpawn = false;
|
||||||
|
public int initialServerSpawnX = -2;
|
||||||
|
public int initialServerSpawnY = -2;
|
||||||
|
public bool spawnSynced = false;
|
||||||
|
public int initialClientSpawnX = -2;
|
||||||
|
public int initialClientSpawnY = -2;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A queue of tiles destroyed by the player for reverting.
|
/// A queue of tiles destroyed by the player for reverting.
|
||||||
|
|
@ -350,6 +356,9 @@ namespace TShockAPI
|
||||||
/// <summary>Determines if the player is disabled for not clearing their trash. A re-login is the only way to reset this.</summary>
|
/// <summary>Determines if the player is disabled for not clearing their trash. A re-login is the only way to reset this.</summary>
|
||||||
public bool IsDisabledPendingTrashRemoval;
|
public bool IsDisabledPendingTrashRemoval;
|
||||||
|
|
||||||
|
/// <summary>Determines if the player has finished the handshake (Sent all necessary packets for connection, such as Request World Data, Spawn Player, etc). A normal client would do all of this no problem.</summary>
|
||||||
|
public bool FinishedHandshake = false;
|
||||||
|
|
||||||
/// <summary>Checks to see if active throttling is happening on events by Bouncer. Rejects repeated events by malicious clients in a short window.</summary>
|
/// <summary>Checks to see if active throttling is happening on events by Bouncer. Rejects repeated events by malicious clients in a short window.</summary>
|
||||||
/// <returns>If the player is currently being throttled by Bouncer, or not.</returns>
|
/// <returns>If the player is currently being throttled by Bouncer, or not.</returns>
|
||||||
public bool IsBouncerThrottled()
|
public bool IsBouncerThrottled()
|
||||||
|
|
@ -935,9 +944,15 @@ namespace TShockAPI
|
||||||
public bool LoginHarassed = false;
|
public bool LoginHarassed = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Player cant die, unless onehit
|
/// Controls the journey godmode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool GodMode = false;
|
public bool GodMode
|
||||||
|
{
|
||||||
|
get =>
|
||||||
|
CreativePowerManager.Instance.GetPower<CreativePowers.GodmodePower>().IsEnabledForPlayer(Index);
|
||||||
|
set =>
|
||||||
|
CreativePowerManager.Instance.GetPower<CreativePowers.GodmodePower>().SetEnabledState(Index, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Players controls are inverted if using SSC
|
/// Players controls are inverted if using SSC
|
||||||
|
|
@ -981,7 +996,7 @@ namespace TShockAPI
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return RealPlayer
|
return RealPlayer
|
||||||
&& (Netplay.Clients[Index] != null && Netplay.Clients[Index].IsActive && !Netplay.Clients[Index].PendingTermination);
|
&& (Client != null && Client.IsActive && !Client.PendingTermination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,8 +1013,8 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int State
|
public int State
|
||||||
{
|
{
|
||||||
get { return Netplay.Clients[Index].State; }
|
get { return Client.State; }
|
||||||
set { Netplay.Clients[Index].State = value; }
|
set { Client.State = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1007,7 +1022,7 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string UUID
|
public string UUID
|
||||||
{
|
{
|
||||||
get { return RealPlayer ? Netplay.Clients[Index].ClientUUID : ""; }
|
get { return RealPlayer ? Client.ClientUUID : ""; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1019,8 +1034,8 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(CacheIP))
|
if (string.IsNullOrEmpty(CacheIP))
|
||||||
return
|
return
|
||||||
CacheIP = RealPlayer ? (Netplay.Clients[Index].Socket.IsConnected()
|
CacheIP = RealPlayer ? (Client.Socket.IsConnected()
|
||||||
? TShock.Utils.GetRealIP(Netplay.Clients[Index].Socket.GetRemoteAddress().ToString())
|
? TShock.Utils.GetRealIP(Client.Socket.GetRemoteAddress().ToString())
|
||||||
: "")
|
: "")
|
||||||
: "127.0.0.1";
|
: "127.0.0.1";
|
||||||
else
|
else
|
||||||
|
|
@ -1103,6 +1118,11 @@ namespace TShockAPI
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Player RemoteClient.
|
||||||
|
/// </summary>
|
||||||
|
public RemoteClient Client => Netplay.Clients[Index];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the Terraria Player object associated with the player.
|
/// Gets the Terraria Player object associated with the player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1135,6 +1155,11 @@ namespace TShockAPI
|
||||||
get { return TPlayer.team; }
|
get { return TPlayer.team; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets PvP player mode.
|
||||||
|
/// </summary>
|
||||||
|
public bool Hostile => TPlayer.hostile;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the player's X coordinate.
|
/// Gets the player's X coordinate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1267,7 +1292,7 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerData = new PlayerData(this);
|
PlayerData = new PlayerData();
|
||||||
Group = TShock.Groups.GetGroupByName(TShock.Config.Settings.DefaultGuestGroupName);
|
Group = TShock.Groups.GetGroupByName(TShock.Config.Settings.DefaultGuestGroupName);
|
||||||
tempGroup = null;
|
tempGroup = null;
|
||||||
if (tempGroupTimer != null)
|
if (tempGroupTimer != null)
|
||||||
|
|
@ -1363,6 +1388,25 @@ namespace TShockAPI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Teleports the player to their spawnpoint.
|
||||||
|
/// Teleports to main spawnpoint if their bed is not active.
|
||||||
|
/// Supports SSC.
|
||||||
|
/// </summary>
|
||||||
|
public bool TeleportSpawnpoint()
|
||||||
|
{
|
||||||
|
// NOTE: it is vanilla behaviour to not permanently override the spawnpoint if the bed spawn is broken/invalid
|
||||||
|
int x = TPlayer.SpawnX;
|
||||||
|
int y = TPlayer.SpawnY;
|
||||||
|
if ((x == -1 && y == -1) ||
|
||||||
|
!Main.tile[x, y - 1].active() || Main.tile[x, y - 1].type != TileID.Beds || !WorldGen.StartRoomCheck(x, y - 1))
|
||||||
|
{
|
||||||
|
x = Main.spawnTileX;
|
||||||
|
y = Main.spawnTileY;
|
||||||
|
}
|
||||||
|
return Teleport(x * 16, y * 16 - 48);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Heals the player.
|
/// Heals the player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1377,14 +1421,7 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Spawn(PlayerSpawnContext context, int? respawnTimer = null)
|
public void Spawn(PlayerSpawnContext context, int? respawnTimer = null)
|
||||||
{
|
{
|
||||||
if (this.sX > 0 && this.sY > 0)
|
Spawn(TPlayer.SpawnX, TPlayer.SpawnY, context, respawnTimer);
|
||||||
{
|
|
||||||
Spawn(this.sX, this.sY, context, respawnTimer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Spawn(TPlayer.SpawnX, TPlayer.SpawnY, context, respawnTimer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1487,6 +1524,41 @@ namespace TShockAPI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the values of the <see cref="RemoteClient.TileSections"/> array.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rectangle">The area of the sections you want to set a value to.
|
||||||
|
/// The minimum size should be set to 200x150. If null, then the entire map is specified.</param>
|
||||||
|
/// <param name="isLoaded">Is the section loaded.</param>
|
||||||
|
// The server does not send the player the whole world, it sends it in sections. To do this, it sets up visible and invisible sections.
|
||||||
|
// If the player was not in any section(Client.TileSections[x, y] == false) then the server will send the missing section of the world.
|
||||||
|
// This method allows you to simulate what the player has or has not seen these sections.
|
||||||
|
// For example, we can put some number of earths blocks in some vast area, for example, for the whole world, but the player will not see the changes, because some section is already loaded for him. At this point this method can come into effect! With it we will be able to select some zone and make it both visible and invisible to the player.
|
||||||
|
// The server will assume that the zone is not loaded on the player, and will resend the data, but with earth blocks.
|
||||||
|
public void UpdateSection(Rectangle? rectangle = null, bool isLoaded = false)
|
||||||
|
{
|
||||||
|
if (rectangle.HasValue)
|
||||||
|
{
|
||||||
|
for (int i = Netplay.GetSectionX(rectangle.Value.X); i < Netplay.GetSectionX(rectangle.Value.X + rectangle.Value.Width) && i < Main.maxSectionsX; i++)
|
||||||
|
{
|
||||||
|
for (int j = Netplay.GetSectionY(rectangle.Value.Y); j < Netplay.GetSectionY(rectangle.Value.Y + rectangle.Value.Height) && j < Main.maxSectionsY; j++)
|
||||||
|
{
|
||||||
|
Client.TileSections[i, j] = isLoaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Main.maxSectionsX; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < Main.maxSectionsY; j++)
|
||||||
|
{
|
||||||
|
Client.TileSections[i, j] = isLoaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gives an item to the player. Includes banned item spawn prevention to check if the player can spawn the item.
|
/// Gives an item to the player. Includes banned item spawn prevention to check if the player can spawn the item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1519,6 +1591,15 @@ namespace TShockAPI
|
||||||
GiveItemByDrop(type, stack, prefix);
|
GiveItemByDrop(type, stack, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gives an item to the player.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Item with data to be given to the player.</param>
|
||||||
|
public virtual void GiveItem(NetItem item)
|
||||||
|
{
|
||||||
|
GiveItem(item.NetId, item.Stack, item.PrefixId);
|
||||||
|
}
|
||||||
|
|
||||||
private Item EmptySentinelItem = new Item();
|
private Item EmptySentinelItem = new Item();
|
||||||
|
|
||||||
private bool Depleted(Item item)
|
private bool Depleted(Item item)
|
||||||
|
|
@ -1815,7 +1896,17 @@ namespace TShockAPI
|
||||||
/// <param name="damage">The amount of damage the player will take.</param>
|
/// <param name="damage">The amount of damage the player will take.</param>
|
||||||
public virtual void DamagePlayer(int damage)
|
public virtual void DamagePlayer(int damage)
|
||||||
{
|
{
|
||||||
NetMessage.SendPlayerHurt(Index, PlayerDeathReason.LegacyDefault(), damage, (new Random()).Next(-1, 1), false, false, 0, -1, -1);
|
DamagePlayer(damage, PlayerDeathReason.LegacyDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wounds the player with the given damage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="damage">The amount of damage the player will take.</param>
|
||||||
|
/// <param name="reason">The reason for causing damage to player.</param>
|
||||||
|
public virtual void DamagePlayer(int damage, PlayerDeathReason reason)
|
||||||
|
{
|
||||||
|
NetMessage.SendPlayerHurt(Index, reason, damage, (new Random()).Next(-1, 1), false, false, 0, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1823,7 +1914,16 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void KillPlayer()
|
public virtual void KillPlayer()
|
||||||
{
|
{
|
||||||
NetMessage.SendPlayerDeath(Index, PlayerDeathReason.LegacyDefault(), 99999, (new Random()).Next(-1, 1), false, -1, -1);
|
KillPlayer(PlayerDeathReason.LegacyDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kills the player.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reason">Reason for killing a player.</param>
|
||||||
|
public virtual void KillPlayer(PlayerDeathReason reason)
|
||||||
|
{
|
||||||
|
NetMessage.SendPlayerDeath(Index, reason, 99999, (new Random()).Next(-1, 1), false, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1832,6 +1932,8 @@ namespace TShockAPI
|
||||||
/// <param name="team">The team color index.</param>
|
/// <param name="team">The team color index.</param>
|
||||||
public virtual void SetTeam(int team)
|
public virtual void SetTeam(int team)
|
||||||
{
|
{
|
||||||
|
if (team < 0 || team >= Main.teamColor.Length)
|
||||||
|
throw new ArgumentException("The player's team is not in the range of available.");
|
||||||
Main.player[Index].team = team;
|
Main.player[Index].team = team;
|
||||||
NetMessage.SendData((int)PacketTypes.PlayerTeam, -1, -1, NetworkText.Empty, Index);
|
NetMessage.SendData((int)PacketTypes.PlayerTeam, -1, -1, NetworkText.Empty, Index);
|
||||||
}
|
}
|
||||||
|
|
@ -1840,6 +1942,7 @@ namespace TShockAPI
|
||||||
/// Sets the player's pvp.
|
/// Sets the player's pvp.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mode">The state of the pvp mode.</param>
|
/// <param name="mode">The state of the pvp mode.</param>
|
||||||
|
/// <param name="withMsg">Whether a chat message about the change should be sent.</param>
|
||||||
public virtual void SetPvP(bool mode, bool withMsg = false)
|
public virtual void SetPvP(bool mode, bool withMsg = false)
|
||||||
{
|
{
|
||||||
Main.player[Index].hostile = mode;
|
Main.player[Index].hostile = mode;
|
||||||
|
|
@ -2064,7 +2167,7 @@ namespace TShockAPI
|
||||||
if (!RealPlayer || !ConnectionAlive)
|
if (!RealPlayer || !ConnectionAlive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Netplay.Clients[Index].Socket.AsyncSend(data, 0, data.Length, Netplay.Clients[Index].ServerWriteCallBack);
|
Client.Socket.AsyncSend(data, 0, data.Length, Client.ServerWriteCallBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ namespace TShockAPI
|
||||||
/// <summary>VersionNum - The version number the TerrariaAPI will return back to the API. We just use the Assembly info.</summary>
|
/// <summary>VersionNum - The version number the TerrariaAPI will return back to the API. We just use the Assembly info.</summary>
|
||||||
public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version;
|
public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
/// <summary>VersionCodename - The version codename is displayed when the server starts. Inspired by software codenames conventions.</summary>
|
/// <summary>VersionCodename - The version codename is displayed when the server starts. Inspired by software codenames conventions.</summary>
|
||||||
public static readonly string VersionCodename = "Thank you, everyone, for your support of TShock all these years! <3";
|
public static readonly string VersionCodename = "East";
|
||||||
|
|
||||||
/// <summary>SavePath - This is the path TShock saves its data in. This path is relative to the TerrariaServer.exe (not in ServerPlugins).</summary>
|
/// <summary>SavePath - This is the path TShock saves its data in. This path is relative to the TerrariaServer.exe (not in ServerPlugins).</summary>
|
||||||
public static string SavePath = "tshock";
|
public static string SavePath = "tshock";
|
||||||
|
|
@ -428,6 +428,8 @@ namespace TShockAPI
|
||||||
Hooks.AccountHooks.AccountDelete += OnAccountDelete;
|
Hooks.AccountHooks.AccountDelete += OnAccountDelete;
|
||||||
Hooks.AccountHooks.AccountCreate += OnAccountCreate;
|
Hooks.AccountHooks.AccountCreate += OnAccountCreate;
|
||||||
|
|
||||||
|
On.Terraria.RemoteClient.Reset += RemoteClient_Reset;
|
||||||
|
|
||||||
GetDataHandlers.InitGetDataHandler();
|
GetDataHandlers.InitGetDataHandler();
|
||||||
Commands.InitCommands();
|
Commands.InitCommands();
|
||||||
|
|
||||||
|
|
@ -496,6 +498,12 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RemoteClient_Reset(On.Terraria.RemoteClient.orig_Reset orig, RemoteClient client)
|
||||||
|
{
|
||||||
|
client.ClientUUID = null;
|
||||||
|
orig(client);
|
||||||
|
}
|
||||||
|
|
||||||
private static void OnAchievementInitializerLoad(ILContext il)
|
private static void OnAchievementInitializerLoad(ILContext il)
|
||||||
{
|
{
|
||||||
// Modify AchievementInitializer.Load to remove the Main.netMode == 2 check (occupies the first 4 IL instructions)
|
// Modify AchievementInitializer.Load to remove the Main.netMode == 2 check (occupies the first 4 IL instructions)
|
||||||
|
|
@ -676,17 +684,13 @@ namespace TShockAPI
|
||||||
|
|
||||||
if (args.Chest != null)
|
if (args.Chest != null)
|
||||||
{
|
{
|
||||||
|
// After checking for protected regions, no further range checking is necessarily because the client packet only specifies the
|
||||||
|
// inventory slot to quick stack. The vanilla Terraria server itself determines what chests are close enough to the player.
|
||||||
if (Config.Settings.RegionProtectChests && !Regions.CanBuild((int)args.WorldPosition.X, (int)args.WorldPosition.Y, tsplr))
|
if (Config.Settings.RegionProtectChests && !Regions.CanBuild((int)args.WorldPosition.X, (int)args.WorldPosition.Y, tsplr))
|
||||||
{
|
{
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tsplr.IsInRange(args.Chest.x, args.Chest.y))
|
|
||||||
{
|
|
||||||
args.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1178,16 +1182,16 @@ namespace TShockAPI
|
||||||
if (player.RecentFuse > 0)
|
if (player.RecentFuse > 0)
|
||||||
player.RecentFuse--;
|
player.RecentFuse--;
|
||||||
|
|
||||||
if ((Main.ServerSideCharacter) && (player.TPlayer.SpawnX > 0) && (player.sX != player.TPlayer.SpawnX))
|
if (Main.ServerSideCharacter && player.initialSpawn)
|
||||||
{
|
{
|
||||||
player.sX = player.TPlayer.SpawnX;
|
player.initialSpawn = false;
|
||||||
player.sY = player.TPlayer.SpawnY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Main.ServerSideCharacter) && (player.sX > 0) && (player.sY > 0) && (player.TPlayer.SpawnX < 0))
|
// reassert the correct spawnpoint value after the game's Spawn handler changed it
|
||||||
{
|
player.TPlayer.SpawnX = player.initialServerSpawnX;
|
||||||
player.TPlayer.SpawnX = player.sX;
|
player.TPlayer.SpawnY = player.initialServerSpawnY;
|
||||||
player.TPlayer.SpawnY = player.sY;
|
|
||||||
|
player.TeleportSpawnpoint();
|
||||||
|
TShock.Log.ConsoleDebug(GetString("OnSecondUpdate / initial ssc spawn for {0} at ({1}, {2})", player.Name, player.TPlayer.SpawnX, player.TPlayer.SpawnY));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.RPPending > 0)
|
if (player.RPPending > 0)
|
||||||
|
|
@ -1372,6 +1376,8 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bans.CheckBan(player);
|
||||||
Players[args.Who] = player;
|
Players[args.Who] = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1393,7 +1399,8 @@ namespace TShockAPI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bans.CheckBan(player);
|
if (Bans.CheckBan(player))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>OnLeave - Called when a player leaves the server.</summary>
|
/// <summary>OnLeave - Called when a player leaves the server.</summary>
|
||||||
|
|
@ -1433,7 +1440,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
if (tsplr.ReceivedInfo)
|
if (tsplr.ReceivedInfo)
|
||||||
{
|
{
|
||||||
if (!tsplr.SilentKickInProgress && tsplr.State >= 3)
|
if (!tsplr.SilentKickInProgress && tsplr.State >= 3 && tsplr.FinishedHandshake) //The player has left, do not broadcast any clients exploiting the behaviour of not spawning their player.
|
||||||
Utils.Broadcast(GetString("{0} has left.", tsplr.Name), Color.Yellow);
|
Utils.Broadcast(GetString("{0} has left.", tsplr.Name), Color.Yellow);
|
||||||
Log.Info(GetString("{0} disconnected.", tsplr.Name));
|
Log.Info(GetString("{0} disconnected.", tsplr.Name));
|
||||||
|
|
||||||
|
|
@ -1454,6 +1461,9 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tsplr.FinishedHandshake = false;
|
||||||
|
|
||||||
// Fire the OnPlayerLogout hook too, if the player was logged in and they have a TSPlayer object.
|
// Fire the OnPlayerLogout hook too, if the player was logged in and they have a TSPlayer object.
|
||||||
if (tsplr.IsLoggedIn)
|
if (tsplr.IsLoggedIn)
|
||||||
{
|
{
|
||||||
|
|
@ -1483,6 +1493,12 @@ namespace TShockAPI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tsplr.FinishedHandshake)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (args.Text.Length > 500)
|
if (args.Text.Length > 500)
|
||||||
{
|
{
|
||||||
tsplr.Kick(GetString("Crash attempt via long chat packet."), true);
|
tsplr.Kick(GetString("Crash attempt via long chat packet."), true);
|
||||||
|
|
@ -1501,11 +1517,11 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(text))
|
if (!String.IsNullOrEmpty(text))
|
||||||
{
|
{
|
||||||
text = item.Key.Value + ' ' + text;
|
text = EnglishLanguage.GetCommandPrefixByName(item.Value._name) + ' ' + text;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text = item.Key.Value;
|
text = EnglishLanguage.GetCommandPrefixByName(item.Value._name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1699,14 +1715,14 @@ namespace TShockAPI
|
||||||
Log.Info(GetString("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", player.Name, player.IP,
|
Log.Info(GetString("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", player.Name, player.IP,
|
||||||
player.Group.Name, player.Country, TShock.Utils.GetActivePlayerCount(),
|
player.Group.Name, player.Country, TShock.Utils.GetActivePlayerCount(),
|
||||||
TShock.Config.Settings.MaxSlots));
|
TShock.Config.Settings.MaxSlots));
|
||||||
if (!player.SilentJoinInProgress)
|
if (!player.SilentJoinInProgress && player.FinishedHandshake)
|
||||||
Utils.Broadcast(GetString("{0} ({1}) has joined.", player.Name, player.Country), Color.Yellow);
|
Utils.Broadcast(GetString("{0} ({1}) has joined.", player.Name, player.Country), Color.Yellow);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Info(GetString("{0} ({1}) from '{2}' group joined. ({3}/{4})", player.Name, player.IP,
|
Log.Info(GetString("{0} ({1}) from '{2}' group joined. ({3}/{4})", player.Name, player.IP,
|
||||||
player.Group.Name, TShock.Utils.GetActivePlayerCount(), TShock.Config.Settings.MaxSlots));
|
player.Group.Name, TShock.Utils.GetActivePlayerCount(), TShock.Config.Settings.MaxSlots));
|
||||||
if (!player.SilentJoinInProgress)
|
if (!player.SilentJoinInProgress && player.FinishedHandshake)
|
||||||
Utils.Broadcast(GetString("{0} has joined.", player.Name), Color.Yellow);
|
Utils.Broadcast(GetString("{0} has joined.", player.Name), Color.Yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@
|
||||||
Also, be sure to release on github with the exact assembly version tag as below
|
Also, be sure to release on github with the exact assembly version tag as below
|
||||||
so that the update manager works correctly (via the Github releases api and mimic)
|
so that the update manager works correctly (via the Github releases api and mimic)
|
||||||
-->
|
-->
|
||||||
<Version>5.1.3</Version>
|
<Version>5.2.2</Version>
|
||||||
<AssemblyTitle>TShock for Terraria</AssemblyTitle>
|
<AssemblyTitle>TShock for Terraria</AssemblyTitle>
|
||||||
<Company>Pryaxis & TShock Contributors</Company>
|
<Company>Pryaxis & TShock Contributors</Company>
|
||||||
<Product>TShockAPI</Product>
|
<Product>TShockAPI</Product>
|
||||||
<Copyright>Copyright © Pryaxis & TShock Contributors 2011-2022</Copyright>
|
<Copyright>Copyright © Pryaxis & TShock Contributors 2011-2023</Copyright>
|
||||||
<!-- extras for nuget -->
|
<!-- extras for nuget -->
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="GetText.NET" Version="1.7.14" />
|
<PackageReference Include="GetText.NET" Version="1.7.14" />
|
||||||
<PackageReference Include="MySql.Data" Version="8.0.31" />
|
<PackageReference Include="MySql.Data" Version="8.4.0" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.11" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.11" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@ namespace TShockAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TextLog : ILog, IDisposable
|
public class TextLog : ILog, IDisposable
|
||||||
{
|
{
|
||||||
private readonly StreamWriter _logWriter;
|
private readonly bool ClearFile;
|
||||||
|
private StreamWriter _logWriter;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// File name of the Text log
|
/// File name of the Text log
|
||||||
|
|
@ -44,7 +45,7 @@ namespace TShockAPI
|
||||||
public TextLog(string filename, bool clear)
|
public TextLog(string filename, bool clear)
|
||||||
{
|
{
|
||||||
FileName = filename;
|
FileName = filename;
|
||||||
_logWriter = new StreamWriter(filename, !clear);
|
ClearFile = clear;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MayWriteType(TraceLevel type)
|
public bool MayWriteType(TraceLevel type)
|
||||||
|
|
@ -247,6 +248,10 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (!MayWriteType(level))
|
if (!MayWriteType(level))
|
||||||
return;
|
return;
|
||||||
|
if (_logWriter is null)
|
||||||
|
{
|
||||||
|
_logWriter = new StreamWriter(FileName, !ClearFile);
|
||||||
|
}
|
||||||
|
|
||||||
var caller = "TShock";
|
var caller = "TShock";
|
||||||
|
|
||||||
|
|
@ -278,7 +283,10 @@ namespace TShockAPI
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_logWriter.Dispose();
|
if (_logWriter != null)
|
||||||
|
{
|
||||||
|
_logWriter.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ namespace TShockAPI
|
||||||
foreach (TSPlayer player in TShock.Players)
|
foreach (TSPlayer player in TShock.Players)
|
||||||
{
|
{
|
||||||
if (player != null && player != excludedPlayer && player.Active && player.HasPermission(Permissions.logs) &&
|
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);
|
player.SendMessage(log, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +183,7 @@ namespace TShockAPI
|
||||||
/// <returns>The number of active players on the server.</returns>
|
/// <returns>The number of active players on the server.</returns>
|
||||||
public int GetActivePlayerCount()
|
public int GetActivePlayerCount()
|
||||||
{
|
{
|
||||||
return Main.player.Where(p => null != p && p.active).Count();
|
return TShock.Players.Count(p => null != p && p.Active && p.FinishedHandshake);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Random should not be generated in a method
|
//Random should not be generated in a method
|
||||||
|
|
@ -330,7 +330,7 @@ namespace TShockAPI
|
||||||
/// <returns>The item represented by the tag.</returns>
|
/// <returns>The item represented by the tag.</returns>
|
||||||
public Item GetItemFromTag(string tag)
|
public Item GetItemFromTag(string tag)
|
||||||
{
|
{
|
||||||
Regex regex = new Regex(@"\[i(tem)?(?:\/s(?<Stack>\d{1,3}))?(?:\/p(?<Prefix>\d{1,3}))?:(?<NetID>-?\d{1,4})\]");
|
Regex regex = new Regex(@"\[i(tem)?(?:\/s(?<Stack>\d{1,4}))?(?:\/p(?<Prefix>\d{1,3}))?:(?<NetID>-?\d{1,4})\]");
|
||||||
Match match = regex.Match(tag);
|
Match match = regex.Match(tag);
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -1149,11 +1149,15 @@ namespace TShockAPI
|
||||||
/// <param name="empty">If the server is empty; determines if we should use Utils.GetActivePlayerCount() for player count or 0.</param>
|
/// <param name="empty">If the server is empty; determines if we should use Utils.GetActivePlayerCount() for player count or 0.</param>
|
||||||
internal void SetConsoleTitle(bool empty)
|
internal void SetConsoleTitle(bool empty)
|
||||||
{
|
{
|
||||||
|
if (ShouldSkipTitle)
|
||||||
|
return;
|
||||||
Console.Title = GetString("{0}{1}/{2} on {3} @ {4}:{5} (TShock for Terraria v{6})",
|
Console.Title = GetString("{0}{1}/{2} on {3} @ {4}:{5} (TShock for Terraria v{6})",
|
||||||
!string.IsNullOrWhiteSpace(TShock.Config.Settings.ServerName) ? TShock.Config.Settings.ServerName + " - " : "",
|
!string.IsNullOrWhiteSpace(TShock.Config.Settings.ServerName) ? TShock.Config.Settings.ServerName + " - " : "",
|
||||||
empty ? 0 : GetActivePlayerCount(),
|
empty ? 0 : GetActivePlayerCount(),
|
||||||
TShock.Config.Settings.MaxSlots, Main.worldName, Netplay.ServerIP.ToString(), Netplay.ListenPort, TShock.VersionNum);
|
TShock.Config.Settings.MaxSlots, Main.worldName, Netplay.ServerIP.ToString(), Netplay.ListenPort, TShock.VersionNum);
|
||||||
}
|
}
|
||||||
|
// Some terminals doesn't supports XTerm escape sequences for setting the title
|
||||||
|
private static bool ShouldSkipTitle = !System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows) && !(Environment.GetEnvironmentVariable("TERM")?.Contains("xterm") ?? false);
|
||||||
|
|
||||||
/// <summary>Determines the distance between two vectors.</summary>
|
/// <summary>Determines the distance between two vectors.</summary>
|
||||||
/// <param name="value1">The first vector location.</param>
|
/// <param name="value1">The first vector location.</param>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SharpZipLib" Version="1.4.1" />
|
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using TShockPluginManager;
|
using TShockPluginManager;
|
||||||
|
|
||||||
|
// On occasion, users have been seen extracting TShock into their client installation directory -- this is of course incorrect, and is known
|
||||||
|
// to cause issues. Let's attempt to catch this before anything happens (specifically, before Terraria assemblies are resolved) and prevent
|
||||||
|
// TShock from launching.
|
||||||
|
if (File.Exists("TerrariaServer.exe"))
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.Error.WriteLine("A \"TerrariaServer.exe\" file has been found in the current working directory.");
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
"This indicates either installation into a Terraria client directory, or installation into a legacy (TShock 4 or older) TShock directory.");
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
"TShock is never to be installed inside a Terraria client directory. You should instead extract your TShock installation into it's own directory.");
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
"If you are updating a legacy TShock installation, please follow the following documentation to update: https://ikebukuro.tshock.co/#/?id=upgrading-from-tshock-4");
|
||||||
|
Console.Error.WriteLine("The launcher will now exit.");
|
||||||
|
Console.ResetColor();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (args.Length > 0 && args[0].ToLower() == "plugins")
|
if (args.Length > 0 && args[0].ToLower() == "plugins")
|
||||||
{
|
{
|
||||||
var items = args.ToList();
|
var items = args.ToList();
|
||||||
items.RemoveAt(0);
|
items.RemoveAt(0);
|
||||||
await NugetCLI.Main(items);
|
await NugetCLI.Main(items);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,7 +60,7 @@ Dictionary<string, Assembly> _cache = new Dictionary<string, Assembly>();
|
||||||
|
|
||||||
System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += Default_Resolving;
|
System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += Default_Resolving;
|
||||||
|
|
||||||
Start();
|
return Start();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resolves a module from the ./bin folder, either with a .dll by preference or .exe
|
/// Resolves a module from the ./bin folder, either with a .dll by preference or .exe
|
||||||
|
|
@ -70,7 +88,8 @@ Assembly? Default_Resolving(System.Runtime.Loader.AssemblyLoadContext arg1, Asse
|
||||||
/// Initiates the TSAPI server.
|
/// Initiates the TSAPI server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This method exists so that the resolver can attach before TSAPI needs its dependencies.</remarks>
|
/// <remarks>This method exists so that the resolver can attach before TSAPI needs its dependencies.</remarks>
|
||||||
void Start()
|
int Start()
|
||||||
{
|
{
|
||||||
TerrariaApi.Server.Program.Main(args);
|
TerrariaApi.Server.Program.Main(args);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="MySql.Data" Version="8.0.31" />
|
<PackageReference Include="MySql.Data" Version="8.4.0" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.11" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.11" />
|
||||||
<PackageReference Include="ModFramework" Version="1.1.7" GeneratePathProperty="true" /> <!-- only used to extract out to ./bin. -->
|
<PackageReference Include="ModFramework" Version="1.1.7" GeneratePathProperty="true" /> <!-- only used to extract out to ./bin. -->
|
||||||
<PackageReference Include="GetText.NET" Version="1.7.14" /> <!-- only used to extract out to ./bin. -->
|
<PackageReference Include="GetText.NET" Version="1.7.14" /> <!-- only used to extract out to ./bin. -->
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ using NuGet.Versioning;
|
||||||
|
|
||||||
namespace TShockPluginManager
|
namespace TShockPluginManager
|
||||||
{
|
{
|
||||||
|
|
||||||
public class Nugetter
|
public class Nugetter
|
||||||
{
|
{
|
||||||
// this object can figure out the right framework folders to use from a set of packages
|
// this object can figure out the right framework folders to use from a set of packages
|
||||||
|
|
@ -82,15 +81,13 @@ namespace TShockPluginManager
|
||||||
// make sure the source repository can actually tell us about dependencies
|
// make sure the source repository can actually tell us about dependencies
|
||||||
var dependencyInfoResource = await sourceRepository.GetResourceAsync<DependencyInfoResource>();
|
var dependencyInfoResource = await sourceRepository.GetResourceAsync<DependencyInfoResource>();
|
||||||
// get the try and dependencies
|
// get the try and dependencies
|
||||||
// (the above function returns a nullable value, but doesn't properly indicate it as such)
|
if (dependencyInfoResource is null) continue;
|
||||||
#pragma warning disable CS8602
|
var dependencyInfo = await dependencyInfoResource.ResolvePackage(
|
||||||
var dependencyInfo = await dependencyInfoResource?.ResolvePackage(
|
|
||||||
package, framework, cacheContext, logger, CancellationToken.None);
|
package, framework, cacheContext, logger, CancellationToken.None);
|
||||||
#pragma warning restore CS8602
|
|
||||||
|
|
||||||
// oop, we don't have the ability to get dependency info from this repository, or
|
// oop, we don't have the ability to get dependency info from this repository, or
|
||||||
// it wasn't found. let's try the next source repository!
|
// it wasn't found. let's try the next source repository!
|
||||||
if (dependencyInfo == null) continue;
|
if (dependencyInfo is null) continue;
|
||||||
|
|
||||||
availablePackages.Add(dependencyInfo);
|
availablePackages.Add(dependencyInfo);
|
||||||
foreach (var dependency in dependencyInfo.Dependencies)
|
foreach (var dependency in dependencyInfo.Dependencies)
|
||||||
|
|
@ -302,8 +299,11 @@ namespace TShockPluginManager
|
||||||
|
|
||||||
var relativeFolder = Path.GetDirectoryName(packageRelativeFilePath);
|
var relativeFolder = Path.GetDirectoryName(packageRelativeFilePath);
|
||||||
var targetFolder = Path.Join(isPlugin ? "./ServerPlugins" : "./bin", relativeFolder);
|
var targetFolder = Path.Join(isPlugin ? "./ServerPlugins" : "./bin", relativeFolder);
|
||||||
Directory.CreateDirectory(targetFolder);
|
if (File.Exists(filePath))
|
||||||
File.Copy(filePath, Path.Join(targetFolder, Path.GetFileName(filePath)), true);
|
{
|
||||||
|
Directory.CreateDirectory(targetFolder);
|
||||||
|
File.Copy(filePath, Path.Join(targetFolder, Path.GetFileName(filePath)), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NuGet.Packaging" Version="6.3.1" />
|
<PackageReference Include="NuGet.Packaging" Version="6.3.4" />
|
||||||
<PackageReference Include="NuGet.Protocol" Version="6.3.1" />
|
<PackageReference Include="NuGet.Protocol" Version="6.3.3" />
|
||||||
<PackageReference Include="NuGet.Resolver" Version="6.3.1" />
|
<PackageReference Include="NuGet.Resolver" Version="6.3.1" />
|
||||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="6.0.0" />
|
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="6.0.0" />
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit e0e2df24dbc618683cc75595c59bf7f88acada08
|
Subproject commit d4bb7e3a21e875cfeb23bcf5cf847c85d9470ccf
|
||||||
|
|
@ -78,7 +78,53 @@ Use past tense when adding new entries; sign your name off when you add or chang
|
||||||
* If there is no section called "Upcoming changes" below this line, please add one with `## Upcoming changes` as the first line, and then a bulleted item directly after with the first change. -->
|
* If there is no section called "Upcoming changes" below this line, please add one with `## Upcoming changes` as the first line, and then a bulleted item directly after with the first change. -->
|
||||||
|
|
||||||
## Upcoming changes
|
## Upcoming changes
|
||||||
* An additional option `pvpwithnoteam` is added at `PvPMode` to enable PVP with no team.(@CelestialAnarchy, #2617, @ATFGK)
|
* Added a variable for handshake (True upon spawn player), clients no longer notify others of their presence and cant chat if this is never set to true. (@ohayo)
|
||||||
|
* Fixed a security issue with how bans are handled on join. (@ohayo)
|
||||||
|
* Fixed `/dump-reference-data` mutate the command names. (#2943, @sgkoishi)
|
||||||
|
* 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.
|
||||||
|
* Fixed unable to transfer long response body for REST API. (@sgkoishi, #2925)
|
||||||
|
* Fixed the `/wind` command not being very helpful. (@punchready)
|
||||||
|
* Fixed /help, /me, and /p commands can't work in non-English languages. (@ACaiCat)
|
||||||
|
* Added a hook `AccountHooks.AccountGroupUpdate`, which is called when you change the user group. (@AgaSpace)
|
||||||
|
* * Ensured `TSPlayer.PlayerData` is non-null whilst syncing loadouts. (@drunderscore)
|
||||||
|
* * Detected invalid installations, by checking for a file named `TerrariaServer.exe`. (@drunderscore)
|
||||||
|
* This made the two most common installation mistakes (extracting into the Terraria client directory, and extracting TShock 5 or newer into a TShock 4 or older install) prompt the user with a more useful diagnostic, rather than (likely) crashing moments later. Rewrote bed spawning for SSC. (@PotatoCider)
|
||||||
|
* Removed `TSPlayer.s{X,Y}` in favour of using desyncing client and server spawnpoint values (`Terraria.Player.Spawn{X,Y}`) until the player has changed their spawnpoint per session.
|
||||||
|
* Partially fixed the bed spawning bug when SSC is enabled. Players would need to spawn at their beds at least once to tell TShock that the player's spawnpoint has changed.
|
||||||
|
* Changed Bouncer to block updates which set the following fields to infinity or NaN: player position, projectile position, projectile velocity, item position, and item velocity. (@Arthri)
|
||||||
|
* Updated `TShockAPI.Handlers.SendTileRectHandler` (@LaoSparrow):
|
||||||
|
* Fixed incorrect validating range in `TileRectMatch.MatchRemoval`.
|
||||||
|
* Fixed tile rect changes (e.g. turning on and off campfires) are not synced between clients.
|
||||||
|
* Fixed unable to place Hat Rack without permission `tshock.ignore.sendtilesquare`.
|
||||||
|
* Updated `GetDataHandlers` to ignore `NpcItemStrike(msgid 24)`, which should never be sent by a vanilla client. (@LaoSparrow)
|
||||||
|
|
||||||
|
## TShock 5.2.1
|
||||||
|
* Updated `TSPlayer.GodMode`. (@AgaSpace)
|
||||||
|
* Previously the field was used as some kind of dataset changed by /godmode command, but now it is a property that receives/changes data in journey mode.
|
||||||
|
* Added the `TSPlayer.Client` property. It allows the developer to get the `RemoteClient` player, without an additional call to `Terraria.Netplay.Clients`. (@AgaSpace)
|
||||||
|
* Updated the documentation for the `TSPlayer.SetPvP` method. The `sendMsg` parameter, which is responsible for sending a pvp mode change message, was not documented earlier. (@AgaSpace)
|
||||||
|
* Added methods `TSPlayer.KillPlayer` and `TSPlayer.DamagePlayer` for which you can specify the cause (`PlayerDeathReason`) in parameters. (@AgaSpace)
|
||||||
|
* Added an error when trying to change a `TSPlayer` team to, say, 9, when there are only 6. (@AgaSpace)
|
||||||
|
* Added an error when trying to call the `TSPlayer.SetTeam` method with an argument (team) greater than 5 or less than 0. (@AgaSpace)
|
||||||
|
* Added a method `TSPlayer.UpdateSection` with arguments `rectangle` and `isLoaded`, which will load some area from the server to the player. (@AgaSpace)
|
||||||
|
* Added a method `TSPlayer.GiveItem`, which has `TShockAPI.NetItem` structure in its arguments. (@AgaSpace)
|
||||||
|
* Added a property `TSPlayer.Hostile`, which gets pvp player mode. (@AgaSpace)
|
||||||
|
* 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)
|
||||||
|
* Added a constructor for `TShockAPI.PlayerData` that accepts the `includingStarterInventory` parameter, which is responsible for loading the TShock inventory.
|
||||||
|
* Declared the constructor `TShockAPI.PlayerData` accepting the argument `TShockAPI.TSPlayer` obsolete.
|
||||||
|
* Updated the `PlayerData.StoreSlot` method: Added an overload that takes `TShockAPI.NetItem`.
|
||||||
|
* Added `PlayerHooks.PrePlayerCommand` hook, which fired before command execution. (@AgaSpace)
|
||||||
|
* Added `PlayerHooks.PostPlayerCommand` hook, which fired after command execution. (@AgaSpace)
|
||||||
|
|
||||||
|
## 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):
|
* Corrected and updated deserialization of the following packets (@ATFGK):
|
||||||
* `ProjectileNew`: Read the third `AI` value.
|
* `ProjectileNew`: Read the third `AI` value.
|
||||||
* Before this change, it was previously possible for the projectile damage limit to falsely trigger, such as when using the Terra Balde and Fire Gauntlet together.
|
* Before this change, it was previously possible for the projectile damage limit to falsely trigger, such as when using the Terra Balde and Fire Gauntlet together.
|
||||||
|
|
@ -105,6 +151,10 @@ Use past tense when adding new entries; sign your name off when you add or chang
|
||||||
* Initialized achievements and the `AchievementManager` on the server. This ensures that players cannot cause exceptions to be thrown, chat messages are always logged, and allows achievement names to be localized in the console. Also added a test case for this. (@drunderscore)
|
* Initialized achievements and the `AchievementManager` on the server. This ensures that players cannot cause exceptions to be thrown, chat messages are always logged, and allows achievement names to be localized in the console. Also added a test case for this. (@drunderscore)
|
||||||
* Allowed multiple test cases to be in TShock's test suite. (@drunderscore)
|
* Allowed multiple test cases to be in TShock's test suite. (@drunderscore)
|
||||||
* Fixed unable to use Purification/Evil Powder in jungle. (@sgkoishi)
|
* Fixed unable to use Purification/Evil Powder in jungle. (@sgkoishi)
|
||||||
|
* Set the `GetDataHandledEventArgs.Player` property for the `SyncTilePicking` data handler. (@drunderscore)
|
||||||
|
* 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)
|
||||||
|
|
||||||
## TShock 5.1.3
|
## TShock 5.1.3
|
||||||
* Added support for Terraria 1.4.4.9 via OTAPI 3.1.20. (@SignatureBeef)
|
* Added support for Terraria 1.4.4.9 via OTAPI 3.1.20. (@SignatureBeef)
|
||||||
|
|
|
||||||
|
|
@ -14,32 +14,27 @@ Open ports can also be passed through using `-p <host_port>:<container_port>`.
|
||||||
|
|
||||||
For Example:
|
For Example:
|
||||||
```bash
|
```bash
|
||||||
# Building the image
|
|
||||||
docker build -t tshock:linux-amd64 --build-arg TARGETPLATFORM=linux/amd64 .
|
|
||||||
|
|
||||||
# Running the image
|
|
||||||
docker run -p 7777:7777 -p 7878:7878 \
|
docker run -p 7777:7777 -p 7878:7878 \
|
||||||
-v /home/cider/tshock/:/tshock \
|
-v /home/cider/tshock/:/tshock \
|
||||||
-v /home/cider/.local/share/Terraria/Worlds:/worlds \
|
-v /home/cider/.local/share/Terraria/Worlds:/worlds \
|
||||||
-v /home/cider/tshock/plugins:/plugins \
|
-v /home/cider/tshock/plugins:/plugins \
|
||||||
--rm -it tshock:linux-amd64 \
|
--rm -it ghcr.io/pryaxis/tshock:latest \
|
||||||
-world /worlds/backflip.wld -motd "OMFG DOCKER"
|
-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
|
```bash
|
||||||
# Building the image using buildx and loading it into docker
|
docker buildx build -t tshock:latest --load .
|
||||||
sudo docker buildx build -t tshock:linux-arm64 --platform linux/arm64 --load .
|
```
|
||||||
|
|
||||||
# Running the image
|
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`):
|
||||||
docker run -p 7777:7777 -p 7878:7878 \
|
|
||||||
-v /home/cider/tshock/:/tshock \
|
```bash
|
||||||
-v /home/cider/.local/share/Terraria/Worlds:/worlds \
|
docker buildx build -t tshock:linux-arm64 --platform linux/arm64 --load .
|
||||||
-v /home/cider/tshock/plugins:/plugins \
|
|
||||||
--rm -it tshock:linux-arm64 \
|
|
||||||
-world /worlds/backflip.wld -motd "ARM64 ftw"
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script>
|
<script>
|
||||||
window.$docsify = {
|
window.location.replace("https://github.com/Pryaxis/TShock/wiki");
|
||||||
name: 'TShock for Terraria',
|
|
||||||
repo: 'pryaxis/tshock',
|
|
||||||
loadSidebar: true,
|
|
||||||
subMaxLevel: 9
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<!-- Docsify v4 -->
|
<!-- Docsify v4 -->
|
||||||
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: tshock\n"
|
"Project-Id-Version: tshock\n"
|
||||||
"POT-Creation-Date: 2022-12-06 05:43:49+0000\n"
|
"POT-Creation-Date: 2022-12-06 05:43:49+0000\n"
|
||||||
"PO-Revision-Date: 2022-12-06 05:52\n"
|
"PO-Revision-Date: 2022-12-30 01:02\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: Portuguese, Brazilian\n"
|
"Language-Team: Portuguese, Brazilian\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|
@ -1149,7 +1149,7 @@ msgstr "De {0} a {1}"
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:187
|
#: ../../TShockPluginManager/NugetCLI.cs:187
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "<green>{0} <black>from <blue>{1} <black>[{2}]"
|
msgid "<green>{0} <black>from <blue>{1} <black>[{2}]"
|
||||||
msgstr ""
|
msgstr "<verde>{0} <preto>de <azul>{1} <preto>[{2}]"
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:178
|
#: ../../TShockPluginManager/NugetCLI.cs:178
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -1166,15 +1166,15 @@ msgstr "<Para {0}> {1}"
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "=== Dependency ==="
|
msgid "=== Dependency ==="
|
||||||
msgid_plural "=== Dependencies ==="
|
msgid_plural "=== Dependencies ==="
|
||||||
msgstr[0] ""
|
msgstr[0] "=== Dependência ==="
|
||||||
msgstr[1] ""
|
msgstr[1] "=== Dependências ==="
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:133
|
#: ../../TShockPluginManager/NugetCLI.cs:133
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "=== Requested Plugin ==="
|
msgid "=== Requested Plugin ==="
|
||||||
msgid_plural "=== Requested Plugins ==="
|
msgid_plural "=== Requested Plugins ==="
|
||||||
msgstr[0] ""
|
msgstr[0] "=== Plugin exigido ==="
|
||||||
msgstr[1] ""
|
msgstr[1] "=== Plugins exigidos ==="
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2818
|
#: ../../TShockAPI/Commands.cs:2818
|
||||||
msgid "a Deerclops"
|
msgid "a Deerclops"
|
||||||
|
|
@ -1325,7 +1325,7 @@ msgstr "todos os chefes"
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:169
|
#: ../../TShockPluginManager/NugetCLI.cs:169
|
||||||
msgid "All done! :)"
|
msgid "All done! :)"
|
||||||
msgstr ""
|
msgstr "Concluído!"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2104
|
#: ../../TShockAPI/Commands.cs:2104
|
||||||
msgid "All REST tokens have been destroyed."
|
msgid "All REST tokens have been destroyed."
|
||||||
|
|
@ -1847,7 +1847,7 @@ msgstr "Bouncer / OnLiquidSet rejeitou a verificação inválida de {0}"
|
||||||
#: ../../TShockAPI/Bouncer.cs:1731
|
#: ../../TShockAPI/Bouncer.cs:1731
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Bouncer / OnLiquidSet rejected liquid type {0} from {1} holding {2}"
|
msgid "Bouncer / OnLiquidSet rejected liquid type {0} from {1} holding {2}"
|
||||||
msgstr ""
|
msgstr "Segurador / OnLiquidSet rejeitou o tipo líquido {0} de {1} segurando {2}"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1840
|
#: ../../TShockAPI/Bouncer.cs:1840
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -2671,7 +2671,7 @@ msgstr "Configuração, permissões e regiões recarregadas completamente. Algum
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:100
|
#: ../../TShockPluginManager/NugetCLI.cs:100
|
||||||
msgid "Connect to the internet to figure out what to download?"
|
msgid "Connect to the internet to figure out what to download?"
|
||||||
msgstr ""
|
msgstr "Conectar-se à internet para descobrir o que baixar?"
|
||||||
|
|
||||||
#: ../../TShockAPI/TShock.cs:1329
|
#: ../../TShockAPI/TShock.cs:1329
|
||||||
msgid "Connecting via a proxy is not allowed."
|
msgid "Connecting via a proxy is not allowed."
|
||||||
|
|
@ -2901,7 +2901,7 @@ msgstr "disallow <ID do bloco> <grupo> - Desautoriza um grupo de usar o bloco."
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:140
|
#: ../../TShockPluginManager/NugetCLI.cs:140
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:161
|
#: ../../TShockPluginManager/NugetCLI.cs:161
|
||||||
msgid "Download and install the given packages?"
|
msgid "Download and install the given packages?"
|
||||||
msgstr ""
|
msgstr "Baixar e instalar os pacotes indicados?"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2648
|
#: ../../TShockAPI/Commands.cs:2648
|
||||||
msgid "Duke Fishron"
|
msgid "Duke Fishron"
|
||||||
|
|
@ -3739,11 +3739,11 @@ msgstr "Se você entendeu, por favor digite {0}login <nome de usuário> <senha>
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:142
|
#: ../../TShockPluginManager/NugetCLI.cs:142
|
||||||
msgid "If you want to know which plugins need which dependencies, press E."
|
msgid "If you want to know which plugins need which dependencies, press E."
|
||||||
msgstr ""
|
msgstr "Se você quiser saber quais plugins precisam de quais dependências, pressione E."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:162
|
#: ../../TShockPluginManager/NugetCLI.cs:162
|
||||||
msgid "If you'd like to see which plugins need which dependencies again, press E."
|
msgid "If you'd like to see which plugins need which dependencies again, press E."
|
||||||
msgstr ""
|
msgstr "Se você quiser ver quais plugins precisam de dependências novamente, pressione E."
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:986
|
#: ../../TShockAPI/Bouncer.cs:986
|
||||||
msgid "If you're seeing this message and you know what that player did, please report it to TShock for further investigation."
|
msgid "If you're seeing this message and you know what that player did, please report it to TShock for further investigation."
|
||||||
|
|
@ -3799,7 +3799,7 @@ msgstr "Falha ao inserir o banimento no banco de dados."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:39
|
#: ../../TShockPluginManager/NugetCLI.cs:39
|
||||||
msgid "Install the plugins as specified in the plugins.json"
|
msgid "Install the plugins as specified in the plugins.json"
|
||||||
msgstr ""
|
msgstr "Instalar os plugins conforme especificado no plugins.json"
|
||||||
|
|
||||||
#: ../../TShockAPI/Rest/Rest.cs:426
|
#: ../../TShockAPI/Rest/Rest.cs:426
|
||||||
msgid "Internal server error."
|
msgid "Internal server error."
|
||||||
|
|
@ -4566,7 +4566,7 @@ msgstr "Nome da máquina: {0}"
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:141
|
#: ../../TShockPluginManager/NugetCLI.cs:141
|
||||||
msgid "Make sure that you trust the plugins you're installing."
|
msgid "Make sure that you trust the plugins you're installing."
|
||||||
msgstr ""
|
msgstr "Certifique-se de confiar nos plugins que você está instalando."
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:2471
|
#: ../../TShockAPI/Bouncer.cs:2471
|
||||||
msgid "Malicious portal attempt."
|
msgid "Malicious portal attempt."
|
||||||
|
|
@ -4574,7 +4574,7 @@ msgstr "Tentativa de portal malicioso."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:35
|
#: ../../TShockPluginManager/NugetCLI.cs:35
|
||||||
msgid "Manage plugins and their requirements"
|
msgid "Manage plugins and their requirements"
|
||||||
msgstr ""
|
msgstr "Gerenciar plugins e suas exigências"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:280
|
#: ../../TShockAPI/Commands.cs:280
|
||||||
msgid "Manages groups."
|
msgid "Manages groups."
|
||||||
|
|
@ -4614,7 +4614,7 @@ msgstr "Gerencia contas de usuários."
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1775
|
#: ../../TShockAPI/Bouncer.cs:1775
|
||||||
msgid "Manipulating unknown liquid type"
|
msgid "Manipulating unknown liquid type"
|
||||||
msgstr ""
|
msgstr "Manipulando tipo de líquido desconhecido"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:4721
|
#: ../../TShockAPI/Commands.cs:4721
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -4816,7 +4816,7 @@ msgstr "Dano do NPC excedeu {0}."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:103
|
#: ../../TShockPluginManager/NugetCLI.cs:103
|
||||||
msgid "One moment..."
|
msgid "One moment..."
|
||||||
msgstr ""
|
msgstr "Aguarde..."
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/RegionManager.cs:102
|
#: ../../TShockAPI/DB/RegionManager.cs:102
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -5141,7 +5141,7 @@ msgstr "Limite de TilePlace atingido."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:128
|
#: ../../TShockPluginManager/NugetCLI.cs:128
|
||||||
msgid "Read the message below to find out more."
|
msgid "Read the message below to find out more."
|
||||||
msgstr ""
|
msgstr "Leia a mensagem abaixo para saber mais."
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1495
|
#: ../../TShockAPI/Commands.cs:1495
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -6041,7 +6041,7 @@ msgstr "O valor deve ser maior que zero."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:127
|
#: ../../TShockPluginManager/NugetCLI.cs:127
|
||||||
msgid "The versions of plugins you requested aren't compatible with eachother."
|
msgid "The versions of plugins you requested aren't compatible with eachother."
|
||||||
msgstr ""
|
msgstr "As versões de plugins que você solicitou não são compatíveis uns com os outros."
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2722
|
#: ../../TShockAPI/Commands.cs:2722
|
||||||
msgid "the Wall of Flesh"
|
msgid "the Wall of Flesh"
|
||||||
|
|
@ -6110,17 +6110,17 @@ msgstr "Ocorreu um erro ao processar seu login ou solicitação relacionada à a
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:121
|
#: ../../TShockPluginManager/NugetCLI.cs:121
|
||||||
msgid "There was an issue figuring out what to download."
|
msgid "There was an issue figuring out what to download."
|
||||||
msgstr ""
|
msgstr "Houve um problema ao descobrir o que baixar."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:90
|
#: ../../TShockPluginManager/NugetCLI.cs:90
|
||||||
msgid "There was an issue reading the packages.json."
|
msgid "There was an issue reading the packages.json."
|
||||||
msgstr ""
|
msgstr "Houve um problema ao ler packages.json."
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:99
|
#: ../../TShockPluginManager/NugetCLI.cs:99
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "This is the plugin you requested to install."
|
msgid "This is the plugin you requested to install."
|
||||||
msgid_plural "These are the plugins you requested to install"
|
msgid_plural "These are the plugins you requested to install"
|
||||||
msgstr[0] ""
|
msgstr[0] "Este é o plugin que você solicitou para instalar."
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: ../../TShockAPI/TShock.cs:1013
|
#: ../../TShockAPI/TShock.cs:1013
|
||||||
|
|
@ -6574,37 +6574,37 @@ msgstr "Usando {0} para implementação de bloco"
|
||||||
#: ../../TShockAPI/Bouncer.cs:1794
|
#: ../../TShockAPI/Bouncer.cs:1794
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using {0} on non-honey"
|
msgid "Using {0} on non-honey"
|
||||||
msgstr ""
|
msgstr "Usando {0} em não-mel"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1803
|
#: ../../TShockAPI/Bouncer.cs:1803
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using {0} on non-lava"
|
msgid "Using {0} on non-lava"
|
||||||
msgstr ""
|
msgstr "Usando {0} em não-lava"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1810
|
#: ../../TShockAPI/Bouncer.cs:1810
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using {0} on non-shimmer"
|
msgid "Using {0} on non-shimmer"
|
||||||
msgstr ""
|
msgstr "Usando {0} em não-cintilante"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1785
|
#: ../../TShockAPI/Bouncer.cs:1785
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using {0} on non-water"
|
msgid "Using {0} on non-water"
|
||||||
msgstr ""
|
msgstr "Usando {0} em não-água"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1817
|
#: ../../TShockAPI/Bouncer.cs:1817
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using {0} on non-water or shimmer"
|
msgid "Using {0} on non-water or shimmer"
|
||||||
msgstr ""
|
msgstr "Usando {0} em não-água ou cintilante"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1825
|
#: ../../TShockAPI/Bouncer.cs:1825
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using {0} to manipulate unknown liquid {1}"
|
msgid "Using {0} to manipulate unknown liquid {1}"
|
||||||
msgstr ""
|
msgstr "Usando {0} para manipular líquido desconhecido {1}"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1740
|
#: ../../TShockAPI/Bouncer.cs:1740
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Using banned {0} to manipulate liquid"
|
msgid "Using banned {0} to manipulate liquid"
|
||||||
msgstr ""
|
msgstr "Uso banido {0} para manipular líquido"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1763
|
#: ../../TShockAPI/Bouncer.cs:1763
|
||||||
msgid "Using banned honey bucket without permissions"
|
msgid "Using banned honey bucket without permissions"
|
||||||
|
|
@ -6616,7 +6616,7 @@ msgstr "Usando balde de lava banido sem permissões"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1770
|
#: ../../TShockAPI/Bouncer.cs:1770
|
||||||
msgid "Using banned shimmering water bucket without permissions"
|
msgid "Using banned shimmering water bucket without permissions"
|
||||||
msgstr ""
|
msgstr "Usando balde de água cintilante banido sem permissões"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1749
|
#: ../../TShockAPI/Bouncer.cs:1749
|
||||||
msgid "Using banned water bucket without permissions"
|
msgid "Using banned water bucket without permissions"
|
||||||
|
|
@ -6694,7 +6694,7 @@ msgstr "Árvore de salgueiro"
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:85
|
#: ../../TShockPluginManager/NugetCLI.cs:85
|
||||||
msgid "Without a list of plugins to install, no plugins can be installed."
|
msgid "Without a list of plugins to install, no plugins can be installed."
|
||||||
msgstr ""
|
msgstr "Sem uma lista de plugins para instalar, nenhum plugin pode ser instalado."
|
||||||
|
|
||||||
#: ../../TShockAPI/BackupManager.cs:80
|
#: ../../TShockAPI/BackupManager.cs:80
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -7319,7 +7319,7 @@ msgstr "Não é permitido alterar blocos aqui!"
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:84
|
#: ../../TShockPluginManager/NugetCLI.cs:84
|
||||||
msgid "You're trying to sync, but you don't have a packages.json file."
|
msgid "You're trying to sync, but you don't have a packages.json file."
|
||||||
msgstr ""
|
msgstr "Você está tentando sincronizar, mas não tem um arquivo packages.json."
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1987
|
#: ../../TShockAPI/Commands.cs:1987
|
||||||
msgid "Your account has been elevated to superadmin for 10 minutes."
|
msgid "Your account has been elevated to superadmin for 10 minutes."
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: tshock\n"
|
"Project-Id-Version: tshock\n"
|
||||||
"POT-Creation-Date: 2022-12-06 05:43:49+0000\n"
|
"POT-Creation-Date: 2022-12-06 05:43:49+0000\n"
|
||||||
"PO-Revision-Date: 2022-12-06 05:52\n"
|
"PO-Revision-Date: 2023-01-11 13:30\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: Turkish\n"
|
"Language-Team: Turkish\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|
@ -1028,12 +1028,12 @@ msgstr "{0} adlı oyuncunun son bilinen IP adresi {1}."
|
||||||
#: ../../TShockAPI/Commands.cs:1286
|
#: ../../TShockAPI/Commands.cs:1286
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0}'s last login occurred {1} {2} UTC{3}."
|
msgid "{0}'s last login occurred {1} {2} UTC{3}."
|
||||||
msgstr ""
|
msgstr "{0} adlı oyuncunun son girişi {1} {2} UTC {3}."
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1298
|
#: ../../TShockAPI/Commands.cs:1298
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0}'s register date is {1} {2} UTC{3}."
|
msgid "{0}'s register date is {1} {2} UTC{3}."
|
||||||
msgstr ""
|
msgstr "{0} adlı oyuncunun kayıt tarihi {1} {2} UTC{3}."
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:5778
|
#: ../../TShockAPI/Commands.cs:5778
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -1093,19 +1093,19 @@ msgstr ""
|
||||||
#: ../../TShockAPI/Permissions.cs:547
|
#: ../../TShockAPI/Permissions.cs:547
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "* **Commands**: `{0}`"
|
msgid "* **Commands**: `{0}`"
|
||||||
msgstr ""
|
msgstr "* **Komutlar**: `{0}`"
|
||||||
|
|
||||||
#: ../../TShockAPI/Configuration/ServerSideConfig.cs:123
|
#: ../../TShockAPI/Configuration/ServerSideConfig.cs:123
|
||||||
#: ../../TShockAPI/Configuration/TShockConfig.cs:645
|
#: ../../TShockAPI/Configuration/TShockConfig.cs:645
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "* **Default**: `{0}`"
|
msgid "* **Default**: `{0}`"
|
||||||
msgstr ""
|
msgstr "* **Varsayılan**: `{0}`"
|
||||||
|
|
||||||
#: ../../TShockAPI/Configuration/ServerSideConfig.cs:122
|
#: ../../TShockAPI/Configuration/ServerSideConfig.cs:122
|
||||||
#: ../../TShockAPI/Configuration/TShockConfig.cs:644
|
#: ../../TShockAPI/Configuration/TShockConfig.cs:644
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "* **Field type**: `{0}`"
|
msgid "* **Field type**: `{0}`"
|
||||||
msgstr ""
|
msgstr "* **Alan türü**: `{0}`"
|
||||||
|
|
||||||
#: ../../TShockAPI/Rest/RestManager.cs:1220
|
#: ../../TShockAPI/Rest/RestManager.cs:1220
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -1167,14 +1167,14 @@ msgstr "<{0} hedefine> {1}"
|
||||||
msgid "=== Dependency ==="
|
msgid "=== Dependency ==="
|
||||||
msgid_plural "=== Dependencies ==="
|
msgid_plural "=== Dependencies ==="
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] "=== Bağımlılıklar ==="
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:133
|
#: ../../TShockPluginManager/NugetCLI.cs:133
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "=== Requested Plugin ==="
|
msgid "=== Requested Plugin ==="
|
||||||
msgid_plural "=== Requested Plugins ==="
|
msgid_plural "=== Requested Plugins ==="
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] "=== İstenen Eklentiler ==="
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2818
|
#: ../../TShockAPI/Commands.cs:2818
|
||||||
msgid "a Deerclops"
|
msgid "a Deerclops"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: tshock\n"
|
"Project-Id-Version: tshock\n"
|
||||||
"POT-Creation-Date: 2022-12-06 05:43:49+0000\n"
|
"POT-Creation-Date: 2022-12-06 05:43:49+0000\n"
|
||||||
"PO-Revision-Date: 2022-12-06 17:49\n"
|
"PO-Revision-Date: 2023-01-04 07:35\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: Chinese Simplified\n"
|
"Language-Team: Chinese Simplified\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|
@ -99,7 +99,7 @@ msgstr " {1}会被作为玩家名称或序号进行识别,除非添加了参
|
||||||
#: ../../TShockAPI/Commands.cs:1262
|
#: ../../TShockAPI/Commands.cs:1262
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid " -> Logged-in as: {0}; in group {1}."
|
msgid " -> Logged-in as: {0}; in group {1}."
|
||||||
msgstr " -> 登录为用户 {0} , 在组 {1} 中。"
|
msgstr " ->登录为用户 {0} , 在组 {1} 中。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1398
|
#: ../../TShockAPI/Commands.cs:1398
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -127,7 +127,7 @@ msgstr "- 根据用户名封禁一个不在线的玩家"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1445
|
#: ../../TShockAPI/Commands.cs:1445
|
||||||
msgid "- Ban an offline player by IP address"
|
msgid "- Ban an offline player by IP address"
|
||||||
msgstr "- 封禁离线玩家的IP地址"
|
msgstr "- 通过IP地址封禁离线的玩家"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1448
|
#: ../../TShockAPI/Commands.cs:1448
|
||||||
msgid "- Ban an online player by index (Useful for hard to type names)"
|
msgid "- Ban an online player by index (Useful for hard to type names)"
|
||||||
|
|
@ -345,7 +345,7 @@ msgstr "{0} <{1}|{2}|{3}> [{4}]"
|
||||||
#: ../../TShockAPI/Commands.cs:1106
|
#: ../../TShockAPI/Commands.cs:1106
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} added account {1} to group {2}."
|
msgid "{0} added account {1} to group {2}."
|
||||||
msgstr "{0} 将账号 {1} 添加至组 {2}!"
|
msgstr "{0} 将账号 {1} 添加至组 {2}!"
|
||||||
|
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:3546
|
#: ../../TShockAPI/GetDataHandlers.cs:3546
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -365,7 +365,7 @@ msgstr "{0}使用了游商背包([i:5343])。"
|
||||||
#: ../../TShockAPI/Commands.cs:1064
|
#: ../../TShockAPI/Commands.cs:1064
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} attempted to register for the account {1} but it was already taken."
|
msgid "{0} attempted to register for the account {1} but it was already taken."
|
||||||
msgstr "{0}尝试注册账号“{1}” ,但它已被注册。"
|
msgstr "{0}试图注册账号“{1}” ,但它已被占用。"
|
||||||
|
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:2637
|
#: ../../TShockAPI/GetDataHandlers.cs:2637
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:3212
|
#: ../../TShockAPI/GetDataHandlers.cs:3212
|
||||||
|
|
@ -381,7 +381,7 @@ msgstr "{0}已成功登录账号{1}。"
|
||||||
#: ../../TShockAPI/TSPlayer.cs:1955
|
#: ../../TShockAPI/TSPlayer.cs:1955
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} banned {1} for '{2}'."
|
msgid "{0} banned {1} for '{2}'."
|
||||||
msgstr "{0} 以'{2}'为理由封禁了{1}"
|
msgstr "{0} 以'{2}'为理由封禁了'{1}'"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:6051
|
#: ../../TShockAPI/Commands.cs:6051
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -553,7 +553,7 @@ msgstr "{0}已将你所属的用户组更改为{1}。"
|
||||||
#: ../../TShockAPI/Commands.cs:3026
|
#: ../../TShockAPI/Commands.cs:3026
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} has disabled incoming teleports."
|
msgid "{0} has disabled incoming teleports."
|
||||||
msgstr "{0} 禁止玩家对其使用传送"
|
msgstr "{0} 禁止玩家对其使用传送。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2412
|
#: ../../TShockAPI/Commands.cs:2412
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -608,22 +608,22 @@ msgstr "{0} 已将你复活。"
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:3555
|
#: ../../TShockAPI/GetDataHandlers.cs:3555
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} has sent a request to the bunny delivery service!"
|
msgid "{0} has sent a request to the bunny delivery service!"
|
||||||
msgstr "{0}联系了兔兔运送服务站。"
|
msgstr "{0}从递送站申领了新的兔兔!"
|
||||||
|
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:3561
|
#: ../../TShockAPI/GetDataHandlers.cs:3561
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} has sent a request to the cat delivery service!"
|
msgid "{0} has sent a request to the cat delivery service!"
|
||||||
msgstr "{0}联系了猫咪运送服务站。"
|
msgstr "{0}从递送站申领了新的猫猫!"
|
||||||
|
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:3558
|
#: ../../TShockAPI/GetDataHandlers.cs:3558
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} has sent a request to the dog delivery service!"
|
msgid "{0} has sent a request to the dog delivery service!"
|
||||||
msgstr "{0}联系了狗狗运送服务站。"
|
msgstr "{0}从递送站申领了新的狗狗!"
|
||||||
|
|
||||||
#: ../../TShockAPI/GetDataHandlers.cs:3552
|
#: ../../TShockAPI/GetDataHandlers.cs:3552
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} has sent a request to the slime delivery service!"
|
msgid "{0} has sent a request to the slime delivery service!"
|
||||||
msgstr "{0}联系了史莱姆运送服务站。"
|
msgstr "{0}已向史莱姆递送服务发送请求!"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2878
|
#: ../../TShockAPI/Commands.cs:2878
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -684,7 +684,7 @@ msgstr "{0}为他自己恢复了{1}血量。"
|
||||||
#: ../../TShockAPI/Commands.cs:4250
|
#: ../../TShockAPI/Commands.cs:4250
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} is already allowed to place tile {1}."
|
msgid "{0} is already allowed to place tile {1}."
|
||||||
msgstr "{0} 已被允许放置方块 {1}。"
|
msgstr "{0} 已被允许放置图格 {1}。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:3885
|
#: ../../TShockAPI/Commands.cs:3885
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -719,12 +719,12 @@ msgstr "{0} 已被禁止使用射弹 {1}。"
|
||||||
#: ../../TShockAPI/ItemBans.cs:234
|
#: ../../TShockAPI/ItemBans.cs:234
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} is banned! Remove it!"
|
msgid "{0} is banned! Remove it!"
|
||||||
msgstr "{0} 已被封禁!请删除它!"
|
msgstr "{0} 已被禁用!请移除它!"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:6751
|
#: ../../TShockAPI/Commands.cs:6751
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "{0} is no longer in god mode."
|
msgid "{0} is no longer in god mode."
|
||||||
msgstr "已关闭{0}的无敌模式。"
|
msgstr "已关闭{0}的上帝模式。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:5546
|
#: ../../TShockAPI/Commands.cs:5546
|
||||||
#: ../../TShockAPI/Commands.cs:5577
|
#: ../../TShockAPI/Commands.cs:5577
|
||||||
|
|
@ -1253,7 +1253,7 @@ msgstr "成功移除账号。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2094
|
#: ../../TShockAPI/Commands.cs:2094
|
||||||
msgid "Active REST Users ({{0}}/{{1}}):"
|
msgid "Active REST Users ({{0}}/{{1}}):"
|
||||||
msgstr "活跃REST用户({{0}}/{{1}}):"
|
msgstr "有效的临时REST用户({{0}}/{{1}}):"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:3971
|
#: ../../TShockAPI/Commands.cs:3971
|
||||||
msgid "add <item> - Adds an item ban."
|
msgid "add <item> - Adds an item ban."
|
||||||
|
|
@ -1307,7 +1307,7 @@ msgstr "{0}{1}的别名:{0}{2}"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:6013
|
#: ../../TShockAPI/Commands.cs:6013
|
||||||
msgid "All alive NPCs (excluding town NPCs) on the server will be killed if you do not input a name or ID."
|
msgid "All alive NPCs (excluding town NPCs) on the server will be killed if you do not input a name or ID."
|
||||||
msgstr "输入名称或序号可以消灭特定NPC,否则将默认消灭所有非城镇NPC。"
|
msgstr "输入NPC名称或ID可以杀死特定NPC,否则将默认杀死所有非城镇NPC。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2626
|
#: ../../TShockAPI/Commands.cs:2626
|
||||||
msgid "all bosses"
|
msgid "all bosses"
|
||||||
|
|
@ -1315,7 +1315,7 @@ msgstr "所有boss"
|
||||||
|
|
||||||
#: ../../TShockPluginManager/NugetCLI.cs:169
|
#: ../../TShockPluginManager/NugetCLI.cs:169
|
||||||
msgid "All done! :)"
|
msgid "All done! :)"
|
||||||
msgstr "下载完毕!"
|
msgstr "下载完毕!: )"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2104
|
#: ../../TShockAPI/Commands.cs:2104
|
||||||
msgid "All REST tokens have been destroyed."
|
msgid "All REST tokens have been destroyed."
|
||||||
|
|
@ -1328,15 +1328,15 @@ msgstr "已分配内存: {0}"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:3972
|
#: ../../TShockAPI/Commands.cs:3972
|
||||||
msgid "allow <item> <group> - Allows a group to use an item."
|
msgid "allow <item> <group> - Allows a group to use an item."
|
||||||
msgstr "allow <物品> <组名> - 允许指定组使用被禁用的物品"
|
msgstr "allow <物品> <用户组> - 给予用户组使用特定物品的豁免权。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:4150
|
#: ../../TShockAPI/Commands.cs:4150
|
||||||
msgid "allow <projectile ID> <group> - Allows a group to use a projectile."
|
msgid "allow <projectile ID> <group> - Allows a group to use a projectile."
|
||||||
msgstr "allow <射弹> <用户组> - 给与用户组使用特定射弹的豁免权。"
|
msgstr "allow <射弹> <用户组> - 给予用户组使用特定射弹的豁免权。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:4326
|
#: ../../TShockAPI/Commands.cs:4326
|
||||||
msgid "allow <tile ID> <group> - Allows a group to place a tile."
|
msgid "allow <tile ID> <group> - Allows a group to place a tile."
|
||||||
msgstr "allow <物块> <用户组> - 给与用户组使用特定物块的豁免权。"
|
msgstr "allow <物块> <用户组> - 给予用户组使用特定物块的豁免权。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:5193
|
#: ../../TShockAPI/Commands.cs:5193
|
||||||
msgid "allow <user> <region> - Allows a user to a region."
|
msgid "allow <user> <region> - Allows a user to a region."
|
||||||
|
|
@ -1374,20 +1374,20 @@ msgstr "执行指令时发生了异常。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/BanManager.cs:644
|
#: ../../TShockAPI/DB/BanManager.cs:644
|
||||||
msgid "An identifier for a character name."
|
msgid "An identifier for a character name."
|
||||||
msgstr "角色名字的标识。"
|
msgstr "可以匹配游戏内的角色名。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/BanManager.cs:648
|
#: ../../TShockAPI/DB/BanManager.cs:648
|
||||||
msgid "An identifier for a TShock User Account name."
|
msgid "An identifier for a TShock User Account name."
|
||||||
msgstr "一个TShock用户名的标识符。"
|
msgstr "可以匹配TShock用户名。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/BanManager.cs:640
|
#: ../../TShockAPI/DB/BanManager.cs:640
|
||||||
msgid "An identifier for a UUID."
|
msgid "An identifier for a UUID."
|
||||||
msgstr "UUID的标识。"
|
msgstr "可以匹配UUID。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/BanManager.cs:636
|
#: ../../TShockAPI/DB/BanManager.cs:636
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "An identifier for an IP Address in octet format. e.g., '{0}'."
|
msgid "An identifier for an IP Address in octet format. e.g., '{0}'."
|
||||||
msgstr "用句点分隔的十进制格式的IP地址,例如{0}。"
|
msgstr "可以匹配IP地址,格式为用句点分隔的十进制,例如{0}。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2052
|
#: ../../TShockAPI/Commands.cs:2052
|
||||||
msgid "An update check has been queued. If an update is available, you will be notified shortly."
|
msgid "An update check has been queued. If an update is available, you will be notified shortly."
|
||||||
|
|
@ -1446,7 +1446,7 @@ msgstr "自动存档已开启。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Rest/RestManager.cs:811
|
#: ../../TShockAPI/Rest/RestManager.cs:811
|
||||||
msgid "AutoSave has been disabled"
|
msgid "AutoSave has been disabled"
|
||||||
msgstr "自动存档已关闭"
|
msgstr "自动保存已关闭"
|
||||||
|
|
||||||
#: ../../TShockAPI/Rest/RestManager.cs:807
|
#: ../../TShockAPI/Rest/RestManager.cs:807
|
||||||
msgid "AutoSave has been enabled"
|
msgid "AutoSave has been enabled"
|
||||||
|
|
@ -1466,7 +1466,7 @@ msgstr "可用Ban指令:"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1432
|
#: ../../TShockAPI/Commands.cs:1432
|
||||||
msgid "Available identifiers ({{0}}/{{1}}):"
|
msgid "Available identifiers ({{0}}/{{1}}):"
|
||||||
msgstr "可用的标识符 ({{0}}/{{1}}):"
|
msgstr "可选的匹配代码 ({{0}}/{{1}}):"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:5208
|
#: ../../TShockAPI/Commands.cs:5208
|
||||||
msgid "Available Region Sub-Commands ({{0}}/{{1}}):"
|
msgid "Available Region Sub-Commands ({{0}}/{{1}}):"
|
||||||
|
|
@ -1474,7 +1474,7 @@ msgstr "可用的区域子命令 ({{0}}/{{1}}):"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:2109
|
#: ../../TShockAPI/Commands.cs:2109
|
||||||
msgid "Available REST Sub-Commands:"
|
msgid "Available REST Sub-Commands:"
|
||||||
msgstr "Rest命令使用帮助:"
|
msgstr "REST命令使用帮助:"
|
||||||
|
|
||||||
#: ../../TShockAPI/BackupManager.cs:75
|
#: ../../TShockAPI/BackupManager.cs:75
|
||||||
msgid "Backing up world..."
|
msgid "Backing up world..."
|
||||||
|
|
@ -1684,7 +1684,7 @@ msgstr "Bouncer / OnFishOutNPC(钓出NPC防护)因没有召唤Boss的权限
|
||||||
#: ../../TShockAPI/Bouncer.cs:2781
|
#: ../../TShockAPI/Bouncer.cs:2781
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Bouncer / OnFoodPlatterTryPlacing rejected disabled from {0}"
|
msgid "Bouncer / OnFoodPlatterTryPlacing rejected disabled from {0}"
|
||||||
msgstr "Bouncer / OnFoodPlatterTryPlacing(放置食物防护)因玩家被拘束阻止了{0}"
|
msgstr "Bouncer / OnFoodPlatterTryPlacing(放置食物防护)因玩家被限制行动而阻止了{0}"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:2774
|
#: ../../TShockAPI/Bouncer.cs:2774
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -1997,7 +1997,7 @@ msgstr "Bouncer / OnPlaceChest(宝箱放置防护)因超出范围而阻止
|
||||||
#: ../../TShockAPI/Bouncer.cs:1562
|
#: ../../TShockAPI/Bouncer.cs:1562
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Bouncer / OnPlaceChest rejected from weird check from {0}"
|
msgid "Bouncer / OnPlaceChest rejected from weird check from {0}"
|
||||||
msgstr "Bouncer / OnPlaceChest 拒绝了来自 {0} 的怪物的检查"
|
msgstr "Bouncer / OnPlaceChest 拒绝了来自 {0} 的奇怪的检查"
|
||||||
|
|
||||||
#: ../../TShockAPI/Bouncer.cs:1573
|
#: ../../TShockAPI/Bouncer.cs:1573
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -2998,7 +2998,7 @@ msgstr "检测到恶意攻击"
|
||||||
#: ../../TShockAPI/Commands.cs:1494
|
#: ../../TShockAPI/Commands.cs:1494
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Failed to add ban for identifier: {0}."
|
msgid "Failed to add ban for identifier: {0}."
|
||||||
msgstr "无法给{0}添加封禁标识符"
|
msgstr "无法添加封禁(匹配代码{0})。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Rest/RestManager.cs:671
|
#: ../../TShockAPI/Rest/RestManager.cs:671
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -3515,7 +3515,7 @@ msgstr "用户组{1}为{0}的父组,但也同时是它的子组。已删除此
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/GroupManager.cs:578
|
#: ../../TShockAPI/DB/GroupManager.cs:578
|
||||||
msgid "Group \"superadmin\" is defined in the database even though it's a reserved group name."
|
msgid "Group \"superadmin\" is defined in the database even though it's a reserved group name."
|
||||||
msgstr "组 ”superadmin”(超级管理员)已存在于数据库中,即使这是一个保留的组名。"
|
msgstr "数据库中存在superadmin组,但它已被预留,不应存在于数据库中。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/GroupManager.cs:708
|
#: ../../TShockAPI/DB/GroupManager.cs:708
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
|
|
@ -3573,7 +3573,7 @@ msgstr "用户组{0}的父组为{1},但该用户组不存在。已删除此父
|
||||||
#: ../../TShockAPI/DB/GroupManager.cs:637
|
#: ../../TShockAPI/DB/GroupManager.cs:637
|
||||||
#, csharp-format
|
#, csharp-format
|
||||||
msgid "Group {0} is referencing itself as parent group; parent reference was removed."
|
msgid "Group {0} is referencing itself as parent group; parent reference was removed."
|
||||||
msgstr "组{0}试图将自己作为父组。父组的引用已被删除。"
|
msgstr "用户组{0}的父组为它自己。已删除此父子关系。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:4862
|
#: ../../TShockAPI/Commands.cs:4862
|
||||||
#: ../../TShockAPI/Commands.cs:4897
|
#: ../../TShockAPI/Commands.cs:4897
|
||||||
|
|
@ -5849,7 +5849,7 @@ msgstr "此用户组不存在。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/BanManager.cs:258
|
#: ../../TShockAPI/DB/BanManager.cs:258
|
||||||
msgid "The ban is invalid because a current ban for this identifier already exists."
|
msgid "The ban is invalid because a current ban for this identifier already exists."
|
||||||
msgstr "禁令无效,因为当前禁止此标识符的禁令已经存在。"
|
msgstr "目前已经封禁了符合这个匹配代码的玩家,无法再次封禁。"
|
||||||
|
|
||||||
#: ../../TShockAPI/DB/BanManager.cs:295
|
#: ../../TShockAPI/DB/BanManager.cs:295
|
||||||
msgid "The ban was not valid for an unknown reason."
|
msgid "The ban was not valid for an unknown reason."
|
||||||
|
|
@ -5986,7 +5986,7 @@ msgstr "史莱姆皇后"
|
||||||
|
|
||||||
#: ../../TShockAPI/Rest/RestManager.cs:158
|
#: ../../TShockAPI/Rest/RestManager.cs:158
|
||||||
msgid "The REST authentication token."
|
msgid "The REST authentication token."
|
||||||
msgstr "REST 身份验证令牌。"
|
msgstr "REST 授权令牌"
|
||||||
|
|
||||||
#: ../../TShockAPI/UpdateManager.cs:150
|
#: ../../TShockAPI/UpdateManager.cs:150
|
||||||
msgid "The server is out of date. Latest version: "
|
msgid "The server is out of date. Latest version: "
|
||||||
|
|
@ -6047,7 +6047,7 @@ msgstr "当前没有任何有效的临时REST用户。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:1434
|
#: ../../TShockAPI/Commands.cs:1434
|
||||||
msgid "There are currently no available identifiers."
|
msgid "There are currently no available identifiers."
|
||||||
msgstr "目前没有可用的匹配代码。"
|
msgstr "目前没有可选的匹配代码。"
|
||||||
|
|
||||||
#: ../../TShockAPI/Commands.cs:4001
|
#: ../../TShockAPI/Commands.cs:4001
|
||||||
msgid "There are currently no banned items."
|
msgid "There are currently no banned items."
|
||||||
|
|
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue