-
Notifications
You must be signed in to change notification settings - Fork 0
/
ModEvents.cs
205 lines (167 loc) · 7.44 KB
/
ModEvents.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
using Microsoft.Xna.Framework;
using SPYoyoMod.Core;
using SPYoyoMod.Core.Netcode;
using SPYoyoMod.Utils;
using System;
using System.IO;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace SPYoyoMod
{
[LoadPriority(sbyte.MaxValue)]
public sealed class ModEvents : ILoadable
{
// Mod
/// <summary>
/// Позволяет обрабатывать рецепты после их настройки. Не следует редактировать какой-либо рецепт.
/// </summary>
public static event Action<Recipe[]> OnPostSetupRecipes;
/// <summary>
/// Позволяет загружать вещи после того, как мод подготовил весь свой контент.
/// </summary>
public static event Action OnPostSetupContent;
/// <summary>
/// Вызывается всякий раз, как игрок подключается к игре; Вызов происходит для всех, как для клиентов, так и для сервера.
/// </summary>
public static event Action<Player> OnPlayerConnect;
/// <summary>
/// Вызывается при выгрузке мира.
/// </summary>
public static event Action OnWorldUnload;
/// <summary>
/// Вызывается перед тем, как пыль будет обновлена.
/// </summary>
public static event Action OnPreUpdateDusts;
/// <summary>
/// Вызывается после того, как Network был обновлен. Это событие является последним из всех, что вызываются при обновлении игры.
/// </summary>
public static event Action OnPostUpdateEverything;
/// <summary>
/// Вызывается после обновления позиции камеры. Полезен для отрисовки на целях рендеринга.
/// </summary>
public static event Action OnPostUpdateCameraPosition;
/// <summary>
/// Вызывается при изменении разрешения экрана.
/// </summary>
public static event Action<Point> OnResolutionChanged;
// Vanilla
/// <summary>
/// Вызывается перед началом отрисовки игры.
/// </summary>
public static event Action OnPreDraw;
void ILoadable.Load(Mod mod)
{
LoadModEvents();
LoadVanillaEvents();
}
void ILoadable.Unload()
{
UnloadVanillaEvents();
UnloadModEvents();
}
private static void LoadModEvents()
{
OnPostSetupRecipes += ModUtils.EmptyAction;
OnPostSetupContent += ModUtils.EmptyAction;
OnWorldUnload += ModUtils.EmptyAction;
OnPreUpdateDusts += ModUtils.EmptyAction;
OnPostUpdateEverything += ModUtils.EmptyAction;
OnPostUpdateCameraPosition += ModUtils.EmptyAction;
OnResolutionChanged += ModUtils.EmptyAction;
On_Main.DoDraw_UpdateCameraPosition += (orig) =>
{
orig();
OnPostUpdateCameraPosition();
};
}
private static void UnloadModEvents()
{
OnResolutionChanged = null;
OnPostUpdateCameraPosition = null;
OnPostUpdateEverything = null;
OnPreUpdateDusts = null;
OnWorldUnload = null;
OnPostSetupContent = null;
OnPostSetupRecipes = null;
}
private static void LoadVanillaEvents()
{
OnPreDraw += ModUtils.EmptyAction;
Main.OnPreDraw += ModOnPreDraw;
}
private static void UnloadVanillaEvents()
{
Main.OnPreDraw -= ModOnPreDraw;
OnPreDraw = null;
}
private static void ModOnPreDraw(GameTime _)
=> ModEvents.OnPreDraw();
[LoadPriority(sbyte.MaxValue)]
private sealed class EventSystem : ModSystem
{
private Point _savedScreenSize;
private bool _savedGameInactive;
public override void Load()
{
// - Почему не используется только ванильный Main.OnResolutionChanged?
// При загрузке мода с разрешением происходят какиет проблемы,
// а вызова OnResolutionChanged не происходит.
// Данный способ хоть и добавляет дополнительную постоянную проверку,
// но гарантирует, что размер экрана действительно был изменен.
ModEvents.OnPreDraw += () => ResolutionChangedHandler(Main.ScreenSize.ToVector2());
Main.OnResolutionChanged += ResolutionChangedHandler;
}
public override void Unload()
=> Main.OnResolutionChanged -= ResolutionChangedHandler;
public override void PostAddRecipes()
=> ModEvents.OnPostSetupRecipes(Main.recipe);
public override void PostSetupContent()
=> ModEvents.OnPostSetupContent();
public override void OnWorldLoad()
{
// Костыль, без которого не обойтись...
ModEvents.OnResolutionChanged(Main.ScreenSize);
}
public override void OnWorldUnload()
=> ModEvents.OnWorldUnload();
public override void PreUpdateDusts()
=> ModEvents.OnPreUpdateDusts();
public override void PostUpdateEverything()
=> ModEvents.OnPostUpdateEverything();
private void ResolutionChangedHandler(Vector2 screenSize)
{
if (_savedScreenSize != Main.ScreenSize || _savedGameInactive != Main.gameInactive)
{
_savedScreenSize = Main.ScreenSize;
_savedGameInactive = Main.gameInactive;
ModEvents.OnResolutionChanged(Main.ScreenSize);
}
}
}
private sealed class PlayerConnectPacket : NetPacket
{
public override void Send(BinaryWriter writer, params object[] context)
{
writer.Write((byte)context[0]); //< connectedPlayerIndex
}
public override void Receive(BinaryReader reader, int sender)
{
var connectedPlayerIndex = reader.ReadByte();
ModEvents.OnPlayerConnect(Main.player[connectedPlayerIndex]);
if (Main.netMode == NetmodeID.Server)
NetHandler.Send<PlayerConnectPacket>(null, sender, connectedPlayerIndex);
}
}
[LoadPriority(sbyte.MaxValue)]
private sealed class EventPlayer : ModPlayer
{
public override void PlayerConnect()
{
var connectedPlayerIndex = (byte)Main.myPlayer;
ModEvents.OnPlayerConnect(Main.player[connectedPlayerIndex]);
NetHandler.Send<PlayerConnectPacket>(null, null, connectedPlayerIndex);
}
}
}
}