Cleanup and adds configuration for crashguard (#240)

This commit is contained in:
Kamron Batman 2020-09-12 01:57:07 -07:00 • committed by GitHub
parent 55ae0f8778
commit 7dbfa086bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 1248 additions and 97 deletions

View file

@ -51,10 +51,14 @@ namespace Server
)
{
if (m?.Deleted != false || !m.Alive || damage <= 0)
{
return 0;
}
if (phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0)
{
MeerMage.StopEffect(m, true);
}
if (!Core.AOS)
{
@ -71,6 +75,7 @@ namespace Server
Fix(ref direct);
if (Core.ML && chaos > 0)
{
switch (Utility.Random(5))
{
case 0:
@ -89,11 +94,14 @@ namespace Server
nrgy += chaos;
break;
}
}
BaseQuiver quiver = null;
if (archer && from != null)
quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver;
{
quiver = @from.FindItemOnLayer(Layer.Cloak) as BaseQuiver;
}
int totalDamage;
@ -119,31 +127,44 @@ namespace Server
totalDamage += damage * direct / 100;
if (quiver != null)
{
totalDamage += totalDamage * quiver.DamageIncrease / 100;
}
}
if (totalDamage < 1)
{
totalDamage = 1;
}
}
else if (Core.ML && m is PlayerMobile && from is PlayerMobile)
{
if (quiver != null)
{
damage += damage * quiver.DamageIncrease / 100;
}
if (!deathStrike)
{
totalDamage = Math.Min(damage, 35); // Direct Damage cap of 35
}
else
{
totalDamage = Math.Min(damage, 70); // Direct Damage cap of 70
}
}
else
{
totalDamage = damage;
if (Core.ML && quiver != null)
{
totalDamage += totalDamage * quiver.DamageIncrease / 100;
}
}
if (from?.Player != true && m.Player && m.Mount is SwampDragon pet)
{
if (pet.HasBarding)
{
var percent = pet.BardingExceptional ? 20 : 10;
@ -160,9 +181,12 @@ namespace Server
m.SendLocalizedMessage(1053031); // Your dragon's barding has been destroyed!
}
}
}
if (keepAlive && totalDamage > m.Hits)
{
totalDamage = m.Hits;
}
if (from?.Deleted == false && from.Alive)
{
@ -194,7 +218,9 @@ namespace Server
public static void Fix(ref int val)
{
if (val < 0)
{
val = 0;
}
}
public static int Scale(int input, int percent) => input * percent / 100;
@ -447,7 +473,9 @@ namespace Server
public static int GetValue(Mobile m, AosAttribute attribute)
{
if (!Core.AOS)
{
return 0;
}
var items = m.Items;
var value = 0;
@ -461,55 +489,73 @@ namespace Server
var attrs = weapon.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
if (attribute == AosAttribute.Luck)
{
value += weapon.GetLuckBonus();
}
}
else if (obj is BaseArmor armor)
{
var attrs = armor.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
if (attribute == AosAttribute.Luck)
{
value += armor.GetLuckBonus();
}
}
else if (obj is BaseJewel jewel)
{
var attrs = jewel.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
else if (obj is BaseClothing clothing)
{
var attrs = clothing.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
else if (obj is Spellbook spellbook)
{
var attrs = spellbook.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
else if (obj is BaseQuiver quiver)
{
var attrs = quiver.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
else if (obj is BaseTalisman talisman)
{
var attrs = talisman.Attributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
}
@ -529,13 +575,19 @@ namespace Server
var modName = Owner.Serial.ToString();
if (strBonus != 0)
{
to.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero));
}
if (dexBonus != 0)
{
to.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero));
}
if (intBonus != 0)
{
to.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero));
}
}
to.CheckStatTimers();
@ -784,7 +836,9 @@ namespace Server
public static int GetValue(Mobile m, AosWeaponAttribute attribute)
{
if (!Core.AOS)
{
return 0;
}
var items = m.Items;
var value = 0;
@ -798,14 +852,18 @@ namespace Server
var attrs = weapon.WeaponAttributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
else if (obj is ElvenGlasses glasses)
{
var attrs = glasses.WeaponAttributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
}
@ -878,7 +936,9 @@ namespace Server
public static int GetValue(Mobile m, AosArmorAttribute attribute)
{
if (!Core.AOS)
{
return 0;
}
var items = m.Items;
var value = 0;
@ -892,14 +952,18 @@ namespace Server
var attrs = armor.ArmorAttributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
else if (obj is BaseClothing clothing)
{
var attrs = clothing.ClothingAttributes;
if (attrs != null)
{
value += attrs[attribute];
}
}
}
@ -1001,8 +1065,12 @@ namespace Server
public void GetProperties(ObjectPropertyList list)
{
for (var i = 0; i < 5; ++i)
{
if (GetValues(i, out var skill, out var bonus))
{
list.Add(1060451 + i, "#{0}\t{1}", GetLabel(skill), bonus);
}
}
}
public static int GetLabel(SkillName skill)
@ -1023,7 +1091,9 @@ namespace Server
for (var i = 0; i < 5; ++i)
{
if (!GetValues(i, out var skill, out var bonus))
{
continue;
}
m_Mods ??= new List<SkillMod>();
@ -1037,7 +1107,9 @@ namespace Server
public void Remove()
{
if (m_Mods == null)
{
return;
}
for (var i = 0; i < m_Mods.Count; ++i)
{
@ -1045,7 +1117,9 @@ namespace Server
m_Mods[i].Remove();
if (Core.ML)
{
CheckCancelMorph(m);
}
}
m_Mods = null;
@ -1123,7 +1197,9 @@ namespace Server
public void CheckCancelMorph(Mobile m)
{
if (m == null)
{
return;
}
var acontext = AnimalForm.GetContext(m);
var context = TransformationSpellHelper.GetContext(m);
@ -1132,17 +1208,26 @@ namespace Server
{
spell.GetCastSkills(out var minSkill, out _);
if (m.Skills[spell.CastSkill].Value < minSkill)
{
TransformationSpellHelper.RemoveContext(m, context, true);
}
}
if (acontext != null)
{
int i;
for (i = 0; i < AnimalForm.Entries.Length; ++i)
{
if (AnimalForm.Entries[i].Type == acontext.Type)
{
break;
}
}
if (m.Skills.Ninjitsu.Value < AnimalForm.Entries[i].ReqSkill)
{
AnimalForm.RemoveContext(m, true);
}
}
if (!m.CanBeginAction<PolymorphSpell>() && m.Skills.Magery.Value < 66.1)
@ -1158,7 +1243,10 @@ namespace Server
if (!m.CanBeginAction<IncognitoSpell>() && m.Skills.Magery.Value < 38.1)
{
if (m is PlayerMobile mobile)
{
mobile.SetHairMods(-1, -1);
}
m.BodyMod = 0;
m.HueMod = -1;
m.NameMod = null;
@ -1292,7 +1380,9 @@ namespace Server
m_Values = new int[reader.ReadEncodedInt()];
for (var i = 0; i < m_Values.Length; ++i)
{
m_Values[i] = reader.ReadEncodedInt();
}
break;
}
@ -1302,7 +1392,9 @@ namespace Server
m_Values = new int[reader.ReadInt()];
for (var i = 0; i < m_Values.Length; ++i)
{
m_Values[i] = reader.ReadInt();
}
break;
}
@ -1320,23 +1412,31 @@ namespace Server
writer.WriteEncodedInt(m_Values.Length);
for (var i = 0; i < m_Values.Length; ++i)
{
writer.WriteEncodedInt(m_Values[i]);
}
}
public int GetValue(int bitmask)
{
if (!Core.AOS)
{
return 0;
}
var mask = (uint)bitmask;
if ((m_Names & mask) == 0)
{
return 0;
}
var index = GetIndex(mask);
if (index >= 0 && index < m_Values.Length)
{
return m_Values[index];
}
return 0;
}
@ -1346,14 +1446,20 @@ namespace Server
if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && this is AosWeaponAttributes)
{
if (Owner is BaseWeapon weapon)
{
weapon.UnscaleDurability();
}
}
else if (bitmask == (int)AosArmorAttribute.DurabilityBonus && this is AosArmorAttributes)
{
if (Owner is BaseArmor armor)
{
armor.UnscaleDurability();
}
else if (Owner is BaseClothing clothing)
{
clothing.UnscaleDurability();
}
}
var mask = (uint)bitmask;
@ -1365,7 +1471,9 @@ namespace Server
var index = GetIndex(mask);
if (index >= 0 && index < m_Values.Length)
{
m_Values[index] = value;
}
}
else
{
@ -1377,12 +1485,16 @@ namespace Server
m_Values = new int[old.Length + 1];
for (var i = 0; i < index; ++i)
{
m_Values[i] = old[i];
}
m_Values[index] = value;
for (var i = index; i < old.Length; ++i)
{
m_Values[i + 1] = old[i];
}
m_Names |= mask;
}
@ -1406,10 +1518,14 @@ namespace Server
m_Values = new int[old.Length - 1];
for (var i = 0; i < index; ++i)
{
m_Values[i] = old[i];
}
for (var i = index + 1; i < old.Length; ++i)
{
m_Values[i - 1] = old[i];
}
}
}
}
@ -1417,14 +1533,20 @@ namespace Server
if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && this is AosWeaponAttributes)
{
if (Owner is BaseWeapon weapon)
{
weapon.ScaleDurability();
}
}
else if (bitmask == (int)AosArmorAttribute.DurabilityBonus && this is AosArmorAttributes)
{
if (Owner is BaseArmor armor)
{
armor.ScaleDurability();
}
else if (Owner is BaseClothing clothing)
{
clothing.ScaleDurability();
}
}
if (Owner.Parent is Mobile m)
@ -1455,10 +1577,14 @@ namespace Server
while (currentBit != mask)
{
if ((ourNames & currentBit) != 0)
{
++index;
}
if (currentBit == 0x80000000)
{
return -1;
}
currentBit <<= 1;
}

View file

@ -108,36 +108,49 @@ namespace Server
public TextDefinition Args { get; }
public static void Initialize()
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("buffIcons.enable", Core.ML);
}
public static void Initialize()
{
if (Enabled)
{
EventSink.ClientVersionReceived += ResendBuffsOnClientVersionReceived;
}
}
public static void ResendBuffsOnClientVersionReceived(NetState ns, ClientVersion cv)
{
if (ns.Mobile is PlayerMobile pm)
{
Timer.DelayCall(pm.ResendBuffs);
}
}
public static void AddBuff(Mobile m, BuffInfo b)
{
if (m is PlayerMobile pm)
{
pm.AddBuff(b);
}
}
public static void RemoveBuff(Mobile m, BuffInfo b)
{
if (m is PlayerMobile pm)
{
pm.RemoveBuff(b);
}
}
public static void RemoveBuff(Mobile m, BuffIcon b)
{
if (m is PlayerMobile pm)
{
pm.RemoveBuff(b);
}
}
}
@ -235,7 +248,9 @@ namespace Server
Stream.Fill(4);
if (length < TimeSpan.Zero)
{
length = TimeSpan.Zero;
}
Stream.Write((short)length.TotalSeconds); // Time in seconds

View file

@ -7,7 +7,7 @@ using Server.Network;
namespace Server.Misc
{
public class ClientVerification
public static class ClientVerification
{
private static bool m_DetectClientRequirement;
private static OldClientResponse m_OldClientResponse;
@ -25,7 +25,7 @@ namespace Server.Misc
public static TimeSpan KickDelay { get; set; }
public static void Initialize()
public static void Configure()
{
m_DetectClientRequirement = ServerConfiguration.GetOrUpdateSetting("clientVerification.enable", true);
m_OldClientResponse =
@ -36,7 +36,10 @@ namespace Server.Misc
TimeSpan.FromHours(25)
);
KickDelay = ServerConfiguration.GetOrUpdateSetting("clientVerification.kickDelay", TimeSpan.FromSeconds(20.0));
}
public static void Initialize()
{
EventSink.ClientVersionReceived += EventSink_ClientVersionReceived;
if (m_DetectClientRequirement)
@ -49,12 +52,14 @@ namespace Server.Misc
if (info.FileMajorPart != 0 || info.FileMinorPart != 0 || info.FileBuildPart != 0 ||
info.FilePrivatePart != 0)
{
Required = new ClientVersion(
info.FileMajorPart,
info.FileMinorPart,
info.FileBuildPart,
info.FilePrivatePart
);
}
}
}
@ -75,7 +80,9 @@ namespace Server.Misc
string kickMessage = null;
if (state.Mobile?.AccessLevel != AccessLevel.Player)
{
return;
}
if (Required != null && version < Required && (m_OldClientResponse == OldClientResponse.Kick ||
m_OldClientResponse == OldClientResponse.LenientKick &&
@ -88,11 +95,17 @@ namespace Server.Misc
else if (!AllowGod || !AllowRegular || !AllowUOTD)
{
if (!AllowGod && version.Type == ClientType.God)
{
kickMessage = "This server does not allow god clients to connect.";
}
else if (!AllowRegular && version.Type == ClientType.Regular)
{
kickMessage = "This server does not allow regular clients to connect.";
}
else if (!AllowUOTD && state.IsUOTDClient)
{
kickMessage = "This server does not allow UO:TD clients to connect.";
}
if (!AllowGod && !AllowRegular && !AllowUOTD)
{
@ -105,11 +118,17 @@ namespace Server.Misc
else if (kickMessage != null)
{
if (AllowRegular && AllowUOTD)
{
kickMessage += " You can use regular or UO:TD clients.";
}
else if (AllowRegular)
{
kickMessage += " You can use regular clients.";
}
else if (AllowUOTD)
{
kickMessage += " You can use UO:TD clients.";
}
}
}
@ -162,11 +181,13 @@ namespace Server.Misc
from.SendMessage("You will be reminded of this again.");
if (m_OldClientResponse == OldClientResponse.LenientKick)
{
from.SendMessage(
"Old clients will be kicked after {0} days of character age and {1} hours of play time",
m_AgeLeniency,
m_GameTimeLeniency
);
}
Timer.DelayCall(TimeSpan.FromMinutes(Utility.Random(5, 15)), SendAnnoyGump, from);
}

View file

@ -8,11 +8,18 @@ namespace Server.Misc
{
public static class CrashGuard
{
// TODO: Make this configurable
private const bool Enabled = true;
private const bool SaveBackup = true;
private const bool RestartServer = true;
private const bool GenerateReport = true;
private static bool Enabled;
private static bool SaveBackup;
private static bool RestartServer; // Disable this if using a daemon/service
private static bool GenerateReport;
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("crashGuard.enabled", true);
SaveBackup = ServerConfiguration.GetOrUpdateSetting("crashGuard.saveBackup", true);
RestartServer = ServerConfiguration.GetOrUpdateSetting("crashGuard.restartServer", true);
GenerateReport = ServerConfiguration.GetOrUpdateSetting("crashGuard.generateReport", true);
}
public static void Initialize()
{

View file

@ -18,7 +18,10 @@ namespace Server.Misc
/// <param name="pageType"></param>
public static void SendQueueEmail(PageEntry entry, string pageType)
{
if (!EmailConfiguration.EmailEnabled) return;
if (!EmailConfiguration.EmailEnabled)
{
return;
}
var sender = entry.Sender;
var time = DateTime.UtcNow;
@ -75,7 +78,10 @@ namespace Server.Misc
/// <param name="filePath"></param>
public static void SendCrashEmail(string filePath)
{
if (EmailConfiguration.EmailEnabled) return;
if (EmailConfiguration.EmailEnabled)
{
return;
}
var message = new MimeMessage();
message.From.Add(EmailConfiguration.FromAddress);
@ -96,7 +102,10 @@ namespace Server.Misc
/// <param name="message"></param>
private static async void SendAsync(MimeMessage message)
{
if (!EmailConfiguration.EmailEnabled) return;
if (!EmailConfiguration.EmailEnabled)
{
return;
}
var now = DateTime.UtcNow;
var messageID = $"<{now:yyyyMMdd}.{now:HHmmssff}@{EmailConfiguration.EmailServer}>";
@ -106,6 +115,7 @@ namespace Server.Misc
var delay = EmailConfiguration.EmailSendRetryDelay;
for (var i = 0; i < EmailConfiguration.EmailSendRetryCount; i++)
{
try
{
using var client = new SmtpClient();
@ -130,6 +140,7 @@ namespace Server.Misc
await Task.Delay(delay * 1000);
}
}
}
}
}

View file

@ -7,24 +7,16 @@ namespace Server
{
public class AssemblyEmitter
{
private readonly AssemblyBuilder m_AssemblyBuilder;
private readonly ModuleBuilder m_ModuleBuilder;
private AppDomain m_AppDomain;
private string m_AssemblyName;
public AssemblyEmitter(string assemblyName)
{
m_AssemblyName = assemblyName;
m_AppDomain = AppDomain.CurrentDomain;
m_AssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName(assemblyName),
AssemblyBuilderAccess.Run
);
m_ModuleBuilder = m_AssemblyBuilder.DefineDynamicModule(assemblyName);
m_ModuleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName);
}
public TypeBuilder DefineType(string typeName, TypeAttributes attrs, Type parentType) =>

View file

@ -52,7 +52,7 @@ namespace Server.Misc
{
if (from == GuildStatus.Waring && target == GuildStatus.Waring)
return true;
return false;
}*/
@ -193,7 +193,7 @@ namespace Server.Misc
(fromGuild == targetGuild || fromGuild.IsAlly(targetGuild) || fromGuild.IsEnemy(targetGuild)))
return true; // Guild allies or enemies can be harmful
if (bcTarg?.Controlled == true || bcTarg?.Summoned == true && bcTarg?.SummonMaster != @from)
if (bcTarg?.Controlled == true || bcTarg?.Summoned == true && bcTarg?.SummonMaster != from)
return false; // Cannot harm other controlled mobiles
if (target.Player)

View file

@ -82,7 +82,7 @@ namespace Server.Misc
var points = (int)(from.Skills.Focus.Value * 0.1);
if (@from is BaseCreature creature && creature.IsParagon || from is Leviathan)
if (from is BaseCreature creature && creature.IsParagon || from is Leviathan)
points += 40;
var cappedPoints = AosAttributes.GetValue(from, AosAttribute.RegenStam);
@ -130,7 +130,7 @@ namespace Server.Misc
var totalPoints = focusPoints + medPoints + (from.Meditating ? medPoints > 13.0 ? 13.0 : medPoints : 0.0);
if (@from is BaseCreature creature && creature.IsParagon || from is Leviathan)
if (from is BaseCreature creature && creature.IsParagon || from is Leviathan)
totalPoints += 40;
var cappedPoints = AosAttributes.GetValue(from, AosAttribute.RegenMana);

View file

@ -43,16 +43,21 @@ namespace Server.Misc
public static bool AutoDetect { get; private set; }
public static void Initialize()
public static void Configure()
{
Address = ServerConfiguration.GetOrUpdateSetting("serverListing.address", null);
AutoDetect = ServerConfiguration.GetOrUpdateSetting("serverListing.autoDetect", true);
ServerName = ServerConfiguration.GetOrUpdateSetting("serverListing.serverName", "ModernUO");
}
public static void Initialize()
{
if (Address == null)
{
if (AutoDetect)
{
AutoDetection();
}
}
else
{
@ -77,7 +82,9 @@ namespace Server.Misc
{
ipep = (IPEndPoint)ns.Connection.RemoteEndPoint;
if (!IsPrivateNetwork(ipep.Address) && m_PublicAddress != null)
{
localAddress = m_PublicAddress;
}
}
e.AddServer(ServerName, new IPEndPoint(localAddress, localPort));
@ -97,23 +104,31 @@ namespace Server.Misc
m_PublicAddress = FindPublicAddress();
if (m_PublicAddress != null)
{
Console.WriteLine("done ({0})", m_PublicAddress);
}
else
{
Console.WriteLine("failed");
}
}
}
private static void Resolve(string addr, out IPAddress outValue)
{
if (IPAddress.TryParse(addr, out outValue))
{
return;
}
try
{
var iphe = Dns.GetHostEntry(addr);
if (iphe.AddressList.Length > 0)
{
outValue = iphe.AddressList[^1];
}
}
catch
{

View file

@ -156,7 +156,7 @@ namespace Server.Misc
if (from is BaseCreature creature && creature.Controlled)
gc *= 2;
if (from.Alive && (gc >= Utility.RandomDouble() && AllowGain(@from, skill, amObj) || skill.Base < 10.0))
if (from.Alive && (gc >= Utility.RandomDouble() && AllowGain(from, skill, amObj) || skill.Base < 10.0))
Gain(from, skill);
return success;

View file

@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.IO;
using Server.Engines.Spawners;
// Version 0.8
namespace Server
{
public class UOAMVendorGenerator