Skip to content

Commit ce60e1c

Browse files
Updte
2 parents fa0c7bd + 3982e73 commit ce60e1c

File tree

9 files changed

+451
-0
lines changed

9 files changed

+451
-0
lines changed

GolfRewards/ConfigFile.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using Newtonsoft.Json;
5+
6+
namespace RewardSection
7+
{
8+
public class ConfigFile
9+
{
10+
public static ConfigFile Read(string path)
11+
{
12+
if (!File.Exists(path))
13+
{
14+
return new ConfigFile
15+
{
16+
RewardTable = new List<RewardSection>
17+
{
18+
new RewardSection(0, 0, new List<ItemSections> { new ItemSections(757, 1, 0) }, new List<string> { "/time noon" }),
19+
new RewardSection(0, 0, new List<ItemSections> { new ItemSections(757, 1, 0) }, new List<string> { "/time night" })
20+
}
21+
};
22+
}
23+
24+
using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
25+
using (var streamReader = new StreamReader(fileStream))
26+
{
27+
var configFile = JsonConvert.DeserializeObject<ConfigFile>(streamReader.ReadToEnd());
28+
ConfigR?.Invoke(configFile);
29+
return configFile;
30+
}
31+
}
32+
33+
public static ConfigFile Read(Stream stream)
34+
{
35+
using (var streamReader = new StreamReader(stream))
36+
{
37+
var configFile = JsonConvert.DeserializeObject<ConfigFile>(streamReader.ReadToEnd());
38+
ConfigR?.Invoke(configFile);
39+
return configFile;
40+
}
41+
}
42+
43+
public void Write(string path)
44+
{
45+
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write))
46+
{
47+
Write(fileStream);
48+
}
49+
}
50+
51+
public void Write(Stream stream)
52+
{
53+
var value = JsonConvert.SerializeObject(this, Formatting.Indented);
54+
using (var streamWriter = new StreamWriter(stream))
55+
{
56+
streamWriter.Write(value);
57+
}
58+
}
59+
60+
[JsonProperty("奖励表")]
61+
public List<RewardSection> RewardTable { get; set; } = new List<RewardSection>();
62+
63+
public static Action<ConfigFile> ConfigR;
64+
}
65+
}

GolfRewards/GolfRewards.cs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
using Terraria;
2+
using TerrariaApi.Server;
3+
using TShockAPI;
4+
using TShockAPI.Hooks;
5+
6+
namespace RewardSection
7+
{
8+
[ApiVersion(2, 1)]
9+
public class GolfRewards : TerrariaPlugin
10+
{
11+
public override string Name => "高尔夫奖励";
12+
public override string Author => "GK 阁下 由 鸽子 定制,肝帝熙恩更新适配1449";
13+
public override string Description => "将高尔夫打入球洞会得到奖励.";
14+
public override Version Version => new Version(1, 0, 5);
15+
16+
public GolfRewards(Main game) : base(game)
17+
{
18+
base.Order = 5;
19+
LC.RI();
20+
}
21+
22+
private void OnInitialize(EventArgs args)
23+
{
24+
GeneralHooks.ReloadEvent += CMD;
25+
LC.RC();
26+
27+
Commands.ChatCommands.Add(new Command("物块坐标", CMD2, "物块坐标")
28+
{
29+
HelpText = "输入/物块坐标后敲击物块确认坐标"
30+
});
31+
}
32+
33+
34+
public override void Initialize()
35+
{
36+
GeneralHooks.ReloadEvent -= CMD;
37+
ServerApi.Hooks.NetGetData.Register(this, GetData);
38+
39+
ServerApi.Hooks.GameInitialize.Register(this, OnInitialize);
40+
41+
ServerApi.Hooks.NetGreetPlayer.Register(this, OnGreetPlayer);
42+
43+
ServerApi.Hooks.ServerLeave.Register(this, OnLeave);
44+
45+
GetDataHandlers.TileEdit += TileEdit;
46+
47+
GetDataHandlers.LandGolfBallInCup += Golf;
48+
}
49+
50+
51+
protected override void Dispose(bool disposing)
52+
{
53+
if (disposing)
54+
{
55+
ServerApi.Hooks.NetGetData.Deregister(this, GetData);
56+
57+
ServerApi.Hooks.GameInitialize.Deregister(this, OnInitialize);
58+
59+
ServerApi.Hooks.NetGreetPlayer.Deregister(this, OnGreetPlayer);
60+
61+
ServerApi.Hooks.ServerLeave.Deregister(this, OnLeave);
62+
63+
GetDataHandlers.TileEdit -= TileEdit;
64+
65+
GetDataHandlers.LandGolfBallInCup -= Golf;
66+
}
67+
base.Dispose(disposing);
68+
}
69+
70+
71+
private void CMD(ReloadEventArgs args)
72+
{
73+
LC.RC();
74+
args.Player.SendSuccessMessage("[高尔夫奖励] 重读配置完毕!");
75+
}
76+
77+
private void CMD2(CommandArgs args)
78+
{
79+
if (LC.LPlayers.TryGetValue(args.Player.Index, out LPlayer player) && player != null)
80+
{
81+
player.tip = true;
82+
}
83+
args.Player.SendSuccessMessage("敲击物块以确认其坐标!");
84+
}
85+
86+
private void OnGreetPlayer(GreetPlayerEventArgs e)
87+
{
88+
LC.LPlayers.AddOrUpdate(e.Who, new LPlayer(e.Who), (_, existingPlayer) => existingPlayer);
89+
}
90+
91+
private void OnLeave(LeaveEventArgs e)
92+
{
93+
LC.LPlayers.TryRemove(e.Who, out _);
94+
}
95+
96+
private void TileEdit(object sender, GetDataHandlers.TileEditEventArgs args)
97+
{
98+
if (args.Handled)
99+
return;
100+
101+
TSPlayer tsplayer = TShock.Players[args.Player.Index];
102+
if (tsplayer == null)
103+
return;
104+
105+
if (LC.LPlayers.TryGetValue(args.Player.Index, out LPlayer player) && player != null && player.tip)
106+
{
107+
player.tip = false;
108+
tsplayer.SendInfoMessage($"目标坐标为: X{args.X} Y{args.Y}");
109+
}
110+
}
111+
112+
113+
public void Golf(object sender, GetDataHandlers.LandGolfBallInCupEventArgs args)
114+
{
115+
if (args.Handled)
116+
return;
117+
118+
var player = args.Player;
119+
if (player == null)
120+
return;
121+
122+
int tileX = args.TileX;
123+
int tileY = args.TileY;
124+
int hits = args.Hits;
125+
126+
foreach (var RewardSection in LC.LConfig.RewardTable)
127+
{
128+
if (RewardSection.HolePositionX != tileX || RewardSection.HolePositionY != tileY)
129+
continue;
130+
131+
if (hits <= RewardSection.MinSwings || hits > RewardSection.MaxSwings)
132+
continue;
133+
134+
if (!string.IsNullOrEmpty(RewardSection.HitPrompt))
135+
TShock.Utils.Broadcast(RewardSection.HitPrompt, byte.MaxValue, 215, 0);
136+
137+
var randomItems = RewardSection.GetRandomItems();
138+
if (randomItems != null && randomItems.ItemId != 0 && randomItems.ItemStack > 0)
139+
player.GiveItem(randomItems.ItemId, randomItems.ItemStack, randomItems.ItemPrefix);
140+
141+
var randomCMD = RewardSection.GetRandomCMD();
142+
if (!string.IsNullOrEmpty(randomCMD))
143+
{
144+
bool cmdSuccess = Commands.HandleCommand(TSPlayer.Server, randomCMD.Replace("{name}", player.Name));
145+
if (!cmdSuccess)
146+
Console.WriteLine($"指令 {randomCMD} 执行失败! ");
147+
}
148+
149+
if (RewardSection.OnlyClaimRewardAtThisLocation)
150+
break;
151+
}
152+
}
153+
154+
private void GetData(GetDataEventArgs args)
155+
{
156+
}
157+
}
158+
}

GolfRewards/GolfRewards.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<Import Project="..\template.targets" />
4+
5+
</Project>

GolfRewards/ItemSections.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
4+
namespace RewardSection
5+
{
6+
public class ItemSections
7+
{
8+
[JsonProperty("物品ID")]
9+
public int ItemId { get; set; }
10+
11+
[JsonProperty("物品数量")]
12+
public int ItemStack { get; set; }
13+
14+
public ItemSections(int id, int stack, int prefix)
15+
{
16+
ItemId = id;
17+
ItemStack = stack;
18+
ItemPrefix = prefix;
19+
}
20+
21+
[JsonProperty("相对概率")]
22+
public int RelativeProbability { get; set; } = 1;
23+
24+
[JsonProperty("物品前缀")]
25+
public int ItemPrefix { get; set; } = 0;
26+
}
27+
}

GolfRewards/LC.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.IO;
4+
using TShockAPI;
5+
6+
namespace RewardSection
7+
{
8+
internal class LC
9+
{
10+
public static ConfigFile LConfig { get; set; }
11+
internal static string LConfigPath => Path.Combine(TShock.SavePath, "高尔夫奖励.json");
12+
public static ConcurrentDictionary<int, LPlayer> LPlayers { get; set; }
13+
public static Random LRadom = new Random();
14+
15+
public static void RI()
16+
{
17+
LConfig = new ConfigFile();
18+
// 初始化 LPlayers 为 ConcurrentDictionary
19+
LPlayers = new ConcurrentDictionary<int, LPlayer>();
20+
}
21+
22+
public static void RC()
23+
{
24+
try
25+
{
26+
if (!File.Exists(LConfigPath))
27+
{
28+
TShock.Log.ConsoleError("未找到高尔夫奖励配置文件,已为您创建!");
29+
}
30+
LConfig = ConfigFile.Read(LConfigPath);
31+
LConfig.Write(LConfigPath);
32+
}
33+
catch (Exception ex)
34+
{
35+
TShock.Log.ConsoleError("高尔夫奖励插件错误配置读取错误:" + ex.ToString());
36+
}
37+
}
38+
}
39+
}

GolfRewards/LPlayer.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace RewardSection
4+
{
5+
public class LPlayer
6+
{
7+
public int Index { get; set; }
8+
public bool tip { get; set; }
9+
10+
public LPlayer(int index)
11+
{
12+
this.Index = index;
13+
this.tip = false;
14+
}
15+
}
16+
}

GolfRewards/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# GolfRewards 高尔夫奖励
2+
3+
- 作者: GK 阁下 由 鸽子 定制,肝帝熙恩更新适配1449
4+
- 出处: TShock中文官方群
5+
- 玩家在高尔夫球洞中击球,根据击球次数(杆数)获得相应的奖励。
6+
- 插件支持自定义奖励表,包括物品奖励和执行的命令。
7+
8+
## 更新日志
9+
10+
```
11+
暂无
12+
```
13+
14+
## 指令
15+
16+
| 语法 | 权限 | 说明 |
17+
| -------------- | :-----------------: | :------: |
18+
| /物块坐标 | 物块坐标 | 辅助指令,确定方块坐标|
19+
20+
## 配置
21+
22+
每个奖励节点(`奖励节`)包含以下属性:
23+
24+
- `球洞坐标X`:球洞在X轴上的坐标。
25+
- `球洞坐标Y`:球洞在Y轴上的坐标。
26+
- `最少杆数`:玩家击球进入球洞所需的最少杆数。
27+
- `最多杆数`:玩家击球进入球洞所需的最多杆数。
28+
- `本位置仅领取该奖励`:如果为`true`,则玩家在该位置只能领取一次奖励。
29+
- `物品节`:一个列表,包含了玩家可以获得的物品奖励。每个物品奖励包含物品ID、数量和物品前缀。
30+
- `指令节`:一个列表,包含了玩家击球成功后可能执行的命令。
31+
32+
```json
33+
{
34+
"奖励表": [
35+
{
36+
"球洞坐标X": 0,
37+
"球洞坐标Y": 0,
38+
"最少杆数": 0,
39+
"最多杆数": 999,
40+
"本位置仅领取该奖励": false,
41+
"物品节": [
42+
{
43+
"物品ID": 757, // 物品的ID,例如757是泰拉刀
44+
"物品数量": 1, // 物品的数量
45+
"物品前缀": 0 // 物品的前缀,0表示无前缀
46+
}
47+
],
48+
"指令节": [
49+
"/time noon", // 执行的命令,例如设置游戏时间为中午
50+
"/time night" // 另一个可能的命令,设置游戏时间为夜晚
51+
],
52+
"命中提示": "高尔夫击中奖励球" // 玩家击球成功后的提示信息
53+
}
54+
]
55+
}
56+
```
57+
## 反馈
58+
- 共同维护的插件库:https://github.com/THEXN/TShockPlugin/
59+
- 国内社区trhub.cn 或 TShock官方群等

0 commit comments

Comments
 (0)