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

@ -25,8 +25,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Server.Json;
using Server.Network;

View file

@ -387,7 +387,7 @@ namespace Server.Network
if (from.Mobile == Mobile && to.Mobile == m)
{
return @from.Container;
return from.Container;
}
if (from.Mobile == m && to.Mobile == Mobile)

View file

@ -6,7 +6,7 @@ using Server.Network;
namespace Server.Accounting
{
public class AccountAttackLimiter
public static class AccountAttackLimiter
{
public static bool Enabled;
@ -20,7 +20,9 @@ namespace Server.Accounting
public static void Initialize()
{
if (!Enabled)
{
return;
}
PacketHandlers.RegisterThrottler(0x80, Throttle_Callback);
PacketHandlers.RegisterThrottler(0x91, Throttle_Callback);
@ -32,7 +34,9 @@ namespace Server.Accounting
var accessLog = FindAccessLog(ns);
if (accessLog == null)
{
return TimeSpan.Zero;
}
var date = DateTime.UtcNow;
var access = accessLog.LastAccessTime + ComputeThrottle(accessLog.Counts);
@ -42,7 +46,9 @@ namespace Server.Accounting
public static InvalidAccountAccessLog FindAccessLog(NetState ns)
{
if (ns == null)
{
return null;
}
var ipAddress = ns.Address;
@ -51,9 +57,13 @@ namespace Server.Accounting
var accessLog = m_List[i];
if (accessLog.HasExpired)
{
m_List.RemoveAt(i--);
}
else if (accessLog.Address.Equals(ipAddress))
{
return accessLog;
}
}
return null;
@ -62,17 +72,22 @@ namespace Server.Accounting
public static void RegisterInvalidAccess(NetState ns)
{
if (ns == null || !Enabled)
{
return;
}
var accessLog = FindAccessLog(ns);
if (accessLog == null)
{
m_List.Add(accessLog = new InvalidAccountAccessLog(ns.Address));
}
accessLog.Counts += 1;
accessLog.RefreshAccessTime();
if (accessLog.Counts >= 3)
{
try
{
using var op = new StreamWriter("throttle.log", true);
@ -87,24 +102,35 @@ namespace Server.Accounting
{
// ignored
}
}
}
public static TimeSpan ComputeThrottle(int counts)
{
if (counts >= 15)
{
return TimeSpan.FromMinutes(5.0);
}
if (counts >= 10)
{
return TimeSpan.FromMinutes(1.0);
}
if (counts >= 5)
{
return TimeSpan.FromSeconds(20.0);
}
if (counts >= 3)
{
return TimeSpan.FromSeconds(10.0);
}
if (counts >= 1)
{
return TimeSpan.FromSeconds(2.0);
}
return TimeSpan.Zero;
}

View file

@ -33,7 +33,9 @@ namespace Server.Ethics
if ((item.SavedFlags & 0x100) != 0)
{
if (item.Hue == Hero.Definition.PrimaryHue)
{
return Hero;
}
item.SavedFlags &= ~0x100;
}
@ -41,7 +43,9 @@ namespace Server.Ethics
if ((item.SavedFlags & 0x200) != 0)
{
if (item.Hue == Evil.Definition.PrimaryHue)
{
return Evil;
}
item.SavedFlags &= ~0x200;
}
@ -54,12 +58,18 @@ namespace Server.Ethics
var itemEthic = Find(item);
if (itemEthic == null || Find(newOwner) == itemEthic)
{
return true;
}
if (itemEthic == Hero)
{
(from == newOwner ? to : from).SendMessage("Only heros may receive this item.");
}
else if (itemEthic == Evil)
{
(from == newOwner ? to : from).SendMessage("Only the evil may receive this item.");
}
return false;
}
@ -69,12 +79,18 @@ namespace Server.Ethics
var itemEthic = Find(item);
if (itemEthic == null || Find(from) == itemEthic)
{
return true;
}
if (itemEthic == Hero)
{
from.SendMessage("Only heros may wear this item.");
}
else if (itemEthic == Evil)
{
from.SendMessage("Only the evil may wear this item.");
}
return false;
}
@ -84,28 +100,43 @@ namespace Server.Ethics
public static bool IsImbued(Item item, bool recurse)
{
if (Find(item) != null)
{
return true;
}
if (recurse)
{
foreach (var child in item.Items)
{
if (IsImbued(child, true))
{
return true;
}
}
}
return false;
}
public static void Initialize()
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("ethics.enable", false);
}
public static void Initialize()
{
if (Enabled)
{
EventSink.Speech += EventSink_Speech;
}
}
public static void EventSink_Speech(SpeechEventArgs e)
{
if (e.Blocked || e.Handled)
{
return;
}
var pl = Player.Find(e.Mobile);
@ -116,13 +147,19 @@ namespace Server.Ethics
var ethic = Ethics[i];
if (!ethic.IsEligible(e.Mobile))
{
continue;
}
if (!Insensitive.Equals(ethic.Definition.JoinPhrase.String, e.Speech))
{
continue;
}
if (!e.Mobile.GetItemsInRange(2).Any(item => item is AnkhNorth || item is AnkhWest))
{
continue;
}
pl = new Player(ethic, e.Mobile);
@ -138,7 +175,9 @@ namespace Server.Ethics
else
{
if (e.Mobile is PlayerMobile mobile && mobile.DuelContext != null)
{
return;
}
var ethic = pl.Ethic;
@ -147,10 +186,14 @@ namespace Server.Ethics
var power = ethic.Definition.Powers[i];
if (!Insensitive.Equals(power.Definition.Phrase.String, e.Speech))
{
continue;
}
if (!power.CheckInvoke(pl))
{
continue;
}
power.BeginInvoke(pl);
e.Handled = true;
@ -169,16 +212,26 @@ namespace Server.Ethics
var pl = Player.Find(mob);
if (pl != null)
{
return pl.Ethic;
}
if (inherit && mob is BaseCreature bc)
{
if (bc.Controlled)
{
return Find(bc.ControlMaster, false);
}
if (bc.Summoned)
{
return Find(bc.SummonMaster, false);
}
if (allegiance)
{
return bc.EthicAllegiance;
}
}
return null;
@ -201,7 +254,9 @@ namespace Server.Ethics
var pl = new Player(this, reader);
if (pl.Mobile != null)
{
Timer.DelayCall(pl.CheckAttach);
}
}
break;
@ -216,7 +271,9 @@ namespace Server.Ethics
writer.WriteEncodedInt(m_Players.Count);
for (var i = 0; i < m_Players.Count; ++i)
{
m_Players[i].Serialize(writer);
}
}
}
}

View file

@ -41,7 +41,7 @@ namespace Server.Factions
if (faction == null && from.AccessLevel < AccessLevel.GameMaster)
return; // TODO: Message?
if (m_Town.Owner == null || @from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)
if (m_Town.Owner == null || from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)
from.SendLocalizedMessage(1010332); // Your faction does not control this town
else if (!m_Town.Owner.IsCommander(from))
from.SendLocalizedMessage(1005242); // Only faction Leaders can use townstones

View file

@ -43,7 +43,9 @@ namespace Server.Engines.MLQuests
while ((line = sr.ReadLine()) != null)
{
if (line.Length == 0 || line.StartsWith("#"))
{
continue;
}
var split = line.Split('\t');
@ -52,11 +54,13 @@ namespace Server.Engines.MLQuests
if (type == null || !baseQuestType.IsAssignableFrom(type))
{
if (Debug)
{
Console.WriteLine(
"Warning: {1} quest type '{0}'",
split[0],
type == null ? "Unknown" : "Invalid"
);
}
continue;
}
@ -73,7 +77,9 @@ namespace Server.Engines.MLQuests
}
if (quest == null)
{
continue;
}
Register(type, quest);
@ -84,11 +90,13 @@ namespace Server.Engines.MLQuests
if (questerType == null || !baseQuesterType.IsAssignableFrom(questerType))
{
if (Debug)
{
Console.WriteLine(
"Warning: {1} quester type '{0}'",
split[i],
questerType == null ? "Unknown" : "Invalid"
);
}
continue;
}
@ -115,7 +123,9 @@ namespace Server.Engines.MLQuests
private static void RegisterQuestGiver(MLQuest quest, Type questerType)
{
if (!QuestGivers.TryGetValue(questerType, out var questList))
{
QuestGivers[questerType] = questList = new List<MLQuest>();
}
questList.Add(quest);
}
@ -125,20 +135,33 @@ namespace Server.Engines.MLQuests
Register(quest.GetType(), quest);
foreach (var questerType in questerTypes)
{
RegisterQuestGiver(quest, questerType);
}
}
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("questSystem.enableMLQuests", Core.ML);
}
public static void Initialize()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("questSystem.enableMLQuests", Core.ML);
if (!Enabled)
{
return;
}
if (AutoGenerateNew)
{
foreach (var quest in Quests.Values)
{
if (quest?.Deserialized == false)
{
quest.Generate();
}
}
}
MLQuestPersistence.EnsureExistence();
@ -205,9 +228,11 @@ namespace Server.Engines.MLQuests
m.SendMessage("Serialization for quest {0} is now {1}.", quest.GetType().Name, enable ? "enabled" : "disabled");
if (AutoGenerateNew && !enable)
{
m.SendMessage(
"Please note that automatic generation of new quests is ON. This quest will be regenerated on the next server start."
);
}
}
[Usage("SaveAllQuests [saveEnabled=true]")]
@ -225,14 +250,18 @@ namespace Server.Engines.MLQuests
var enable = e.Length == 1 ? e.GetBoolean(0) : true;
foreach (var quest in Quests.Values)
{
quest.SaveEnabled = enable;
}
m.SendMessage("Serialization for all quests is now {0}.", enable ? "enabled" : "disabled");
if (AutoGenerateNew && !enable)
{
m.SendMessage(
"Please note that automatic generation of new quests is ON. All quests will be regenerated on the next server start."
);
}
}
[Usage("InvalidQuestItems")]
@ -244,19 +273,29 @@ namespace Server.Engines.MLQuests
var found = new List<object>();
foreach (var item in World.Items.Values)
{
if (item.QuestItem)
{
if (item.Parent is Backpack pack)
{
if (pack.Parent is PlayerMobile player && player.Backpack == pack)
{
continue;
}
}
found.Add(item);
}
}
if (found.Count == 0)
{
m.SendMessage("No matching objects found.");
}
else
{
m.SendGump(new InterfaceGump(m, new[] { "Object" }, found, 0, null));
}
}
private static bool FindQuest(
@ -272,6 +311,7 @@ namespace Server.Engines.MLQuests
// 1. Check quests in progress with this NPC (overriding deliveries is intended)
if (context != null)
{
foreach (var questEntry in quests)
{
var instance = context.FindInstance(questEntry);
@ -284,6 +324,7 @@ namespace Server.Engines.MLQuests
return true;
}
}
}
// 2. Check deliveries (overriding chain offers is intended)
if ((entry = HandleDelivery(pm, quester, questerType)) != null)
@ -294,12 +335,16 @@ namespace Server.Engines.MLQuests
// 3. Check chain quest offers
if (context != null)
{
foreach (var questEntry in quests)
{
if (questEntry.IsChainTriggered && context.ChainOffers.Contains(questEntry))
{
quest = questEntry;
return true;
}
}
}
// 4. Random quest
quest = RandomStarterQuest(quester, pm, context);
@ -310,7 +355,9 @@ namespace Server.Engines.MLQuests
public static void OnDoubleClick(IQuestGiver quester, PlayerMobile pm)
{
if (quester.Deleted || !pm.Alive)
{
return;
}
var context = GetContext(pm);
@ -325,13 +372,22 @@ namespace Server.Engines.MLQuests
TurnToFace(quester, pm);
if (entry.Failed)
{
return; // Note: OSI sends no gump at all for failed quests, they have to be cancelled in the quest overview
}
if (entry.ClaimReward)
{
entry.SendRewardOffer();
}
else if (entry.IsCompleted())
{
entry.SendReportBackGump();
}
else
{
entry.SendProgressGump();
}
}
else if (quest.CanOffer(quester, pm, context, true))
{
@ -346,9 +402,15 @@ namespace Server.Engines.MLQuests
var context = GetContext(pm);
if (context != null)
{
foreach (var quest in context.QuestInstances)
{
if (!quest.ClaimReward && quest.AllowsQuestItem(item, type))
{
return true;
}
}
}
return false;
}
@ -358,7 +420,9 @@ namespace Server.Engines.MLQuests
var context = GetContext(pm);
if (context == null)
{
return;
}
var instances = context.QuestInstances;
@ -368,14 +432,18 @@ namespace Server.Engines.MLQuests
var instance = instances[i];
if (instance.ClaimReward)
{
continue;
}
foreach (var objective in instance.Objectives)
{
if (!objective.Expired && objective.AllowsQuestItem(item, type))
{
objective.CheckComplete(); // yes, this can happen multiple times (for multiple quests)
break;
}
}
}
}
@ -399,7 +467,9 @@ namespace Server.Engines.MLQuests
var context = GetContext(pm);
if (context == null)
{
return;
}
var instances = context.QuestInstances;
@ -408,15 +478,19 @@ namespace Server.Engines.MLQuests
var instance = instances[i];
if (instance.ClaimReward)
{
continue;
}
foreach (var objective in instance.Objectives)
{
if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance &&
objectiveInstance.Handles(skill))
{
objectiveInstance.CheckComplete();
break;
}
}
}
}
@ -425,7 +499,9 @@ namespace Server.Engines.MLQuests
var context = GetContext(pm);
if (context == null)
{
return;
}
var instances = context.QuestInstances;
@ -436,13 +512,16 @@ namespace Server.Engines.MLQuests
var instance = instances[i];
if (instance.ClaimReward)
{
continue;
}
/* A kill only counts for a single objective within a quest,
* but it can count for multiple quests. This is something not
* currently observable on OSI, so it is assumed behavior.
*/
foreach (var objective in instance.Objectives)
{
if (!objective.Expired && objective is KillObjectiveInstance kill)
{
type ??= mob.GetType();
@ -453,6 +532,7 @@ namespace Server.Engines.MLQuests
break;
}
}
}
}
}
@ -461,7 +541,9 @@ namespace Server.Engines.MLQuests
var context = GetContext(pm);
if (context == null)
{
return null;
}
var instances = context.QuestInstances;
MLQuestInstance deliverInstance = null;
@ -476,6 +558,7 @@ namespace Server.Engines.MLQuests
foreach (var objective in instance.Objectives)
// Note: On OSI, expired deliveries can still be completed. Bug?
{
if (!objective.Expired && objective is DeliverObjectiveInstance deliver &&
deliver.IsDestination(quester, questerType))
{
@ -492,6 +575,7 @@ namespace Server.Engines.MLQuests
break; // don't return, we may have to complete more deliveries
}
}
}
return deliverInstance;
@ -507,7 +591,9 @@ namespace Server.Engines.MLQuests
public static MLQuestContext GetOrCreateContext(PlayerMobile pm)
{
if (!Contexts.TryGetValue(pm, out var context))
{
Contexts[pm] = context = new MLQuestContext(pm);
}
return context;
}
@ -541,7 +627,9 @@ namespace Server.Engines.MLQuests
var instance = instances[i];
if (instance.Quester == quester)
{
instance.OnQuesterDeleted();
}
}
}
}
@ -549,7 +637,9 @@ namespace Server.Engines.MLQuests
public static void EventSink_QuestGumpRequest(Mobile m)
{
if (!Enabled || !(m is PlayerMobile pm))
{
return;
}
pm.SendGump(new QuestLogGump(pm));
}
@ -559,7 +649,9 @@ namespace Server.Engines.MLQuests
var quests = quester.MLQuests;
if (quests.Count == 0)
{
return null;
}
m_EligiblePool.Clear();
MLQuest fallback = null;
@ -567,7 +659,9 @@ namespace Server.Engines.MLQuests
foreach (var quest in quests)
{
if (quest.IsChainTriggered || context?.IsDoingQuest(quest) == true)
{
continue;
}
/*
* Save first quest that reaches the CanOffer call.
@ -576,7 +670,9 @@ namespace Server.Engines.MLQuests
fallback ??= quest;
if (quest.CanOffer(quester, pm, context, false))
{
m_EligiblePool.Add(quest);
}
}
return m_EligiblePool.Count == 0 ? fallback : m_EligiblePool.RandomElement();
@ -585,7 +681,9 @@ namespace Server.Engines.MLQuests
public static void TurnToFace(IQuestGiver quester, Mobile mob)
{
if (quester is Mobile m)
{
m.Direction = m.GetDirectionTo(mob);
}
}
public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc)
@ -593,11 +691,17 @@ namespace Server.Engines.MLQuests
TurnToFace(quester, pm);
if (quester is Mobile mobile)
{
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, pm.NetState);
}
else if (quester is Item item)
{
MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, SpeechColor);
}
else
{
pm.SendLocalizedMessage(cliloc);
}
}
public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc, string args)
@ -605,11 +709,17 @@ namespace Server.Engines.MLQuests
TurnToFace(quester, pm);
if (quester is Mobile mobile)
{
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, args, pm.NetState);
}
else if (quester is Item item)
{
MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, args, SpeechColor);
}
else
{
pm.SendLocalizedMessage(cliloc, args);
}
}
public static void Tell(IQuestGiver quester, PlayerMobile pm, string message)
@ -617,22 +727,34 @@ namespace Server.Engines.MLQuests
TurnToFace(quester, pm);
if (quester is Mobile mobile)
{
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, false, message, pm.NetState);
}
else if (quester is Item item)
{
MessageHelper.SendMessageTo(item, pm, message, SpeechColor);
}
else
{
pm.SendMessage(SpeechColor, message);
}
}
public static void TellDef(IQuestGiver quester, PlayerMobile pm, TextDefinition def)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
Tell(quester, pm, def.Number);
}
else if (def.String != null)
{
Tell(quester, pm, def.String);
}
}
public static void WriteQuestRef(IGenericWriter writer, MLQuest quest)
@ -645,12 +767,16 @@ namespace Server.Engines.MLQuests
var typeName = reader.ReadString();
if (typeName == null)
{
return null; // not serialized
}
var questType = AssemblyHandler.FindFirstTypeForName(typeName);
if (questType == null)
{
return null; // no longer a type
}
return FindQuest(questType);
}
@ -713,9 +839,13 @@ namespace Server.Engines.MLQuests
public override void Execute(CommandEventArgs e, object obj)
{
if (!(obj is PlayerMobile pm))
{
LogFailure("They have no ML quest context.");
}
else
{
e.Mobile.SendGump(new PropertiesGump(e.Mobile, GetOrCreateContext(pm)));
}
}
}
}

View file

@ -18,38 +18,38 @@ namespace Server.Engines.PartySystem
if (from == m)
{
@from.SendLocalizedMessage(1005439); // You cannot add yourself to a party.
from.SendLocalizedMessage(1005439); // You cannot add yourself to a party.
}
else if (p != null && p.Leader != from)
{
@from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader.
from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader.
}
else if (m.Party is Mobile)
{
}
else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity)
{
@from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates).
from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates).
}
else if (!m.Player && m.Body.IsHuman)
{
m.SayTo(@from, 1005443); // Nay, I would rather stay here and watch a nail rust.
m.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust.
}
else if (!m.Player)
{
@from.SendLocalizedMessage(1005444); // The creature ignores your offer.
from.SendLocalizedMessage(1005444); // The creature ignores your offer.
}
else if (mp != null && mp == p)
{
@from.SendLocalizedMessage(1005440); // This person is already in your party!
from.SendLocalizedMessage(1005440); // This person is already in your party!
}
else if (mp != null)
{
@from.SendLocalizedMessage(1005441); // This person is already in a party!
from.SendLocalizedMessage(1005441); // This person is already in a party!
}
else
{
Party.Invite(@from, m);
Party.Invite(from, m);
}
}
else

View file

@ -24,7 +24,7 @@ namespace Server
public IPoint3D Goal { get; }
public static void Initialize()
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("pathfinding.enable", true);
}

View file

@ -284,8 +284,8 @@ namespace Server.Engines.Plants
}
public bool IsUsableBy(Mobile from) =>
IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(@from) ||
RootParent is Item root && root.IsSecure && root.IsAccessibleTo(@from);
IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(from) ||
RootParent is Item root && root.IsSecure && root.IsAccessibleTo(from);
public override void OnDoubleClick(Mobile from)
{

View file

@ -95,7 +95,7 @@ namespace Server.Engines.Quests.Doom
);
Effects.PlaySound(loc, Map, 0x1FE);
Chyloth = new Chyloth { Direction = (Direction)(7 & (4 + (int)@from.GetDirectionTo(loc))) };
Chyloth = new Chyloth { Direction = (Direction)(7 & (4 + (int)from.GetDirectionTo(loc))) };
Chyloth.MoveToWorld(loc, Map);

View file

@ -22,7 +22,9 @@ namespace Server.Engines.VeteranRewards
get
{
if (m_Categories == null)
{
SetupRewardTables();
}
return m_Categories;
}
@ -33,7 +35,9 @@ namespace Server.Engines.VeteranRewards
get
{
if (m_Lists == null)
{
SetupRewardTables();
}
return m_Lists;
}
@ -45,15 +49,22 @@ namespace Server.Engines.VeteranRewards
for (var j = 0; j < entries.Count; ++j)
// RewardEntry entry = entries[j];
{
if (HasAccess(mob, entries[j]))
{
return true;
}
}
return false;
}
public static bool HasAccess(Mobile mob, RewardEntry entry)
{
if (Core.Expansion < entry.RequiredExpansion)
{
return false;
}
return HasAccess(mob, entry.List, out var _);
}
@ -77,7 +88,9 @@ namespace Server.Engines.VeteranRewards
ts = list.Age - totalTime;
if (ts <= TimeSpan.Zero)
{
return true;
}
return false;
}
@ -85,7 +98,9 @@ namespace Server.Engines.VeteranRewards
public static int GetRewardLevel(Mobile mob)
{
if (!(mob.Account is Account acct))
{
return 0;
}
return GetRewardLevel(acct);
}
@ -100,7 +115,9 @@ namespace Server.Engines.VeteranRewards
public static bool HasHalfLevel(Mobile mob)
{
if (!(mob.Account is Account acct))
{
return false;
}
return HasHalfLevel(acct);
}
@ -119,10 +136,14 @@ namespace Server.Engines.VeteranRewards
ComputeRewardInfo(mob, out var cur, out var max);
if (cur >= max)
{
return false;
}
if (!(mob.Account is Account acct))
{
return false;
}
// if (mob.AccessLevel < AccessLevel.GameMaster)
acct.SetTag("numRewardsChosen", (cur + 1).ToString());
@ -154,14 +175,22 @@ namespace Server.Engines.VeteranRewards
var tag = acct.GetTag("numRewardsChosen");
if (string.IsNullOrEmpty(tag))
{
cur = 0;
}
else
{
cur = Utility.ToInt32(tag);
}
if (level >= 6)
{
max = 9 + (level - 6) * 2;
}
else
{
max = 2 + level;
}
}
public static bool CheckIsUsableBy(Mobile from, Item item, object[] args = null)
@ -178,12 +207,16 @@ namespace Server.Engines.VeteranRewards
for (var j = 0; j < entries.Length; ++j)
{
if (entries[j].ItemType != type)
{
continue;
}
if (args == null && entries[j].Args.Length == 0)
{
if (isRelaxedRules && i <= 0 || HasAccess(from, list, out var ts))
{
return true;
}
from.SendLocalizedMessage(
1008126,
@ -195,17 +228,23 @@ namespace Server.Engines.VeteranRewards
}
if (args?.Length != entries[j].Args.Length)
{
continue;
}
var match = true;
for (var k = 0; match && k < args.Length; ++k)
{
match = args[k].Equals(entries[j].Args[k]);
}
if (match)
{
if (isRelaxedRules && i <= 0 || HasAccess(from, list, out var ts))
{
return true;
}
from.SendLocalizedMessage(
1008126,
@ -240,22 +279,30 @@ namespace Server.Engines.VeteranRewards
var entries = list.Entries;
for (var j = 0; j < entries.Length; ++j)
{
if (entries[j].ItemType == type)
{
if (args == null && entries[j].Args.Length == 0)
{
return i + 1;
}
if (args?.Length == entries[j].Args.Length)
{
var match = true;
for (var k = 0; match && k < args.Length; ++k)
{
match = args[k].Equals(entries[j].Args[k]);
}
if (match)
{
return i + 1;
}
}
}
}
}
// no entry?
@ -532,20 +579,27 @@ namespace Server.Engines.VeteranRewards
};
}
public static void Initialize()
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("vetRewards.enable", true);
SkillCapRewards = ServerConfiguration.GetOrUpdateSetting("vetRewards.skillCapRewards", true);
RewardInterval = ServerConfiguration.GetOrUpdateSetting("vetRewards.rewardInterval", TimeSpan.FromDays(30.0));
}
public static void Initialize()
{
if (Enabled)
{
EventSink.Login += EventSink_Login;
}
}
private static void EventSink_Login(Mobile m)
{
if (!m.Alive)
{
return;
}
ComputeRewardInfo(m, out var cur, out var max, out var level);
@ -555,9 +609,13 @@ namespace Server.Engines.VeteranRewards
level = Math.Clamp(level, 0, 4);
if (SkillCapRewards)
{
m.SkillsCap = 7000 + level * 50;
}
else
{
m.SkillsCap = 7000;
}
}
if (Core.ML && m is PlayerMobile pm && !pm.HasStatReward && HasHalfLevel(pm))
@ -567,7 +625,9 @@ namespace Server.Engines.VeteranRewards
}
if (cur < max)
{
m.SendGump(new RewardNoticeGump(m));
}
}
}

View file

@ -273,7 +273,7 @@ namespace Server.Gumps
from.SendGump(new WhoGump(from, m_Mobiles, m_Page));
}
else if (m == from || !m.Hidden || from.AccessLevel >= m.AccessLevel ||
m is PlayerMobile mobile && mobile.VisibilityList.Contains(@from))
m is PlayerMobile mobile && mobile.VisibilityList.Contains(from))
{
from.SendGump(new ClientGump(from, m.NetState));
}

View file

@ -234,7 +234,7 @@ namespace Server.Items
base.CheckHold(m, item, false, checkItems, plusItems, plusWeight);
public override bool CheckContentDisplay(Mobile from) =>
RootParent is BaseCreature creature && creature.Controlled && creature.ControlMaster == @from ||
RootParent is BaseCreature creature && creature.Controlled && creature.ControlMaster == from ||
base.CheckContentDisplay(from);
public override void Serialize(IGenericWriter writer)

View file

@ -180,8 +180,8 @@ namespace Server.Items
if (item?.Deleted != false)
continue;
if (item is BaseArmor armor && Resmelt(@from, armor, armor.Resource) ||
item is BaseWeapon weapon && Resmelt(@from, weapon, weapon.Resource) ||
if (item is BaseArmor armor && Resmelt(from, armor, armor.Resource) ||
item is BaseWeapon weapon && Resmelt(from, weapon, weapon.Resource) ||
item is DragonBardingDeed)
salvaged++;
else

View file

@ -102,10 +102,10 @@ namespace Server.Items
}
public static bool ValidateDefault(Mobile from, BaseBoard board) =>
!board.Deleted && (from.AccessLevel >= AccessLevel.GameMaster || @from.Alive &&
(board.IsChildOf(@from.Backpack) || !(board.RootParent is Mobile) &&
board.Map == @from.Map && @from.InRange(board.GetWorldLocation(), 1) &&
BaseHouse.FindHouseAt(board)?.IsOwner(@from) == true));
!board.Deleted && (from.AccessLevel >= AccessLevel.GameMaster || from.Alive &&
(board.IsChildOf(from.Backpack) || !(board.RootParent is Mobile) &&
board.Map == from.Map && from.InRange(board.GetWorldLocation(), 1) &&
BaseHouse.FindHouseAt(board)?.IsOwner(from) == true));
public class DefaultEntry : ContextMenuEntry
{

View file

@ -71,7 +71,7 @@ namespace Server.Items
var contains = false;
if (house == null && m_BeforeChangeover ||
house?.IsOwner(@from) == true && (contains = house.Addons.Contains(this)))
house?.IsOwner(from) == true && (contains = house.Addons.Contains(this)))
{
Effects.PlaySound(GetWorldLocation(), Map, 0x3B3);
from.SendLocalizedMessage(500461); // You destroy the item.

View file

@ -69,7 +69,7 @@ namespace Server.Items
{
from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil.
}
else if (from.Map == GetTargetMap() || @from.Map != Map.Trammel && @from.Map != Map.Felucca)
else if (from.Map == GetTargetMap() || from.Map != Map.Trammel && from.Map != Map.Felucca)
{
from.SendLocalizedMessage(1005401); // You cannot bury the stone here.
}

View file

@ -49,7 +49,7 @@ namespace Server.Items
{
var root = item.RootParent;
if (root != null && root != @from || item.Parent == from)
if (root != null && root != from || item.Parent == from)
{
message = "You decide that item's current location is too awkward to get an accurate result.";
}

View file

@ -157,8 +157,8 @@ namespace Server.Items
public virtual void BeginConfirmation(Mobile from)
{
if (IsInTown(@from.Location, @from.Map) && !IsInTown(Target, TargetMap) ||
@from.Map != Map.Felucca && TargetMap == Map.Felucca && ShowFeluccaWarning)
if (IsInTown(from.Location, from.Map) && !IsInTown(Target, TargetMap) ||
from.Map != Map.Felucca && TargetMap == Map.Felucca && ShowFeluccaWarning)
{
if (from.AccessLevel == AccessLevel.Player || !from.Hidden)
from.Send(new PlaySound(0x20E, from.Location));

View file

@ -188,8 +188,8 @@ namespace Server.Items
var toExplode = eable.Where(
o =>
{
if (!(o is Mobile mobile) || @from != null &&
(!SpellHelper.ValidIndirectTarget(@from, mobile) || !@from.CanBeHarmful(mobile, false)))
if (!(o is Mobile mobile) || from != null &&
(!SpellHelper.ValidIndirectTarget(from, mobile) || !from.CanBeHarmful(mobile, false)))
return o is BaseExplosionPotion && o != this;
++toDamage;

View file

@ -104,7 +104,7 @@ namespace Server.Items
m =>
{
if (from == m || !SpellHelper.ValidIndirectTarget(from, m) || !from.CanBeHarmful(m, false)
|| Core.AOS && !@from.InLOS(m))
|| Core.AOS && !from.InLOS(m))
return false;
if (m.Player)

View file

@ -111,7 +111,7 @@ namespace Server.Items
return;
}
if ((item.IsChildOf(from.Backpack) || Core.ML && item.Parent == @from) &&
if ((item.IsChildOf(from.Backpack) || Core.ML && item.Parent == from) &&
m_Powder.IsChildOf(from.Backpack))
{
var origMaxHP = wearable.MaxHitPoints;

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

View file

@ -232,8 +232,8 @@ namespace Server.Mobiles
if (from.InRange(this, 1))
{
var canAccess = from.AccessLevel >= AccessLevel.GameMaster
|| Controlled && ControlMaster == @from
|| Summoned && SummonMaster == @from;
|| Controlled && ControlMaster == from
|| Summoned && SummonMaster == from;
if (canAccess)
{

File diff suppressed because it is too large Load diff

View file

@ -1087,7 +1087,7 @@ namespace Server.Mobiles
public virtual bool CheckVendorAccess(Mobile from) =>
Region.GetRegion<GuardedRegion>()?.CheckVendorAccess(this, from) != false ||
Region != @from.Region && @from.Region.GetRegion<GuardedRegion>()?.CheckVendorAccess(this, @from) != false;
Region != from.Region && from.Region.GetRegion<GuardedRegion>()?.CheckVendorAccess(this, from) != false;
public override void Serialize(IGenericWriter writer)
{

View file

@ -127,7 +127,7 @@ namespace Server.Multis
{
if (okay && Owner != null && Owner.Owner == null && Owner.DecayLevel != DecayLevel.DemolitionPending)
{
var canClaim = Owner.CoOwners?.Count > 0 && Owner.IsCoOwner(@from) || Owner.IsFriend(from);
var canClaim = Owner.CoOwners?.Count > 0 && Owner.IsCoOwner(from) || Owner.IsFriend(from);
if (canClaim && !BaseHouse.HasAccountHouse(from))
{

View file

@ -164,8 +164,8 @@ namespace Server.SkillHandlers
else if (target is Mobile targ)
{
if (targ == from || targ is BaseCreature bc &&
(bc.BardImmune || !@from.CanBeHarmful(bc, false)) &&
bc.ControlMaster != @from)
(bc.BardImmune || !from.CanBeHarmful(bc, false)) &&
bc.ControlMaster != from)
{
from.SendLocalizedMessage(1049535); // A song of discord would have no effect on that.
}

View file

@ -94,8 +94,8 @@ namespace Server.SkillHandlers
}
else
{
if (Core.ML && isOwner || @from.CheckTargetSkill(SkillName.RemoveTrap, trap, 80.0, 100.0) &&
@from.CheckTargetSkill(SkillName.Tinkering, trap, 80.0, 100.0))
if (Core.ML && isOwner || from.CheckTargetSkill(SkillName.RemoveTrap, trap, 80.0, 100.0) &&
from.CheckTargetSkill(SkillName.Tinkering, trap, 80.0, 100.0))
{
from.PrivateOverheadMessage(
MessageType.Regular,