关于30HB服务器激活码的实现
前言:
私服的运营并不被官方认可,因此应该保持低调。然而,有些人为了谋取利益,不顾一切地公开贩卖私服,这种行为虽然这些私服可能会带来短暂的高人气,但长期来看,它们加速了服务器的关闭,对游戏的稳定性和持久性造成了负面影响。而且对于玩家来说,本来是免费的东西,却被收取了高额的费用,这无疑是对玩家利益和游戏体验的损害。我们应当持批判态度并加强打击力度,避免玩家陷入利益陷阱和风险损失之中。
我们也想了很多办法,踢也踢了,骂也骂了,但效果甚微。倒卖依旧我行我素,你骂他坏,他笑你蠢,你拿他没办法。
这些方法可以说是亡羊补牢,治标不治本,无法从根本上解决问题。所以得从源头上寻找解决办法。
这篇文章通过激活码的方式,尝试限制倒卖行为的发展。通过为每个玩家提供独特的激活码,能够追踪和管理玩家的账号行为,确保私服资源的正规使用和限制倒卖行为的传播。这种方法能够从源头上遏制问题,为游戏的稳定性和持久性提供保障。
正文:
怎么启用激活码?
在命令类(HB_CheatMessage)内的账号找回命令(/findacc),可以看到该命令把AccountRetrieving设置为true了。然后报错后重进后就来的了输入解锁码界面。很明显,这个界面就是我们需要的。
既然是登陆后弹出的,我们来的登陆认证类(Authentication)。可以找到
if (this.player_level.Avatar.AccountRetrieving)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 13
}.Send();
return;
}
很明显,这个代码就是我们需要的,启用激活码功能。
怎么改激活码功能?
首先我们先确定我们需要什么功能:
1、新号需要输入激活码才能通过验证
2、老号无需激活码直接通过验证。
3、保留找回账号功能
下面是我的代码:
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using UCS.Core;
using UCS.Core.Network;
using UCS.Helpers;
using UCS.Helpers.Binary;
using UCS.Logic;
using UCS.Logic.Enums;
using UCS.Packets.Messages.Server;
using UCS.Utilities.Sodium;
namespace UCS.Packets.Messages.Client
{
// Token: 0x020000D9 RID: 217
internal class UnlockAccountMessage : Message
{
// Token: 0x06000457 RID: 1111 RVA: 0x000308C0 File Offset: 0x0002EAC0
public UnlockAccountMessage(Device device, Reader reader) : base(device, reader)
{
try
{
this.Device.PlayerState = State.LOGGED;
}
catch (Exception ex)
{
Console.WriteLine("在设置玩家状态时出现错误: " + ex.Message);
}
}
// Token: 0x06000458 RID: 1112 RVA: 0x0003090C File Offset: 0x0002EB0C
internal override void Decrypt()
{
try
{
this.Device.Keys.SNonce.Increment(2);
byte[] array = Sodium.Decrypt(new byte[16].Concat(this.Reader.ReadBytes(this.Length)).ToArray<byte>(), this.Device.Keys.SNonce, this.Device.Keys.PublicKey);
if (array != null)
{
this.Reader = new Reader(array);
this.Length = (int)this.Reader.BaseStream.Length;
}
}
catch (Exception ex)
{
Console.WriteLine("解密消息时出现错误: " + ex.Message);
}
}
// Token: 0x06000459 RID: 1113 RVA: 0x000309C8 File Offset: 0x0002EBC8
internal override void Decode()
{
try
{
this.UserID = this.Reader.ReadInt64();
this.UserToken = this.Reader.ReadString();
this.UnlockCode = this.Reader.ReadString();
}
catch (Exception ex)
{
Console.WriteLine("解码消息时出现错误: " + ex.Message);
}
}
// Token: 0x0600045A RID: 1114 RVA: 0x00030A34 File Offset: 0x0002EC34
internal override void Process()
{
if (this.UserID > 0L && !(this.UserToken == string.Empty) && this.UserID <= ObjectManager.m_vAvatarSeed && ResourcesManager.GetPlayer(this.UserID, "testtesttoken").Avatar.AccountRetrieving)
{
Logger.WriteDebug(string.Format("UserID: {0}", this.UserID));
Logger.WriteDebug("UserToken: " + this.UserToken);
Logger.WriteDebug("UnlockCode: " + this.UnlockCode);
Console.WriteLine(this.UserID + "正在找回账号");
Console.WriteLine("UserToken: " + this.UserToken);
Console.WriteLine("UnlockCode: " + this.UnlockCode);
long userID = this.UserID;
long accountRetrieving_PlayerID = ResourcesManager.GetPlayer(this.UserID, "testtesttoken").Avatar.AccountRetrieving_PlayerID;
Level player = ResourcesManager.GetPlayer(accountRetrieving_PlayerID, "testtesttoken");
if (ResourcesManager.IsPlayerOnline(accountRetrieving_PlayerID))
{
new UnlockAccountFailedMessage(this.Device)
{
ErrorCode = 1
}.Send();
}
else
{
string text = player.Avatar.LastUserToken.Substring(0, 12);
Console.WriteLine(accountRetrieving_PlayerID + "的token: " + text);
while (text.Length < 12)
{
text += "A";
}
if (this.UnlockCode.Equals(text))
{
new UnlockAccountOkMessage(this.Device)
{
UserID = accountRetrieving_PlayerID,
UserToken = player.Avatar.LastUserToken
}.Send();
Console.WriteLine(this.UserID + "成功找回账号");
return;
}
new UnlockAccountFailedMessage(this.Device)
{
ErrorCode = 1
}.Send();
Console.WriteLine(this.UserID + "输入的Token不正确");
}
ResourcesManager.ModifyPlayer(userID, "testtesttoken", delegate(Level p)
{
p.Avatar.AccountRetrieving_PlayerID = 0L;
p.Avatar.AccountRetrieving = false;
});
Console.WriteLine("已为" + this.UserID + "恢复原本id");
return;
}
bool flag = Regex.IsMatch(this.UnlockCode, "^[a-zA-Z]+$");
if (flag)
{
JArray unlockCodeArray = this.GetUnlockCodeArray(this.UnlockCode);
if (this.IsUnlockCodeInArray(unlockCodeArray))
{
goto IL_3BF;
}
}
else
{
if (Regex.IsMatch(this.UnlockCode, "^[0-9]+$"))
{
JArray jarray = this.GetUnlockCode2Array();
if (this.IsUnlockCodeInArray(jarray))
{
jarray = new JArray(from code in jarray
where code.ToString().ToLower() != this.UnlockCode
select code);
Random random = new Random();
string value = new string((from s in Enumerable.Repeat<string>("0123456789", 12)
select s[random.Next(s.Length)]).ToArray<char>());
jarray.Add(value);
this.SaveUnlockCode2Array(jarray);
goto IL_3BF;
}
}
bool flag2 = false;
JArray adminUnlockCodeArray = this.GetAdminUnlockCodeArray();
foreach (JToken jtoken in adminUnlockCodeArray)
{
JObject jobject = (JObject)jtoken;
string value2 = jobject["unlockcode"].ToString();
if (this.UnlockCode.Equals(value2))
{
int num = (int)jobject["count"];
if (num > 0)
{
jobject["count"] = num - 1;
this.SaveAdminUnlockCodeArray(adminUnlockCodeArray);
flag2 = true;
break;
}
}
}
if (flag2)
{
goto IL_3BF;
}
}
new UnlockAccountFailedMessage(this.Device)
{
ErrorCode = 1
}.Send();
return;
IL_3BF:
try
{
JArray jarray2;
if (this.UserID <= 0L || this.UserToken == string.Empty || this.UserID > ObjectManager.m_vAvatarSeed)
{
if (flag)
{
jarray2 = this.GetUnlockCodeArray(this.UnlockCode);
jarray2 = new JArray(from t in jarray2
where t.ToString().ToLower() != this.UnlockCode.ToLower()
select t);
this.SaveUnlockCodeArray(this.UnlockCode, jarray2);
}
this.NewUser();
jarray2 = this.GetUnlockCodeArray(this.UserToken);
jarray2.Add(this.UserToken.Substring(0, 12));
this.SaveUnlockCodeArray(this.UserToken, jarray2);
new UnlockAccountOkMessage(this.Device)
{
UserID = this.UserID,
UserToken = this.UserToken
}.Send();
return;
}
jarray2 = this.GetUnlockCodeArray(this.UserToken);
jarray2.Add(this.UserToken.Substring(0, 12));
this.SaveUnlockCodeArray(this.UserToken, jarray2);
new UnlockAccountOkMessage(this.Device)
{
UserID = this.UserID,
UserToken = this.UserToken
}.Send();
return;
}
catch (Exception ex)
{
Console.WriteLine("处理消息时出现错误: " + ex.Message);
}
new UnlockAccountFailedMessage(this.Device)
{
ErrorCode = 1
}.Send();
}
// Token: 0x0600045B RID: 1115 RVA: 0x00030F94 File Offset: 0x0002F194
private void NewUser()
{
try
{
File.Copy("Gamefiles/starting_pp.json", string.Format("Saves/pp/{0}.json", ObjectManager.m_vAvatarSeed + 1L));
this.player_level = ObjectManager.CreateAvatar;
this.player_level.Avatar.UserID = ObjectManager.m_vAvatarSeed;
this.player_level.Avatar.AvatarName = string.Format("海洋军阀-{0}", this.player_level.Avatar.UserID);
if (string.IsNullOrEmpty(this.UserToken))
{
for (int i = 0; i < 12; i++)
{
char c = (char)Resources.Random.Next(65, 90);
ClientAvatar avatar = this.player_level.Avatar;
avatar.UserToken += c.ToString();
}
}
this.player_level.Avatar.Password = this.player_level.Avatar.UserToken;
this.player_level.Avatar.AccountRetrieving_UnlockCode = true;
this.player_level.Avatar.InitializeAccountCreationDate();
this.UserID = this.player_level.Avatar.UserID;
this.UserToken = this.player_level.Avatar.UserToken;
File.WriteAllText(string.Format("Saves/pp/{0}.json", this.player_level.Avatar.UserID), this.player_level.Avatar.SaveTOJSONHBVer);
}
catch (Exception ex)
{
Console.WriteLine("创建新用户时出现错误: " + ex.Message);
}
}
// Token: 0x0600045C RID: 1116 RVA: 0x00031134 File Offset: 0x0002F334
private bool IsUnlockCodeInArray(JArray qqArray)
{
bool result;
try
{
if (qqArray != null)
{
string lowerCaseUnlockCode = this.UnlockCode.ToLower();
result = qqArray.Any((JToken t) => t.ToString().ToLower() == lowerCaseUnlockCode);
}
else
{
result = false;
}
}
catch (Exception ex)
{
Console.WriteLine("检查解锁码是否在数组中时出现错误: " + ex.Message);
result = false;
}
return result;
}
// Token: 0x0600045D RID: 1117 RVA: 0x000311A0 File Offset: 0x0002F3A0
private JArray GetUnlockCode2Array()
{
JArray result;
try
{
result = (JArray)JObject.Parse(File.ReadAllText("Config/UnlockCode2.json"))["UnlockCode"];
}
catch (Exception ex)
{
Console.WriteLine("读取 UnlockCode2.json 文件时出现错误: " + ex.Message);
result = new JArray();
}
return result;
}
// Token: 0x0600045E RID: 1118 RVA: 0x00031200 File Offset: 0x0002F400
private void SaveUnlockCode2Array(JArray jarray)
{
try
{
JObject jobject = new JObject();
jobject["UnlockCode"] = jarray;
File.WriteAllText("Config/UnlockCode2.json", jobject.ToString());
}
catch (Exception ex)
{
Console.WriteLine("保存 UnlockCode2.json 文件时出现错误: " + ex.Message);
}
}
// Token: 0x0600045F RID: 1119 RVA: 0x0003125C File Offset: 0x0002F45C
private JArray GetAdminUnlockCodeArray()
{
JArray result;
try
{
result = (JArray)JObject.Parse(File.ReadAllText("Config/IsAdminUnlockCode.json"))["UnlockCode"];
}
catch (Exception ex)
{
Console.WriteLine("读取 IsAdminUnlockCode.json 文件时出现错误: " + ex.Message);
result = new JArray();
}
return result;
}
// Token: 0x06000460 RID: 1120 RVA: 0x000312BC File Offset: 0x0002F4BC
private void SaveAdminUnlockCodeArray(JArray jarray)
{
try
{
JObject jobject = new JObject();
jobject["UnlockCode"] = jarray;
File.WriteAllText("Config/IsAdminUnlockCode.json", jobject.ToString());
}
catch (Exception ex)
{
Console.WriteLine("保存 IsAdminUnlockCode.json 文件时出现错误: " + ex.Message);
}
}
// Token: 0x06000463 RID: 1123 RVA: 0x00031318 File Offset: 0x0002F518
private JArray GetUnlockCodeArray(string UnlockCode)
{
JArray result;
try
{
if (!string.IsNullOrEmpty(UnlockCode))
{
char c = char.ToLower(UnlockCode[0]);
string path = string.Format("Config/UnlockCode/{0}.json", c);
if (!File.Exists(path))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(path, "{\"UnlockCode\": []}");
}
result = (JArray)JObject.Parse(File.ReadAllText(path))["UnlockCode"];
}
else
{
result = null;
}
}
catch (Exception ex)
{
Console.WriteLine("读取 UnlockCode 对应字母文件时出现错误: " + ex.Message);
result = null;
}
return result;
}
// Token: 0x06000464 RID: 1124 RVA: 0x000313B8 File Offset: 0x0002F5B8
private void SaveUnlockCodeArray(string UnlockCode, JArray jarray)
{
try
{
if (!string.IsNullOrEmpty(UnlockCode))
{
char c = char.ToLower(UnlockCode[0]);
string path = string.Format("Config/UnlockCode/{0}.json", c);
JObject jobject = new JObject();
jobject["UnlockCode"] = jarray;
File.WriteAllText(path, jobject.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine("保存 UnlockCode 对应字母文件时出现错误: " + ex.Message);
}
}
// Token: 0x04000416 RID: 1046
internal long UserID;
// Token: 0x04000417 RID: 1047
internal string UserToken;
// Token: 0x04000418 RID: 1048
internal string UnlockCode;
// Token: 0x04000419 RID: 1049
public Level player_level;
}
}
我把创建新号功能,移植到了这里。为的是记录当前账号的UserID和UserToken。不然就需要先创建账号,再启用激活码。这样会创建大量无意义的玩家存档,造成资源浪费。
怎么登陆验证?
既然激活码有了,怎么识别哪些号需要使用激活码,哪些号不要使用激活码?
下面是我的登陆认证代码
using System;
using System.IO;
using System.Linq;
using System.Net;
using Newtonsoft.Json.Linq;
using UCS.Core;
using UCS.Core.Crypto;
using UCS.Core.Network;
using UCS.Core.Settings;
using UCS.Helpers.Binary;
using UCS.Helpers.List;
using UCS.Logic;
using UCS.Logic.Enums;
using UCS.Logic.Manager;
using UCS.Packets.Messages.Server;
using UCS.Utilities.Blake2B;
using UCS.Utilities.Sodium;
namespace UCS.Packets.Messages.Client
{
// Token: 0x020000D6 RID: 214
internal class Authentication : Message
{
// Token: 0x06000447 RID: 1095 RVA: 0x00006835 File Offset: 0x00004A35
public Authentication(Device device, Reader reader) : base(device, reader)
{
this.Device.PlayerState = State.LOGIN;
}
// Token: 0x06000448 RID: 1096 RVA: 0x0002FB04 File Offset: 0x0002DD04
internal override void Decrypt()
{
byte[] array = this.Reader.ReadBytes(this.Length);
this.Device.Keys.PublicKey = array.Take(32).ToArray<byte>();
Logger.WriteDebug("Device.Keys.PublicKey: " + this.Device.Keys.PublicKey.ToList<byte>().BytesToHexa());
Blake2BHasher blake2BHasher = new Blake2BHasher();
blake2BHasher.Update(this.Device.Keys.PublicKey);
blake2BHasher.Update(Key.PublicKey);
this.Device.Keys.RNonce = blake2BHasher.Finish();
array = Sodium.Decrypt(array.Skip(32).ToArray<byte>(), this.Device.Keys.RNonce, Key.PrivateKey, this.Device.Keys.PublicKey);
this.Device.Keys.SNonce = array.Skip(24).Take(24).ToArray<byte>();
Logger.WriteDebug("decrypted Buffer 前24字节: " + array.Take(24).ToList<byte>().BytesToHexa());
Logger.WriteDebug("decrypted Buffer 全部内容: " + array.ToList<byte>().BytesToHexa());
Logger.WriteDebug("Device.Keys.SNonce: " + this.Device.Keys.SNonce.ToList<byte>().BytesToHexa());
this.Reader = new Reader(array.Skip(48).ToArray<byte>());
Logger.WriteDebug("LoginMessage Data: " + array.Skip(48).ToList<byte>().BytesToHexa());
this.Length = array.Length;
}
// Token: 0x06000449 RID: 1097 RVA: 0x0002FCA8 File Offset: 0x0002DEA8
internal override void Decode()
{
this.UserID = this.Reader.ReadInt64();
this.UserToken = this.Reader.ReadString();
this.MajorVersion = this.Reader.ReadInt32();
this.ContentVersion = this.Reader.ReadInt32();
this.MinorVersion = this.Reader.ReadInt32();
this.MasterHash = this.Reader.ReadString();
this.UDID = this.Reader.ReadString();
this.OpenUDID = this.Reader.ReadString();
this.DeviceModel = this.Reader.ReadString();
this.Reader.ReadString();
this.Region = this.Reader.ReadString();
this.AdvertisingGUID = this.Reader.ReadString();
this.OSVersion = this.Reader.ReadString();
this.Reader.ReadString();
Logger.WriteDebug("=== Authentication 10101 ===");
Logger.WriteDebug(string.Format("UserID -> {0}", this.UserID));
Logger.WriteDebug("UserToken -> " + this.UserToken);
Logger.WriteDebug(string.Format("MajorVersion -> {0}", this.MajorVersion));
Logger.WriteDebug(string.Format("ContentVersion -> {0}", this.ContentVersion));
Logger.WriteDebug(string.Format("MinorVersion -> {0}", this.MinorVersion));
Logger.WriteDebug("MasterHash -> " + this.MasterHash);
Logger.WriteDebug("UDID -> " + this.UDID);
Logger.WriteDebug("OpenUDID -> " + this.OpenUDID);
Logger.WriteDebug("DeviceModel -> " + this.DeviceModel);
Logger.WriteDebug("Region -> " + this.Region);
Logger.WriteDebug("AdvertisingGUID -> " + this.AdvertisingGUID);
Logger.WriteDebug("OSVersion -> " + this.OSVersion);
Logger.WriteDebug("=== Authentication END ===");
}
// Token: 0x0600044A RID: 1098 RVA: 0x0002FEC0 File Offset: 0x0002E0C0
internal override void Process()
{
if (Settings.MaintenanceTimeLeft != 0)
{
long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if ((long)Settings.MaintenanceTimeLeft > num)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 10,
RemainingTime = (int)((long)Settings.MaintenanceTimeLeft - num)
}.Send();
}
}
if (Settings.ClientVersion != string.Format("{0}.{1}", this.MajorVersion, this.MinorVersion))
{
new Authentication_Failed(this.Device)
{
ErrorCode = 8,
UpdateURL = Settings.UpdateURL
}.Send();
return;
}
if (!Settings.UsePatch && !this.MasterHash.Equals(Settings.CurrentSha))
{
new Authentication_Failed(this.Device)
{
ErrorCode = 8,
UpdateURL = Settings.UpdateURL
}.Send();
return;
}
if (Settings.UsePatch && !this.MasterHash.Equals(Settings.PatchSha))
{
string text = new WebClient().DownloadString(Settings.PatchURL + "/" + Settings.PatchSha + "/fingerprint.json");
Logger.Write("Patching client...");
Logger.WriteDebug("PatchURL: " + Settings.PatchURL);
Logger.WriteDebug("PatchSha: " + Settings.PatchSha);
Logger.WriteDebug("PatchFingerprint: " + text);
new Authentication_Failed(this.Device)
{
ErrorCode = 7,
ContentUrl = Settings.PatchURL,
ResourceFingerprintData = text
}.Send();
return;
}
Logger.WriteDebug("checking client...");
this.LogUser();
}
// Token: 0x0600044B RID: 1099 RVA: 0x0003005C File Offset: 0x0002E25C
private void LogUser()
{
if (this.UserID <= 0L || this.UserToken == string.Empty || this.UserID > ObjectManager.m_vAvatarSeed)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 13
}.Send();
return;
}
this.player_level = new Level(this.UserID, this.UserToken);
Logger.WriteDebug("Log in,not register!");
if (this.player_level != null)
{
if (this.UserID > 0L)
{
this.player_level.Avatar.UserID = this.UserID;
Logger.WriteDebug("玩家的UserID设为Authentication的UserID");
}
this.player_level.Tick();
this.player_level.Avatar.IPAddress = this.Device.IPAddress;
Logger.WriteDebug("Player IPAddress: " + this.player_level.Avatar.IPAddress);
if (this.player_level.Avatar.AccountBanned)
{
if (this.player_level.Avatar.AccountBanTime == 0L)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 11,
Reason = "因为不合适的玩家行为,您的账号现已被永久封禁!" + ((this.player_level.Avatar.AccountBanReason.Length > 0) ? ("\n理由:" + this.player_level.Avatar.AccountBanReason) : "")
}.Send();
return;
}
long localTimeStamp = TimeManager.getLocalTimeStamp();
long accountBanTime = this.player_level.Avatar.AccountBanTime;
long num = accountBanTime - localTimeStamp;
int[] timeInterval = TimeManager.getTimeInterval(num);
if (num >= 0L)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 11,
Reason = string.Format("因为不合适的玩家行为,您的账号现已被封禁!\n当前时间:{0}\n解封时间:{1}\n距离解封还有 {2} 天 {3} 小时 {4} 分钟 {5} 秒{6}", new object[]
{
TimeManager.getDateTimeByTimeStamp(localTimeStamp),
TimeManager.getDateTimeByTimeStamp(accountBanTime),
timeInterval[0],
timeInterval[1],
timeInterval[2],
timeInterval[3],
(this.player_level.Avatar.AccountBanReason.Length > 0) ? ("\n理由:" + this.player_level.Avatar.AccountBanReason) : ""
})
}.Send();
return;
}
this.player_level.Avatar.UnbanPlayer();
}
else
{
if (this.player_level.Avatar.AccountRetrieving)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 13
}.Send();
return;
}
char c = char.ToLower(this.UserToken[0]);
string path = string.Format("Config/UnlockCode/{0}.json", c);
if (!File.Exists(path))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(path, "{\"UnlockCode\": []}");
}
this._JObjectUnlockCode = JObject.Parse(File.ReadAllText(path));
JArray jarray = (JArray)this._JObjectUnlockCode["UnlockCode"];
if (!this.player_level.Avatar.AccountRetrieving_UnlockCode)
{
jarray.Add(this.UserToken.Substring(0, 12));
this._JObjectUnlockCode["UnlockCode"] = jarray;
File.WriteAllText(path, this._JObjectUnlockCode.ToString());
this.player_level.Avatar.AccountRetrieving_UnlockCode = true;
}
else if (!this.IsUnlockCodeInArray(jarray, this.UserToken.Substring(0, 12)) && this.player_level.Avatar.AccountRetrieving_UnlockCode)
{
new Authentication_Failed(this.Device)
{
ErrorCode = 13
}.Send();
return;
}
if (!this.player_level.Avatar.LastUserToken.Equals("missing LastUserToken") && !this.player_level.Avatar.LastUserToken.Equals(this.UserToken))
{
new Authentication_Failed(this.Device)
{
ErrorCode = 11,
Reason = "UserToken错误。你的Token(" + this.UserToken + ")与服务器记录上一次的Token不一致。"
}.Send();
return;
}
if (ResourcesManager.IsPlayerOnline(this.player_level.Avatar.UserID))
{
new ForceDisconnectMessage(ResourcesManager.m_vInMemoryLevels[this.player_level.Avatar.UserID].Client);
try
{
ResourcesManager.LogPlayerOut(ResourcesManager.m_vInMemoryLevels[this.player_level.Avatar.UserID]);
}
catch (Exception arg)
{
Logger.Write(string.Format("因为异常{0},无法ResourcesManager.LogPlayerOut该玩家,也许已经登出了吧。", arg));
}
Logger.Write(string.Format("玩家 {0} 在其他设备登录,原设备自动登出。", this.player_level.Avatar.UserID));
}
}
ResourcesManager.LogPlayerIn(this.player_level, this.Device);
Logger.WriteDebug("Successfully log in!");
Logger.Write(string.Format("玩家 {0} ({1}) 加入了游戏。", this.player_level.Avatar.UserID, this.player_level.Client.IPAddress));
this.Device.Player.Avatar.PlayerStatisticsAddOne("game_join");
this.Device.Player.Avatar.LastIPAddress = this.Device.IPAddress;
this.Device.Player.Avatar.LastUserToken = this.UserToken;
new Authentication_OK(this.Device)
{
ServerMajorVersion = this.MajorVersion,
ServerBuild = this.MinorVersion,
ContentVersion = this.ContentVersion
}.Send();
this.Device.Player.homeBaseManager.jsonObject = this.Device.CheckArtifact(this.Device.Player.homeBaseManager.jsonObject);
new OwnHomeDataMessage(this.Device).Send();
new AllianceStreamMessage(this.Device).Send();
new MegabaseEventInfoMessage(this.Device)
{
CurrentStage = this.Device.Player.Avatar.MegacrabCurrentStage
}.Send();
new IntelMessage(this.Device)
{
IntelCount = 250,
IntelCapacity = 1000
}.Send();
new CoopMissionDataMessage(this.Device).Send();
if (File.Exists("Config/notice.txt"))
{
string text = File.ReadAllText("Config/notice.txt");
text += string.Format("\n下面是你的账号信息,请不要轻易告知他人\n你的玩家ID:{0}\n你的密码:使用“/me”查看(默认为Token)\n你的Token:{1}\n请截图保存你的信息。\n复制存档:/saves <id> <密码>\n找回账号:/findacc <id>", new object[]
{
this.Device.Player.Avatar.UserID,
this.Device.Player.Avatar.UserToken
});
this.Device.SendCommandFeedback(text);
}
return;
}
new Authentication_Failed(this.Device)
{
ErrorCode = 114514,
Reason = "请删除应用数据后重试。"
}.Send();
}
// Token: 0x0600044C RID: 1100 RVA: 0x00030740 File Offset: 0x0002E940
private void NewUser()
{
Logger.WriteDebug(string.Format("Authentication.NewUser ({0})", ObjectManager.m_vAvatarSeed));
File.Copy("Gamefiles/starting_pp.json", string.Format("Saves/pp/{0}.json", ObjectManager.m_vAvatarSeed + 1L));
this.player_level = ObjectManager.CreateAvatar;
this.player_level.Avatar.UserID = ObjectManager.m_vAvatarSeed;
this.player_level.Avatar.AvatarName = string.Format("海洋军阀-{0}", this.player_level.Avatar.UserID);
if (string.IsNullOrEmpty(this.UserToken))
{
for (int i = 0; i < 12; i++)
{
char c = (char)Resources.Random.Next(65, 90);
ClientAvatar avatar = this.player_level.Avatar;
avatar.UserToken += c.ToString();
}
}
this.player_level.Avatar.Password = this.player_level.Avatar.UserToken;
Logger.WriteDebug(string.Format("New Player Created! PlayerID: {0} UserToken: {1}", this.player_level.Avatar.UserID, this.player_level.Avatar.UserToken));
this.player_level.Avatar.InitializeAccountCreationDate();
}
// Token: 0x0600044D RID: 1101 RVA: 0x00030888 File Offset: 0x0002EA88
private bool IsUnlockCodeInArray(JArray qqArray, string usertoken)
{
if (qqArray != null)
{
string lowerCaseUnlockCode = usertoken.ToLower();
return qqArray.Any((JToken t) => t.ToString().ToLower() == lowerCaseUnlockCode);
}
return false;
}
// Token: 0x040003FB RID: 1019
public string AdvertisingGUID;
// Token: 0x040003FC RID: 1020
public bool Android;
// Token: 0x040003FD RID: 1021
public string AndroidDeviceID;
// Token: 0x040003FE RID: 1022
public int ContentVersion;
// Token: 0x040003FF RID: 1023
public string DeviceModel;
// Token: 0x04000400 RID: 1024
public string FacebookDistributionID;
// Token: 0x04000401 RID: 1025
public bool IsAdvertisingTrackingEnabled;
// Token: 0x04000402 RID: 1026
public Level player_level;
// Token: 0x04000403 RID: 1027
public int LocaleKey;
// Token: 0x04000404 RID: 1028
public string MacAddress;
// Token: 0x04000405 RID: 1029
public int MajorVersion;
// Token: 0x04000406 RID: 1030
public string MasterHash;
// Token: 0x04000407 RID: 1031
public int MinorVersion;
// Token: 0x04000408 RID: 1032
public string OpenUDID;
// Token: 0x04000409 RID: 1033
public string OSVersion;
// Token: 0x0400040A RID: 1034
public string Region;
// Token: 0x0400040B RID: 1035
public uint Seed;
// Token: 0x0400040C RID: 1036
public string UDID;
// Token: 0x0400040D RID: 1037
public long UserID;
// Token: 0x0400040E RID: 1038
public string UserToken;
// Token: 0x0400040F RID: 1039
public string VendorGUID;
// Token: 0x04000410 RID: 1040
public string PatchFingerprint;
// Token: 0x04000411 RID: 1041
private JObject _JObjectUnlockCode;
// Token: 0x020000D7 RID: 215
public class AccountInfo
{
// Token: 0x1700006E RID: 110
// (get) Token: 0x0600044E RID: 1102 RVA: 0x0000684B File Offset: 0x00004A4B
// (set) Token: 0x0600044F RID: 1103 RVA: 0x00006853 File Offset: 0x00004A53
public bool AccountBanned { get; set; }
// Token: 0x1700006F RID: 111
// (get) Token: 0x06000450 RID: 1104 RVA: 0x0000685C File Offset: 0x00004A5C
// (set) Token: 0x06000451 RID: 1105 RVA: 0x00006864 File Offset: 0x00004A64
public long AccountBanTime { get; set; }
// Token: 0x17000070 RID: 112
// (get) Token: 0x06000452 RID: 1106 RVA: 0x0000686D File Offset: 0x00004A6D
// (set) Token: 0x06000453 RID: 1107 RVA: 0x00006875 File Offset: 0x00004A75
public string AccountBanReason { get; set; }
}
}
}
可以看到,新号必定要激活码。
老号通过这个代码记录token和更改身份信息
下面这个代码用于检验账号,避免一码多用。如果有人用了他的token创建了账号,那么会被这代码封禁这个账号。