Updates Packets & Randomizer (#43)

* Fixes a bug with the main loop. Removes unnecessary optimizations for RDRand.

* WIP - Rewriting packets.

* Cleanup and updates README

* Converts more packets

* Fixes header

* Converts Effects packets.

* Forgot the send command

* Adds the start of containers packets.

* Adds message packets with caching

* Extends the send methods

* Starts to add Acquire methods

* Converted the packets

* Cleanup

* Cleanup

* Adds more packets

* Adds more packets

* Fixes clearing arrays from pool. Adds Mobile Incoming

* Converts more packets.

* Moves more packets

* Moves more packets

* Test compression

* Merges

* Migrating to an idiomatic syntax that also supports compression, and proxying.

* Optimize the stack alloc. Changes attributes

* Converted container packets

* Visual Studio doesn't auto save files. I am still getting used to subpar IDEs.

* Adds static packet caching. Will profile later. Converts more packets

* Fixes packets and changes how compression is configured

* WIP - Adds basics for Gumps. Not finished though.

* Fix file

* Fixes formatting

* Changed SpanWriter to be more idiomatic.

* Fixes Span vs RawSpan and missing stackallocs

* Converts over some more gumps

* WIP - Deletes 32bit support.

* Drops RDRand32 support.

* Fixes gump compilation

* Converting gump components

* Removes old huffman compression function

* Revert signature for backwards compatibility

* WIP - Converting more gump components

* Creates ArraySet for the strings. Updates AppendTo to reference that.

* Converts the maining gump components

* Cleans up gump components

* Cleans up directives

* Cleans up ArraySet and moves it. Adds null-coalescing-assignment

* Cleanup, Target Packets, and C# 8 changes.

* Removed OPL Packet

* World packets

* Fixing packet uses

* Cleans up code. Fixes packet uses in various places.

* More cleanup for packets

* Code cleanup

* Converts more packet uses and cleans up more code

* More code cleanup

* Finishes fixing the packets in Item

* Updates secure trade packets

* Updates core and gets it to compile.

* Moved packets to scripts. Fixed account handler use of packets

* Code cleanup

* Updates chat packets

* Code cleanuo

* Adds party packets, but need to implement them.

* Party packets WIP

* Finishes party packets

* Rearrange movement namespaces and classes

* Finishes plant packets

* Code Formatting

* Fixes moving effects

* Code cleanup, eliminates equipinfo

* Adds more packets. Fixes bugs with various packets.

* Finishes mahjon packets

* Fixes mahjong packet

* Code cleanup

* Finishes mahjong packets

* Adds Map packets

* Add multifacet maps and charts

* Cleans up some packets with UTF8

* Optimizes packets

* Cleans up more packets. Moves the MessageHelper

* Removes assistant support. Removes extended protocol. Incorporates MapUO packets as normal packets.

* Updates protocol extensions packet receiver

* Fixes a few bugs. Fixes a few more packets.

* Code cleanup and fixing more packets

* Fixes packet effects

* Cleaned up more code

* Buff Icon cleanup

* Removed unused constructors

* Code Cleanup. Adds BoatHS Packets

* Moves house files. Updates house foundation packets.

* Deployment cleanup

* Fixes:

* Code cleanup

* More code cleanup

* More code cleanup

* Cleaned up BaseHouse

* Enforces styling

* Converts foreach to linq where possible.

* Dont need that

* Goals/Readme updates

* Removes 32bit support at the highest level. Turns on HRT by default.

* Code cleanup. Fixes extended features packet.

* Fixes various bugs

* Code cleanup

* Code cleanup

* Code cleanup. Fixes gump X/Y assignment.

* Code cleanup using |= operator

* More code cleanup

* Cleanup

* Fixes spacing issues. Thanks Visual Studio. You suck.

* Compiler error

* Fixes NPE from RunUO 2.7

* Renames ScriptCompiler to AssemblyHandler. Fixes packets. Updates README

* Fixes more packets. Stupid trailing nulls.

* Fixes various bugs.

* Fixes for gumps

* Fixes more gump stuff. Going to split it out later since it is getting insane

* Recoded the gump writing

* WIP

* *Added output path of scripts project to dev branch
*Activated debugging in code
This commit is contained in:
Kamron Batman 2019-11-11 03:40:16 -08:00 committed by 3HMonkey
parent 7aa8fd3df1
commit 179cb50557
588 changed files with 10843 additions and 16177 deletions

View file

@ -9,7 +9,7 @@ using Server.Spells.Seventh;
namespace Server
{
public class AOS
public static class AOS
{
public static void DisableStatInfluences()
{
@ -1019,8 +1019,7 @@ namespace Server
if (!GetValues(i, out SkillName skill, out double bonus))
continue;
if (m_Mods == null)
m_Mods = new List<SkillMod>();
m_Mods ??= new List<SkillMod>();
SkillMod sk = new DefaultSkillMod(skill, true, bonus);
sk.ObeyCap = true;

View file

@ -3,7 +3,7 @@ using Server.Accounting;
namespace Server.Misc
{
public class AccountPrompt
public static class AccountPrompt
{
public static void Initialize()
{
@ -22,8 +22,7 @@ namespace Server.Misc
Console.Write("Password: ");
string password = Console.ReadLine();
Account a = new Account(username, password);
a.AccessLevel = AccessLevel.Owner;
Account a = new Account(username, password) {AccessLevel = AccessLevel.Owner};
Console.WriteLine("Account created.");
}
@ -36,4 +35,4 @@ namespace Server.Misc
}
}
}
}
}

View file

@ -1,6 +1,6 @@
namespace Server.Misc
{
public class Animations
public static class Animations
{
public static void Initialize()
{
@ -28,4 +28,4 @@ namespace Server.Misc
from.Animate(action, 5, 1, true, false, 0);
}
}
}
}

View file

@ -4,7 +4,7 @@ using Server.Network;
namespace Server.Misc
{
public class AttackMessage
public static class AttackMessage
{
private const string AggressorFormat = "You are attacking {0}!";
private const string AggressedFormat = "{0} is attacking you!";
@ -59,4 +59,4 @@ namespace Server.Misc
return false;
}
}
}
}

View file

@ -141,7 +141,7 @@ namespace Server.Misc
string saves = Path.Combine(Core.BaseDirectory, "Saves");
if (Directory.Exists(saves))
Directory.Move(saves, FormatDirectory(root, m_Backups[m_Backups.Length - 1], GetTimeStamp()));
Directory.Move(saves, FormatDirectory(root, m_Backups[^1], GetTimeStamp()));
}
private static DirectoryInfo Match(string[] paths, string match)
@ -181,4 +181,4 @@ namespace Server.Misc
return $"{now.Day}-{now.Month}-{now.Year} {now.Hour}-{now.Minute:D2}-{now.Second:D2}";
}
}
}
}

View file

@ -1,6 +1,6 @@
namespace Server.Misc
{
public class Broadcasts
public static class Broadcasts
{
public static void Initialize()
{

View file

@ -1,4 +1,5 @@
using System;
using Server.Buffers;
using Server.Mobiles;
using Server.Network;
@ -18,13 +19,11 @@ namespace Server
};
}
#region Properties
public BuffIcon ID{ get; }
public int TitleCliloc{ get; }
public int Title{ get; }
public int SecondaryCliloc{ get; }
public TextDefinition Description{ get; }
public TimeSpan TimeLength{ get; }
@ -32,50 +31,30 @@ namespace Server
public Timer Timer{ get; }
public bool RetainThroughDeath{ get; }
public bool RetainThroughDeath { get; }
public TextDefinition Args{ get; }
#endregion
#region Constructors
public BuffInfo(BuffIcon iconID, int titleCliloc)
: this(iconID, titleCliloc, titleCliloc + 1)
public BuffInfo(BuffIcon iconId, int title, TimeSpan time = default, Mobile m = null) :
this(iconId, title, title + 1, time, m)
{
}
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc)
{
ID = iconID;
TitleCliloc = titleCliloc;
SecondaryCliloc = secondaryCliloc;
}
public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m)
: this(iconID, titleCliloc, titleCliloc + 1, length, m)
public BuffInfo(BuffIcon iconId, int title, string args, TimeSpan time = default, Mobile m = null) :
this(iconId, title, title + 1, args, time, m)
{
}
//Only the timed one needs to Mobile to know when to automagically remove it.
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m)
: this(iconID, titleCliloc, secondaryCliloc)
public BuffInfo(BuffIcon iconId, int title, int desc, TimeSpan time = default, Mobile m = null) :
this(iconId, title, desc, null, time, m)
{
TimeLength = length;
TimeStart = DateTime.UtcNow;
Timer = Timer.DelayCall(length, delegate
{
if (!(m is PlayerMobile pm))
return;
pm.RemoveBuff(this);
});
}
public BuffInfo(BuffIcon iconId, int title, string args, bool retain, Mobile m = null) :
this(iconId, title, title + 1, args, DateTime.UtcNow, default, retain, m)
{
}
public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args)
: this(iconID, titleCliloc, titleCliloc + 1, args)
public BuffInfo(BuffIcon iconId, int title, int desc, string args, TimeSpan time, Mobile m = null) :
this(iconId, title, new TextDefinition(desc, args), DateTime.UtcNow, time, false, m)
{
}
@ -83,8 +62,8 @@ namespace Server
: this(iconID, titleCliloc, secondaryCliloc) =>
Args = args;
public BuffInfo(BuffIcon iconID, int titleCliloc, bool retainThroughDeath)
: this(iconID, titleCliloc, titleCliloc + 1, retainThroughDeath)
public BuffInfo(BuffIcon iconId, int title, int desc, string args, TimeSpan time = default, bool retain = false,
Mobile m = null) : this(iconId, title, new TextDefinition(desc, args), DateTime.UtcNow, time, retain, m)
{
}
@ -92,9 +71,17 @@ namespace Server
: this(iconID, titleCliloc, secondaryCliloc) =>
RetainThroughDeath = retainThroughDeath;
public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args, bool retainThroughDeath)
: this(iconID, titleCliloc, titleCliloc + 1, args, retainThroughDeath)
public BuffInfo(BuffIcon iconId, int title, TextDefinition desc, DateTime start = default, TimeSpan time = default, bool retain = false,
Mobile m = null)
{
ID = iconId;
Title = title;
Description = desc;
TimeLength = time;
TimeStart = start;
RetainThroughDeath = retain;
if (m is PlayerMobile pm)
Timer = Timer.DelayCall(time, playermobile => playermobile.RemoveBuff(this), pm);
}
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, bool retainThroughDeath)
@ -131,20 +118,17 @@ namespace Server
public static void AddBuff(Mobile m, BuffInfo b)
{
if (m is PlayerMobile pm)
pm.AddBuff(b);
(m as PlayerMobile)?.AddBuff(b);
}
public static void RemoveBuff(Mobile m, BuffInfo b)
{
if (m is PlayerMobile pm)
pm.RemoveBuff(b);
(m as PlayerMobile)?.RemoveBuff(b);
}
public static void RemoveBuff(Mobile m, BuffIcon b)
{
if (m is PlayerMobile pm)
pm.RemoveBuff(b);
(m as PlayerMobile)?.RemoveBuff(b);
}
#endregion
@ -208,80 +192,68 @@ namespace Server
Fly
}
public sealed class AddBuffPacket : Packet
public static class BuffPackets
{
public AddBuffPacket(Mobile m, BuffInfo info)
: this(m, info.ID, info.TitleCliloc, info.SecondaryCliloc, info.Args,
info.TimeStart != DateTime.MinValue ? info.TimeStart + info.TimeLength - DateTime.UtcNow : TimeSpan.Zero)
public static void SendAddBuff(Mobile m, BuffInfo info)
{
SendAddBuff(m.NetState, m.Serial, info.ID, info.Title, info.Description,
info.TimeStart != DateTime.MinValue ? info.TimeStart + info.TimeLength - DateTime.UtcNow : TimeSpan.Zero);
}
public static void SendAddBuff(NetState ns, Serial m, BuffIcon iconID, int title, TextDefinition desc, TimeSpan time)
{
if (ns == null)
return;
string args = desc?.String ?? "";
int length = 44 + args.Length * 2;
SpanWriter writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)length); // Dynamic Length
writer.Write(m);
writer.Write((short)iconID); //ID
writer.Write((short)0x1); //Type 0 for removal. 1 for add 2 for Data
writer.Position += 4;
writer.Write((short)iconID); //ID
writer.Write((short)0x01); //Type 0 for removal. 1 for add 2 for Data
writer.Position += 4;
writer.Write((short)Math.Max(time.TotalSeconds, 0)); //Time in seconds
writer.Position += 3;
writer.Write(title);
writer.Write(desc?.Number ?? 0);
writer.Position += 5;
writer.Write((byte)0x1); // Start indicator?
writer.Position += 2;
writer.WriteLittleUniNull(args);
ns.Send(writer.Span);
}
public AddBuffPacket(Mobile mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args,
TimeSpan length)
: base(0xDF)
public static void SendRemoveBuffPacket(NetState ns, Serial m, int icon)
{
bool hasArgs = args != null;
SpanWriter writer = new SpanWriter(stackalloc byte[13]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)13); // Dynamic Length
EnsureCapacity(hasArgs ? 48 + args.ToString().Length * 2 : 44);
m_Stream.Write(mob.Serial);
writer.Write(m);
writer.Write((short)icon); //ID
writer.Write((short)0x0); //Type 0 for removal. 1 for add 2 for Data
m_Stream.Write((short)iconID); //ID
m_Stream.Write((short)0x1); //Type 0 for removal. 1 for add 2 for Data
writer.Position += 4;
m_Stream.Fill(4);
m_Stream.Write((short)iconID); //ID
m_Stream.Write((short)0x01); //Type 0 for removal. 1 for add 2 for Data
m_Stream.Fill(4);
if (length < TimeSpan.Zero)
length = TimeSpan.Zero;
m_Stream.Write((short)length.TotalSeconds); //Time in seconds
m_Stream.Fill(3);
m_Stream.Write(titleCliloc);
m_Stream.Write(secondaryCliloc);
if (!hasArgs)
{
//m_Stream.Fill( 2 );
m_Stream.Fill(10);
}
else
{
m_Stream.Fill(4);
m_Stream.Write((short)0x1); //Unknown -> Possibly something saying 'hey, I have more data!'?
m_Stream.Fill(2);
//m_Stream.WriteLittleUniNull( "\t#1018280" );
m_Stream.WriteLittleUniNull($"\t{args}");
m_Stream.Write((short)0x1); //Even more Unknown -> Possibly something saying 'hey, I have more data!'?
m_Stream.Fill(2);
}
ns.Send(writer.Span);
}
}
public sealed class RemoveBuffPacket : Packet
{
public RemoveBuffPacket(Mobile mob, BuffInfo info)
: this(mob, info.ID)
{
}
public RemoveBuffPacket(Mobile mob, BuffIcon iconID)
: base(0xDF)
{
EnsureCapacity(13);
m_Stream.Write(mob.Serial);
m_Stream.Write((short)iconID); //ID
m_Stream.Write((short)0x0); //Type 0 for removal. 1 for add 2 for Data
m_Stream.Fill(4);
}
}
}
}

View file

@ -7,7 +7,7 @@ using Server.Network;
namespace Server.Misc
{
public class CharacterCreation
public static class CharacterCreation
{
private static readonly CityInfo m_NewHavenInfo =
new CityInfo("New Haven", "The Bountiful Harvest Inn", 3503, 2574, 14, Map.Trammel);
@ -22,15 +22,8 @@ namespace Server.Misc
private static void AddBackpack(Mobile m)
{
Container pack = m.Backpack;
if (pack == null)
{
pack = new Backpack();
pack.Movable = false;
m.AddItem(pack);
}
if (m.Backpack == null)
m.AddItem(new Backpack {Movable = false});
PackItem(new RedBook("a book", m.Name, 20, true));
PackItem(new Gold(1000)); // Starting gold can be customized here
@ -52,16 +45,8 @@ namespace Server.Misc
item.Location = new Point3D(x, y, 0);
}
private static Item MakePotionKeg(PotionEffect type, int hue)
{
PotionKeg keg = new PotionKeg();
keg.Held = 100;
keg.Type = type;
keg.Hue = hue;
return MakeNewbie(keg);
}
private static Item MakePotionKeg(PotionEffect type, int hue) =>
MakeNewbie(new PotionKeg {Held = 100, Type = type, Hue = hue});
private static void FillBankAOS(Mobile m)
{
@ -75,11 +60,8 @@ namespace Server.Misc
m.StatCap = 250;
Container cont;
// Begin box of money
cont = new WoodenBox();
Container cont = new WoodenBox();
cont.ItemID = 0xE7D;
cont.Hue = 0x489;
@ -97,8 +79,7 @@ namespace Server.Misc
// Begin bag of potion kegs
cont = new Backpack();
cont.Name = "Various Potion Kegs";
cont = new Backpack {Name = "Various Potion Kegs"};
PlaceItemIn(cont, 45, 149, MakePotionKeg(PotionEffect.CureGreater, 0x2D));
PlaceItemIn(cont, 69, 149, MakePotionKeg(PotionEffect.HealGreater, 0x499));
@ -113,8 +94,7 @@ namespace Server.Misc
// Begin bag of tools
cont = new Bag();
cont.Name = "Tool Bag";
cont = new Bag {Name = "Tool Bag"};
PlaceItemIn(cont, 30, 35, new TinkerTools(1000));
PlaceItemIn(cont, 60, 35, new HousePlacementTool());
@ -145,8 +125,7 @@ namespace Server.Misc
// Begin bag of archery ammo
cont = new Bag();
cont.Name = "Bag Of Archery Ammo";
cont = new Bag {Name = "Bag Of Archery Ammo"};
PlaceItemIn(cont, 48, 76, new Arrow(5000));
PlaceItemIn(cont, 72, 76, new Bolt(5000));
@ -156,8 +135,7 @@ namespace Server.Misc
// Begin bag of treasure maps
cont = new Bag();
cont.Name = "Bag Of Treasure Maps";
cont = new Bag {Name = "Bag Of Treasure Maps"};
PlaceItemIn(cont, 30, 35, new TreasureMap(1, Map.Trammel));
PlaceItemIn(cont, 45, 35, new TreasureMap(2, Map.Trammel));
@ -181,9 +159,7 @@ namespace Server.Misc
// Begin bag of raw materials
cont = new Bag();
cont.Hue = 0x835;
cont.Name = "Raw Materials Bag";
cont = new Bag {Hue = 0x835, Name = "Raw Materials Bag"};
PlaceItemIn(cont, 92, 60, new BarbedLeather(5000));
PlaceItemIn(cont, 92, 68, new HornedLeather(5000));
@ -216,9 +192,7 @@ namespace Server.Misc
// Begin bag of spell casting stuff
cont = new Backpack();
cont.Hue = 0x480;
cont.Name = "Spell Casting Stuff";
cont = new Backpack {Hue = 0x480, Name = "Spell Casting Stuff"};
PlaceItemIn(cont, 45, 105, new Spellbook(ulong.MaxValue));
PlaceItemIn(cont, 65, 105, new NecromancerSpellbook((ulong)0xFFFF));
@ -234,8 +208,7 @@ namespace Server.Misc
toHue.Hue = 0x2D;
PlaceItemIn(cont, 45, 150, toHue);
toHue = new BagOfNecroReagents(150);
toHue.Hue = 0x488;
toHue = new BagOfNecroReagents(150) {Hue = 0x488};
PlaceItemIn(cont, 65, 150, toHue);
PlaceItemIn(cont, 140, 150, new BagOfAllReagents(500));
@ -250,9 +223,7 @@ namespace Server.Misc
// Begin bag of ethereals
cont = new Backpack();
cont.Hue = 0x490;
cont.Name = "Bag Of Ethy's!";
cont = new Backpack {Hue = 0x490, Name = "Bag Of Ethy's!"};
PlaceItemIn(cont, 45, 66, new EtherealHorse());
PlaceItemIn(cont, 69, 82, new EtherealOstard());
@ -268,9 +239,7 @@ namespace Server.Misc
// Begin first bag of artifacts
cont = new Backpack();
cont.Hue = 0x48F;
cont.Name = "Bag of Artifacts";
cont = new Backpack {Hue = 0x48F, Name = "Bag of Artifacts"};
PlaceItemIn(cont, 45, 66, new TitansHammer());
PlaceItemIn(cont, 69, 82, new InquisitorsResolution());
@ -282,9 +251,7 @@ namespace Server.Misc
// Begin second bag of artifacts
cont = new Backpack();
cont.Hue = 0x48F;
cont.Name = "Bag of Artifacts";
cont = new Backpack {Hue = 0x48F, Name = "Bag of Artifacts"};
PlaceItemIn(cont, 45, 66, new GauntletsOfNobility());
PlaceItemIn(cont, 69, 82, new MidnightBracers());
@ -324,10 +291,7 @@ namespace Server.Misc
// End second bag of artifacts
// Begin bag of minor artifacts
cont = new Backpack();
cont.Hue = 0x48F;
cont.Name = "Bag of Minor Artifacts";
cont = new Backpack {Hue = 0x48F, Name = "Bag of Minor Artifacts"};
PlaceItemIn(cont, 45, 66, new LunaLance());
PlaceItemIn(cont, 69, 82, new VioletCourage());
@ -368,9 +332,7 @@ namespace Server.Misc
if (Core.SE)
{
cont = new Bag();
cont.Hue = 0x501;
cont.Name = "Tokuno Minor Artifacts";
cont = new Bag {Hue = 0x501, Name = "Tokuno Minor Artifacts"};
PlaceItemIn(cont, 42, 70, new Exiler());
PlaceItemIn(cont, 38, 53, new HanzosBow());
@ -398,8 +360,7 @@ namespace Server.Misc
if (Core.SE) //This bag came only after SE.
{
cont = new Bag();
cont.Name = "Bag of Bows";
cont = new Bag {Name = "Bag of Bows"};
PlaceItemIn(cont, 31, 84, new Bow());
PlaceItemIn(cont, 78, 74, new CompositeBow());
@ -432,11 +393,7 @@ namespace Server.Misc
bank.DropItem(new BankCheck(1000000));
// Full spellbook
Spellbook book = new Spellbook();
book.Content = ulong.MaxValue;
bank.DropItem(book);
bank.DropItem(new Spellbook {Content = ulong.MaxValue});
Bag bag = new Bag();
@ -641,10 +598,7 @@ namespace Server.Misc
newChar.Female = args.Female;
//newChar.Body = newChar.Female ? 0x191 : 0x190;
if (Core.Expansion >= args.Race.RequiredExpansion)
newChar.Race = args.Race; //Sets body
else
newChar.Race = Race.DefaultRace;
newChar.Race = Core.Expansion >= args.Race.RequiredExpansion ? args.Race : Race.DefaultRace;
//newChar.Hue = Utility.ClipSkinHue( args.Hue & 0x3FFF ) | 0x8000;
newChar.Hue = newChar.Race.ClipSkinHue(args.Hue & 0x3FFF) | 0x8000;
@ -692,12 +646,7 @@ namespace Server.Misc
if (TestCenter.Enabled)
FillBankbox(newChar);
if (young)
{
NewPlayerTicket ticket = new NewPlayerTicket();
ticket.Owner = newChar;
newChar.BankBox.DropItem(ticket);
}
if (young) newChar.BankBox.DropItem(new NewPlayerTicket {Owner = newChar});
CityInfo city = GetStartLocation(args, young);
@ -710,19 +659,8 @@ namespace Server.Misc
new WelcomeTimer(newChar).Start();
}
public static bool VerifyProfession(int profession)
{
if (profession < 0)
return false;
if (profession < 4)
return true;
if (Core.AOS && profession < 6)
return true;
if (Core.SE && profession < 8)
return true;
return false;
}
public static bool VerifyProfession(int profession) =>
profession >= 0 && (profession < 4 || Core.AOS && profession < 6 || Core.SE && profession < 8);
private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool isYoung)
{
@ -754,9 +692,7 @@ namespace Server.Misc
break;
}
case 5: //Paladin
{
return m_NewHavenInfo;
}
case 6: //Samurai
{
if ((flags & ClientFlags.Tokuno) != 0)
@ -795,10 +731,7 @@ namespace Server.Misc
}
}
if (useHaven)
return m_NewHavenInfo;
return args.City;
return useHaven ? m_NewHavenInfo : args.City;
}
private static void FixStats(ref int str, ref int dex, ref int intel, int max)
@ -1164,7 +1097,7 @@ namespace Server.Misc
if (m_Mobile?.EquipItem(item) == true)
return;
Container pack = m_Mobile.Backpack;
Container pack = m_Mobile?.Backpack;
if (!mustEquip && pack != null)
pack.DropItem(item);
@ -1177,7 +1110,7 @@ namespace Server.Misc
if (!Core.AOS)
item.LootType = LootType.Newbied;
Container pack = m_Mobile.Backpack;
Container pack = m_Mobile?.Backpack;
if (pack != null)
pack.DropItem(item);
@ -1733,18 +1666,18 @@ namespace Server.Misc
private class BadStartMessage : Timer
{
private int m_Message;
private Mobile m_Mobile;
private Mobile m_From;
public BadStartMessage(Mobile m, int message) : base(TimeSpan.FromSeconds(3.5))
{
m_Mobile = m;
m_From = m;
m_Message = message;
Start();
}
protected override void OnTick()
{
m_Mobile.SendLocalizedMessage(m_Message);
m_From.SendLocalizedMessage(m_Message);
}
}
}

View file

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Mobiles;
using Server.Multis;
namespace Server.Misc
@ -43,9 +43,7 @@ namespace Server.Misc
if (relEntity.Entity is Item item1)
validItems.Add(item1);
foreach (VendorInventory inventory in house.VendorInventories)
foreach (Item subItem in inventory.Items)
validItems.Add(subItem);
validItems.AddRange(house.VendorInventories.SelectMany(inventory => inventory.Items));
}
else if (item is BankBox box)
{

View file

@ -1,4 +1,4 @@
using Server.Accounting;
using Server.Items;
using Server.Network;
namespace Server
@ -37,4 +37,4 @@ namespace Server
}
}
}
}
}

View file

@ -390,7 +390,7 @@ namespace Server
public static bool IsFrame(int id, int[] list)
{
if (id > list[list.Length - 1])
if (id > list[^1])
return false;
for (int i = 0; i < list.Length; ++i)

View file

@ -6,17 +6,17 @@ using System.Threading;
namespace Server.Misc
{
public class Email
public static class Email
{
/* In order to support emailing, fill in EmailServer and FromAddress:
* Example:
* public static readonly string EmailServer = "mail.domain.com";
* public static readonly string FromAddress = "runuo@domain.com";
*
*
* If you want to add crash reporting emailing, fill in CrashAddresses:
* Example:
* public static readonly string CrashAddresses = "first@email.here,second@email.here,third@email.here";
*
*
* If you want to add speech log page emailing, fill in SpeechLogPageAddresses:
* Example:
* public static readonly string SpeechLogPageAddresses = "first@email.here,second@email.here,third@email.here";
@ -62,7 +62,7 @@ namespace Server.Misc
// .NET relies on the MTA to generate Message-ID header. Not all MTAs will add this header.
DateTime now = DateTime.UtcNow;
string messageID = $"<{now.ToString("yyyyMMdd")}.{now.ToString("HHmmssff")}@{EmailServer}>";
string messageID = $"<{now:yyyyMMdd}.{now:HHmmssff}@{EmailServer}>";
message.Headers.Add("Message-ID", messageID);
message.Headers.Add("X-Mailer", "RunUO");
@ -89,10 +89,8 @@ namespace Server.Misc
{
MailMessage message = (MailMessage)state;
if (Send(message))
Console.WriteLine("Sent e-mail '{0}' to '{1}'.", message.Subject, message.To);
else
Console.WriteLine("Failure sending e-mail '{0}' to '{1}'.", message.Subject, message.To);
Console.WriteLine(Send(message) ? "Sent e-mail '{0}' to '{1}'." : "Failure sending e-mail '{0}' to '{1}'.",
message.Subject, message.To);
}
}
}
}

View file

@ -4,7 +4,7 @@ namespace Server.Misc
{
// This fastwalk detection is no longer required
// As of B36 PlayerMobile implements movement packet throttling which more reliably controls movement speeds
public class Fastwalk
public static class Fastwalk
{
private static int MaxSteps = 4; // Maximum number of queued steps until fastwalk is detected
private static bool Enabled = false; // Is fastwalk detection enabled?
@ -30,4 +30,4 @@ namespace Server.Misc
Console.WriteLine("Client: {0}: Fast movement detected (name={1})", e.NetState, e.NetState.Mobile.Name);
}
}
}
}

View file

@ -19,26 +19,19 @@ namespace Server.Misc
public static Point2D ArcPoint(Point3D loc, int radius, int angle)
{
int sideA, sideB;
if (angle < 0)
angle = 0;
if (angle > 90)
angle = 90;
sideA = (int)Math.Round(radius * Math.Sin(DegreesToRadians(angle)));
sideB = (int)Math.Round(radius * Math.Cos(DegreesToRadians(angle)));
int sideA = (int)Math.Round(radius * Math.Sin(DegreesToRadians(angle)));
int sideB = (int)Math.Round(radius * Math.Cos(DegreesToRadians(angle)));
return new Point2D(loc.X - sideB, loc.Y - sideA);
}
public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect)
{
Circle2D(loc, map, radius, effect, 0, 360);
}
public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect, int angleStart, int angleEnd)
public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect, int angleStart = 0, int angleEnd = 360)
{
if (angleStart < 0 || angleStart > 360)
angleStart = 0;
@ -147,13 +140,9 @@ namespace Server.Misc
withinBounds = false;
}
else if (pointQuadrant == start.Quadrant && (x < startX || y > startY))
{
withinBounds = false;
}
else if (pointQuadrant == end.Quadrant && (x > endX || y < endY))
{
withinBounds = false;
}
return opposite ? !withinBounds : withinBounds;
}
@ -218,4 +207,4 @@ namespace Server.Misc
public int Quadrant{ get; }
}
}
}
}

View file

@ -129,9 +129,7 @@ namespace Server.Items
Effects.SendMovingEffect(from, targ, 0x36E4, 7, 0, false, true, 0x47F);
}
else
{
from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying.
}
}
else
{
@ -140,11 +138,9 @@ namespace Server.Items
}
}
else
{
from.SendLocalizedMessage(
1005577); // You can only throw a snowball at something that can throw one back.
}
}
}
}
}
}

View file

@ -32,7 +32,7 @@ namespace Server.Guilds
public class RankDefinition
{
public static RankDefinition[] Ranks =
public static readonly RankDefinition[] Ranks =
{
new RankDefinition(1062963, 0, RankFlags.None), //Ronin
new RankDefinition(1062962, 1, RankFlags.Member), //Member
@ -78,8 +78,8 @@ namespace Server.Guilds
public class AllianceInfo
{
private Guild m_Leader;
private List<Guild> m_Members;
private List<Guild> m_PendingMembers;
private readonly List<Guild> m_Members;
private readonly List<Guild> m_PendingMembers;
public AllianceInfo(Guild leader, string name, Guild partner)
{
@ -154,21 +154,9 @@ namespace Server.Guilds
}
}
public bool IsPendingMember(Guild g)
{
if (g.Alliance != this)
return false;
public bool IsPendingMember(Guild g) => g.Alliance == this && m_PendingMembers.Contains(g);
return m_PendingMembers.Contains(g);
}
public bool IsMember(Guild g)
{
if (g.Alliance != this)
return false;
return m_Members.Contains(g);
}
public bool IsMember(Guild g) => g.Alliance == this && m_Members.Contains(g);
public void Serialize(GenericWriter writer)
{
@ -332,29 +320,18 @@ namespace Server.Guilds
public void AllianceChat(Mobile from, int hue, string text)
{
Packet p = null;
for (int i = 0; i < m_Members.Count; i++)
{
Guild g = m_Members[i];
for (int j = 0; j < g.Members.Count; j++)
{
Mobile m = g.Members[j];
NetState ns = g.Members[j].NetState;
NetState state = m.NetState;
if (state != null)
{
if (p == null)
p = Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Alliance, hue, 3,
from.Language, from.Name, text));
state.Send(p);
}
if (ns != null)
Packets.SendUnicodeMessage(ns, from.Serial, from.Body, MessageType.Alliance, hue, 3, from.Language, from.Name, text);
}
}
Packet.Release(p);
}
public void AllianceChat(Mobile from, string text)
@ -683,9 +660,7 @@ namespace Server.Guilds
Mobile from = e.Mobile;
if (arg.Length == 0)
{
e.Mobile.Target = new GuildPropsTarget();
}
else
{
Guild g = uint.TryParse(arg, out uint id)
@ -720,7 +695,7 @@ namespace Server.Guilds
if (o is Guildstone stone)
{
if (stone?.Guild.Disbanded != false)
if (stone.Guild.Disbanded)
{
from.SendMessage("The guild associated with that Guildstone no longer exists");
return;
@ -729,9 +704,7 @@ namespace Server.Guilds
g = stone.Guild;
}
else if (o is Mobile mobile)
{
g = mobile.Guild as Guild;
}
if (g == null)
{
@ -773,13 +746,7 @@ namespace Server.Guilds
public AllianceInfo Alliance
{
get
{
if (m_AllianceInfo != null)
return m_AllianceInfo;
return m_AllianceLeader?.m_AllianceInfo;
}
get => m_AllianceInfo ?? m_AllianceLeader?.m_AllianceInfo;
set
{
AllianceInfo current = Alliance;
@ -822,10 +789,7 @@ namespace Server.Guilds
{
AllianceInfo alliance = g.Alliance;
if (alliance?.Leader != null && alliance.IsMember(g))
return alliance.Leader;
return g;
return alliance?.Leader != null && alliance.IsMember(g) ? alliance.Leader : g;
}
#endregion
@ -837,31 +801,9 @@ namespace Server.Guilds
public List<WarDeclaration> AcceptedWars{ get; private set; }
public WarDeclaration FindPendingWar(Guild g)
{
for (int i = 0; i < PendingWars.Count; i++)
{
WarDeclaration w = PendingWars[i];
public WarDeclaration FindPendingWar(Guild g) => PendingWars.FirstOrDefault(w => w.Opponent == g);
if (w.Opponent == g)
return w;
}
return null;
}
public WarDeclaration FindActiveWar(Guild g)
{
for (int i = 0; i < AcceptedWars.Count; i++)
{
WarDeclaration w = AcceptedWars[i];
if (w.Opponent == g)
return w;
}
return null;
}
public WarDeclaration FindActiveWar(Guild g) => AcceptedWars.FirstOrDefault(w => w.Opponent == g);
public void CheckExpiredWars()
{
@ -936,8 +878,7 @@ namespace Server.Guilds
if (!NewGuildSystem)
return;
if (killer == null)
killer = victim.FindMostRecentDamager(false);
killer ??= victim.FindMostRecentDamager(false);
if (killer == null || victim.Guild == null || killer.Guild == null)
return;
@ -1148,24 +1089,10 @@ namespace Server.Guilds
}
}
if (AllyDeclarations == null)
AllyDeclarations = new List<Guild>();
if (AllyInvitations == null)
AllyInvitations = new List<Guild>();
if (AcceptedWars == null)
AcceptedWars = new List<WarDeclaration>();
if (PendingWars == null)
PendingWars = new List<WarDeclaration>();
/*
if ( ( !NewGuildSystem && m_Guildstone == null )|| m_Members.Count == 0 )
Disband();
*/
AllyDeclarations ??= new List<Guild>();
AllyInvitations ??= new List<Guild>();
AcceptedWars ??= new List<WarDeclaration>();
PendingWars ??= new List<WarDeclaration>();
Timer.DelayCall(TimeSpan.Zero, VerifyGuild_Callback);
}
@ -1334,24 +1261,14 @@ namespace Server.Guilds
public void GuildChat(Mobile from, int hue, string text)
{
Packet p = null;
for (int i = 0; i < Members.Count; i++)
{
Mobile m = Members[i];
NetState ns = Members[i].NetState;
NetState state = m.NetState;
if (state != null)
{
if (p == null)
p = Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Guild, hue, 3,
from.Language, from.Name, text));
state.Send(p);
}
if (ns != null)
Packets.SendUnicodeMessage(ns, from.Serial, from.Body, MessageType.Guild, hue, 3,
from.Language, from.Name, text);
}
Packet.Release(p);
}
public void GuildChat(Mobile from, string text)
@ -1402,17 +1319,12 @@ namespace Server.Guilds
Mobile winner = null;
int highVotes = 0;
foreach (KeyValuePair<Mobile, int> kvp in votes)
{
Mobile m = kvp.Key;
int val = kvp.Value;
foreach ((Mobile m, int val) in votes)
if (winner == null || val > highVotes)
{
winner = m;
highVotes = val;
}
}
if (NewGuildSystem && highVotes * 100 / Math.Max(votingMembers, 1) < MajorityPercentage && !Disbanded &&
winner != m_Leader && m_Leader.Guild == this)

View file

@ -4,7 +4,7 @@ using Server.Mobiles;
namespace Server.Misc
{
public class Keywords
public static class Keywords
{
public static void Initialize()
{
@ -51,4 +51,4 @@ namespace Server.Misc
}
}
}
}
}

View file

@ -20,7 +20,7 @@ namespace Server.Misc
* enable showing of unicode control chars
**/
public class LanguageStatistics
public static class LanguageStatistics
{
private static InternationalCode[] InternationalCodes =
{
@ -317,13 +317,10 @@ namespace Server.Misc
public int Compare(InternationalCodeCounter x, InternationalCodeCounter y)
{
string a = null, b = null;
int ca = 0, cb = 0;
a = x.Code;
ca = x.Count;
b = y.Code;
cb = y.Count;
string a = x?.Code;
int ca = x?.Count ?? 0;
string b = y?.Code;
int cb = y?.Count ?? 0;
if (ca > cb)

View file

@ -4,7 +4,7 @@ using Server.Network;
namespace Server
{
public class LightCycle
public static class LightCycle
{
public const int DayLevel = 0;
public const int NightLevel = 12;
@ -69,12 +69,12 @@ namespace Server
Clock.GetTime(from.Map, from.X, from.Y, out int hours, out int minutes);
/* OSI times:
*
*
* Midnight -> 3:59 AM : Night
* 4:00 AM -> 11:59 PM : Day
*
*
* RunUO times:
*
*
* 10:00 PM -> 11:59 PM : Scale to night
* Midnight -> 3:59 AM : Night
* 4:00 AM -> 5:59 AM : Scale to day
@ -124,10 +124,10 @@ namespace Server
protected override void OnTick()
{
m_Owner.EndAction<LightCycle>();
m_Owner.EndAction<NightSightTimer>();
m_Owner.LightLevel = 0;
BuffInfo.RemoveBuff(m_Owner, BuffIcon.NightSight);
}
}
}
}
}

View file

@ -2,7 +2,7 @@ using Server.Network;
namespace Server.Misc
{
public class LoginStats
public static class LoginStats
{
public static void Initialize()
{
@ -27,4 +27,4 @@ namespace Server.Misc
mobileCount, mobileCount == 1 ? "" : "s");
}
}
}
}

View file

@ -1,17 +1,16 @@
namespace Server.Misc
{
public class MapDefinitions
public static class MapDefinitions
{
public static void Configure()
{
/* Here we configure all maps. Some notes:
*
*
* 1) The first 32 maps are reserved for core use.
* 2) Map 0x7F is reserved for core use.
* 3) Map 0xFF is reserved for core use.
* 4) Changing or removing any predefined maps may cause server instability.
*/
RegisterMap(0, 0, 0, 7168, 4096, 4, "Felucca", MapRules.FeluccaRules);
RegisterMap(1, 1, 1, 7168, 4096, 0, "Trammel", MapRules.TrammelRules);
RegisterMap(2, 2, 2, 2304, 1600, 1, "Ilshenar", MapRules.TrammelRules);
@ -23,7 +22,7 @@ namespace Server.Misc
/* Example of registering a custom map:
* RegisterMap( 32, 0, 0, 6144, 4096, 3, "Iceland", MapRules.FeluccaRules );
*
*
* Defined:
* RegisterMap( <index>, <mapID>, <fileIndex>, <width>, <height>, <season>, <name>, <rules> );
* - <index> : An unreserved unique index for this map
@ -40,7 +39,7 @@ namespace Server.Misc
MultiComponentList.PostHSFormat = true; // OSI Client Patch 7.0.9.0
}
public static void RegisterMap(int mapIndex, int mapID, int fileIndex, int width, int height, int season,
public static void RegisterMap(int mapIndex, int mapID, int fileIndex, int width, int height, byte season,
string name, MapRules rules)
{
Map newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules);
@ -49,4 +48,4 @@ namespace Server.Misc
Map.AllMaps.Add(newMap);
}
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using Server.Buffers;
using Server.Engines.PartySystem;
using Server.Guilds;
using Server.Network;
@ -18,35 +19,12 @@ namespace Server.Misc
private static void OnPartyTrack(NetState state, PacketReader pvSrc)
{
Mobile from = state.Mobile;
Party party = Party.Get(from);
if (party != null)
{
Packets.PartyTrack packet = new Packets.PartyTrack(from, party);
if (packet.UnderlyingStream.Length > 8)
state.Send(packet);
}
MapUOPackets.SendPartyTrack(state, Party.Get(state.Mobile));
}
private static void OnGuildTrack(NetState state, PacketReader pvSrc)
{
Mobile from = state.Mobile;
if (from.Guild is Guild guild)
{
bool locations = pvSrc.ReadByte() != 0;
Packets.GuildTrack packet = new Packets.GuildTrack(from, guild, locations);
if (packet.UnderlyingStream.Length > (locations ? 9 : 5))
state.Send(packet);
}
else
{
state.Send(new Packets.GuildTrack());
}
MapUOPackets.SendGuildTrack(state, state.Mobile.Guild as Guild, pvSrc.ReadBoolean());
}
private static class Settings
@ -56,75 +34,97 @@ namespace Server.Misc
public const bool GuildHitsPercent = true;
}
private static class Packets
private static class MapUOPackets
{
public sealed class PartyTrack : ProtocolExtension
public static void SendPartyTrack(NetState ns, Party party)
{
public PartyTrack(Mobile from, Party party) : base(0x01, (party.Members.Count - 1) * 9 + 4)
Mobile from = ns.Mobile;
int count = party?.Members.Count ?? 0;
if (count < 2)
return;
SpanWriter writer = new SpanWriter(stackalloc byte[Math.Max(count - 1, 0) * 9 + 8]);
writer.Write((byte)0xF0); // Packet ID
writer.Position += 2; // Dynamic Length
writer.Write((byte)0x01); // Command
count = 0;
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < party.Members.Count; ++i)
{
PartyMemberInfo pmi = party.Members[i];
Mobile mob = party.Members[i]?.Mobile; // if count is greater than 0, then party is not null
if (pmi == null || pmi.Mobile == from)
continue;
if (mob == from || mob?.NetState == null || Utility.InUpdateRange(from, mob) && from.CanSee(mob))
continue;
Mobile mob = pmi.Mobile;
if (Utility.InUpdateRange(from, mob) && from.CanSee(mob))
continue;
m_Stream.Write(mob.Serial);
m_Stream.Write((short)mob.X);
m_Stream.Write((short)mob.Y);
m_Stream.Write((byte)(mob.Map?.MapID ?? 0));
}
m_Stream.Write(0);
count++;
writer.Write(mob.Serial);
writer.Write((short)mob.X);
writer.Write((short)mob.Y);
writer.Write((byte)(mob.Map?.MapID ?? 0));
}
if (count == 0)
return;
writer.Position += 4; // Empty Serial
writer.Position = 1;
writer.Write((ushort)writer.WrittenCount);
ns.Send(writer.Span);
}
public sealed class GuildTrack : ProtocolExtension
public static void SendGuildTrack(NetState ns, Guild guild = null, bool locations = false)
{
public GuildTrack() : base(0x02, 5)
{
m_Stream.Write((byte)0);
m_Stream.Write(0);
}
Mobile from = ns.Mobile;
public GuildTrack(Mobile from, Guild guild, bool locations) : base(0x02,
(guild.Members.Count - 1) * (locations ? 10 : 4) + 5)
{
m_Stream.Write((byte)(locations ? 1 : 0));
int count = guild?.Members.Count ?? 0;
for (int i = 0; i < guild.Members.Count; ++i)
if (count < 2)
return;
SpanWriter writer = new SpanWriter(stackalloc byte[Math.Max(count - 1, 0) * (locations ? 10 : 4) + 9]);
writer.Write((byte)0xF0); // Packet ID
writer.Position += 2; // Dynamic Length
writer.Write((byte)0x02); // Command
writer.Write(locations);
count = 0;
for (int i = 0; i < count; ++i)
{
Mobile mob = guild.Members[i]; // If guild count is above 0, then guild is not null.
if (mob == from || mob?.NetState == null || locations && Utility.InUpdateRange(from, mob) && from.CanSee(mob))
continue;
count++;
writer.Write(mob.Serial);
if (locations)
{
Mobile mob = guild.Members[i];
writer.Write((short)mob.X);
writer.Write((short)mob.Y);
writer.Write((byte)(mob.Map?.MapID ?? 0));
if (mob == null || mob == from || mob.NetState == null)
continue;
if (locations && Utility.InUpdateRange(from, mob) && from.CanSee(mob))
continue;
m_Stream.Write(mob.Serial);
if (locations)
{
m_Stream.Write((short)mob.X);
m_Stream.Write((short)mob.Y);
m_Stream.Write((byte)(mob.Map?.MapID ?? 0));
if (Settings.GuildHitsPercent && mob.Alive)
m_Stream.Write((byte)(mob.Hits / Math.Max(mob.HitsMax, 1.0) * 100));
else
m_Stream.Write((byte)0);
}
if (Settings.GuildHitsPercent && mob.Alive)
writer.Write((byte)(mob.Hits / Math.Max(mob.HitsMax, 1.0) * 100));
else
writer.Position++; // writer.Write((byte)0);
}
m_Stream.Write(0);
}
if (count == 0)
return;
writer.Position += 4; // Empty Serial
writer.Position = 1;
writer.Write((ushort)writer.WrittenCount);
ns.Send(writer.Span);
}
}
}
}
}

View file

@ -0,0 +1,22 @@
using Server.Network;
namespace Server
{
public static class MessageHelper
{
public static void SendLocalizedMessageTo(Item from, Mobile to, int number, int hue)
{
SendLocalizedMessageTo(from, to, number, "", hue);
}
public static void SendLocalizedMessageTo(Item from, Mobile to, int number, string args, int hue)
{
Packets.SendMessageLocalized(to.NetState, from.Serial, from.ItemID, MessageType.Regular, hue, 3, number, "", args);
}
public static void SendMessageTo(Item from, Mobile to, string text, int hue)
{
Packets.SendUnicodeMessage(to.NetState, from.Serial, from.ItemID, MessageType.Regular, hue, 3, "ENU", "", text);
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
namespace Server

View file

@ -1,6 +1,6 @@
namespace Server.Misc
{
public class NameVerification
public static class NameVerification
{
public static readonly char[] SpaceDashPeriodQuote =
{
@ -148,20 +148,9 @@ namespace Server.Misc
exceptCount = 0;
}
else
{
bool except = false;
for (int j = 0; !except && j < exceptions.Length; ++j)
if (c == exceptions[j])
except = true;
if (!except || i == 0 && noExceptionsAtStart)
return false;
if (exceptCount++ == maxExceptions)
return false;
}
else if (exceptCount++ == maxExceptions || exceptions.All(exception => exception != c) ||
i == 0 && noExceptionsAtStart)
return false;
}
for (int i = 0; i < disallowed.Length; ++i)
@ -188,11 +177,7 @@ namespace Server.Misc
return false;
}
for (int i = 0; i < startDisallowed.Length; ++i)
if (name.StartsWith(startDisallowed[i]))
return false;
return true;
return startDisallowed.All(t => !name.StartsWith(t));
}
}
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Engines.ConPVP;
using Server.Engines.PartySystem;
using Server.Factions;
@ -12,7 +13,7 @@ using Server.Spells.Seventh;
namespace Server.Misc
{
public class NotorietyHandlers
public static class NotorietyHandlers
{
public static void Initialize()
{
@ -306,7 +307,7 @@ namespace Server.Misc
}
/* Must be thread-safe */
public static int MobileNotoriety(Mobile source, Mobile target)
public static byte MobileNotoriety(Mobile source, Mobile target)
{
BaseCreature bcTarg = target as BaseCreature;
@ -429,27 +430,12 @@ namespace Server.Misc
public static bool IsSummoned(BaseCreature c) => c?.Summoned == true;
public static bool CheckAggressor(List<AggressorInfo> list, Mobile target)
{
for (int i = 0; i < list.Count; ++i)
if (list[i].Attacker == target)
return true;
public static bool IsSummoned(BaseCreature c) => c?.Summoned == true;
return false;
}
public static bool CheckAggressor(IEnumerable<AggressorInfo> list, Mobile target) => list.Any(t => t.Attacker == target);
public static bool CheckAggressed(List<AggressorInfo> list, Mobile target)
{
for (int i = 0; i < list.Count; ++i)
{
AggressorInfo info = list[i];
if (!info.CriminalAggression && info.Defender == target)
return true;
}
return false;
}
public static bool CheckAggressed(IEnumerable<AggressorInfo> list, Mobile target) =>
list.Any(info => !info.CriminalAggression && info.Defender == target);
private enum GuildStatus
{

View file

@ -3,7 +3,7 @@ using Server.Network;
namespace Server.Misc
{
public class Paperdoll
public static class Paperdoll
{
public static void Initialize()
{
@ -13,21 +13,22 @@ namespace Server.Misc
public static void EventSink_PaperdollRequest(PaperdollRequestEventArgs e)
{
Mobile beholder = e.Beholder;
NetState ns = beholder.NetState;
Mobile beheld = e.Beheld;
beholder.Send(new DisplayPaperdoll(beheld, Titles.ComputeTitle(beholder, beheld),
beheld.AllowEquipFrom(beholder)));
Packets.SendDisplayPaperdoll(ns, beholder, Titles.ComputeTitle(beholder, beheld),
beheld.AllowEquipFrom(beholder));
if (ObjectPropertyList.Enabled)
{
List<Item> items = beheld.Items;
for (int i = 0; i < items.Count; ++i)
beholder.Send(items[i].OPLPacket);
items[i].PropertyList.SendOPLInfo(ns);
// NOTE: OSI sends MobileUpdate when opening your own paperdoll.
// It has a very bad rubber-banding affect. What positive affects does it have?
}
}
}
}
}

View file

@ -99,10 +99,7 @@ namespace Server.Misc
return false;
}
default:
case ProfanityAction.Other: // TODO: Provide custom implementation if this is chosen
{
return true;
}
}
}
@ -118,4 +115,4 @@ namespace Server.Misc
e.Blocked = !OnProfanityDetected(from, e.Speech);
}
}
}
}

View file

@ -4,7 +4,7 @@ using Server.Network;
namespace Server.Misc
{
public class Profile
public static class Profile
{
public static void Initialize()
{
@ -48,12 +48,9 @@ namespace Server.Misc
if (footer.Length == 0 && beholder == beheld)
footer = GetAccountDuration(beheld);
string body = beheld.Profile;
string body = beheld.Profile ?? "";
if (body == null || body.Length <= 0)
body = "";
beholder.Send(new DisplayProfile(beholder != beheld || !beheld.ProfileLocked, beheld, header, body, footer));
Packets.SendDisplayProfile(beholder.NetState, beholder != beheld || !beheld.ProfileLocked ? beheld.Serial : Serial.Zero, header, body, footer);
}
private static string GetAccountDuration(Mobile m)
@ -72,10 +69,7 @@ namespace Server.Misc
if (Format(ts.TotalMinutes, "This account is {0} minute{1} old.", out v))
return v;
if (Format(ts.TotalSeconds, "This account is {0} second{1} old.", out v))
return v;
return "";
return Format(ts.TotalSeconds, "This account is {0} second{1} old.", out v) ? v : "";
}
public static bool Format(double value, string format, out string op)
@ -90,4 +84,4 @@ namespace Server.Misc
return false;
}
}
}
}

View file

@ -3,9 +3,9 @@ using Server.Network;
namespace Server.Misc
{
public class ProtocolExtensions
public static class ProtocolExtensions
{
private static PacketHandler[] m_Handlers = new PacketHandler[0x100];
private static readonly PacketHandler[] m_Handlers = new PacketHandler[0x100];
public static void Initialize()
{
@ -17,48 +17,34 @@ namespace Server.Misc
m_Handlers[packetID] = new PacketHandler(packetID, 0, ingame, onReceive);
}
public static PacketHandler GetHandler(int packetID)
{
if (packetID >= 0 && packetID < m_Handlers.Length)
return m_Handlers[packetID];
return null;
}
public static PacketHandler GetHandler(int packetID) => packetID >= 0 && packetID < m_Handlers.Length ? m_Handlers[packetID] : null;
public static void DecodeBundledPacket(NetState state, PacketReader pvSrc)
{
int packetID = pvSrc.ReadByte();
PacketHandler ph = GetHandler(packetID);
if (ph == null)
return;
if (ph != null)
if (ph.Ingame)
{
if (ph.Ingame && state.Mobile == null)
if (state.Mobile == null)
{
Console.WriteLine(
"Client: {0}: Sent ingame packet (0xF0x{1:X2}) before having been attached to a mobile", state,
packetID);
"Client: {0}: Sent ingame packet (0xF0x{1:X2}) before having been attached to a mobile", state, packetID);
state.Dispose();
return;
}
else if (ph.Ingame && state.Mobile.Deleted)
if (state.Mobile.Deleted)
{
state.Dispose();
}
else
{
ph.OnReceive(state, pvSrc);
return;
}
}
ph.OnReceive(state, pvSrc);
}
}
public abstract class ProtocolExtension : Packet
{
public ProtocolExtension(int packetID, int capacity) : base(0xF0)
{
EnsureCapacity(4 + capacity);
m_Stream.Write((byte)packetID);
}
}
}
}

View file

@ -1,3 +1,5 @@
using System.Linq;
namespace Server.Misc
{
public class RaceDefinitions
@ -30,22 +32,9 @@ namespace Server.Misc
{
}
public override bool ValidateHair(bool female, int itemID)
{
if (itemID == 0)
return true;
if (female && itemID == 0x2048 || !female && itemID == 0x2046)
return false; //Buns & Receding Hair
if (itemID >= 0x203B && itemID <= 0x203D)
return true;
if (itemID >= 0x2044 && itemID <= 0x204A)
return true;
return false;
}
public override bool ValidateHair(bool female, int itemID) =>
itemID == 0 || (!female || itemID != 0x2048) && (female || itemID != 0x2046) &&
(itemID >= 0x203B && itemID <= 0x203D || itemID >= 0x2044 && itemID <= 0x204A);
public override int RandomHair(bool female) //Random hair doesn't include baldness
{
@ -90,32 +79,18 @@ namespace Server.Misc
return (rand < 4 ? 0x203E : 0x2047) + rand;
}
public override int ClipSkinHue(int hue)
{
if (hue < 1002)
return 1002;
if (hue > 1058)
return 1058;
return hue;
}
public override int ClipSkinHue(int hue) => hue < 1002 ? 1002 : hue > 1058 ? 1058 : hue;
public override int RandomSkinHue() => Utility.Random(1002, 57) | 0x8000;
public override int ClipHairHue(int hue)
{
if (hue < 1102)
return 1102;
if (hue > 1149)
return 1149;
return hue;
}
public override int ClipHairHue(int hue) => hue < 1102 ? 1102 : hue > 1149 ? 1149 : hue;
public override int RandomHairHue() => Utility.Random(1102, 48);
}
private class Elf : Race
{
private static int[] m_SkinHues =
private static readonly int[] m_SkinHues =
{
0x0BF, 0x24D, 0x24E, 0x24F, 0x353, 0x361, 0x367, 0x374,
0x375, 0x376, 0x381, 0x382, 0x383, 0x384, 0x385, 0x389,
@ -123,7 +98,7 @@ namespace Server.Misc
0x51D, 0x53F, 0x579, 0x76B, 0x76C, 0x76D, 0x835, 0x903
};
private static int[] m_HairHues =
private static readonly int[] m_HairHues =
{
0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x058, 0x08E,
0x08F, 0x090, 0x091, 0x092, 0x101, 0x159, 0x15A, 0x15B,
@ -139,10 +114,10 @@ namespace Server.Misc
{
}
public override bool ValidateHair(bool female, int itemID)
{
if (itemID == 0)
return true;
public override bool ValidateHair(bool female, int itemID) =>
itemID == 0 || (!female || itemID != 0x2FCD && itemID != 0x2FBF) &&
(female || itemID != 0x2FCC && itemID != 0x2FD0) &&
(itemID >= 0x2FBF && itemID <= 0x2FC2 || itemID >= 0x2FCC && itemID <= 0x2FD1);
if (female && (itemID == 0x2FCD || itemID == 0x2FBF) || !female && (itemID == 0x2FCC || itemID == 0x2FD0))
return false;
@ -186,14 +161,9 @@ namespace Server.Misc
public override int RandomSkinHue() => m_SkinHues[Utility.Random(m_SkinHues.Length)] | 0x8000;
public override int ClipHairHue(int hue)
{
for (int i = 0; i < m_HairHues.Length; i++)
if (m_HairHues[i] == hue)
return hue;
public override int RandomSkinHue() => m_SkinHues[Utility.Random(m_SkinHues.Length)] | 0x8000;
return m_HairHues[0];
}
public override int ClipHairHue(int hue) => m_HairHues.Any(t => t == hue) ? hue : m_HairHues[0];
public override int RandomHairHue() => m_HairHues[Utility.Random(m_HairHues.Length)];
}
@ -225,13 +195,11 @@ namespace Server.Misc
{
}
public override bool ValidateHair(bool female, int itemID)
{
if (female == false) return itemID >= 0x4258 && itemID <= 0x425F;
return itemID == 0x4261 || itemID == 0x4262 || itemID >= 0x4273 && itemID <= 0x4275 || itemID == 0x42B0 ||
itemID == 0x42B1 || itemID == 0x42AA || itemID == 0x42AB;
}
public override bool ValidateHair(bool female, int itemID) =>
female == false
? itemID >= 0x4258 && itemID <= 0x425F
: itemID == 0x4261 || itemID == 0x4262 || itemID >= 0x4273 && itemID <= 0x4275 || itemID == 0x42B0 ||
itemID == 0x42B1 || itemID == 0x42AA || itemID == 0x42AB;
public override int RandomHair(bool female)
{
@ -262,14 +230,9 @@ namespace Server.Misc
public override int RandomSkinHue() => m_BodyHues[Utility.Random(m_BodyHues.Length)] | 0x8000;
public override int ClipHairHue(int hue)
{
for (int i = 0; i < m_HornHues.Length; i++)
if (m_HornHues[i] == hue)
return hue;
public override int RandomSkinHue() => m_BodyHues[Utility.Random(m_BodyHues.Length)] | 0x8000;
return m_HornHues[0];
}
public override int ClipHairHue(int hue) => m_HornHues.Any(t => t == hue) ? hue : m_HornHues[0];
public override int RandomHairHue() => m_HornHues[Utility.Random(m_HornHues.Length)];
}

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@ -9,18 +10,18 @@ namespace Server.Misc
{
public class ServerList
{
/*
/*
* The default setting for Address, a value of 'null', will use your local IP address. If all of your local IP addresses
* are private network addresses and AutoDetect is 'true' then RunUO will attempt to discover your public IP address
* for you automatically.
*
* If you do not plan on allowing clients outside of your LAN to connect, you can set AutoDetect to 'false' and leave
* Address set to 'null'.
*
*
* If your public IP address cannot be determined, you must change the value of Address to your public IP address
* manually to allow clients outside of your LAN to connect to your server. Address can be either an IP address or
* a hostname that will be resolved when RunUO starts.
*
*
* If you want players outside your LAN to be able to connect to your server and you are behind a router, you must also
* forward TCP port 2593 to your private IP address. The procedure for doing this varies by manufacturer but generally
* involves configuration of the router through your web browser.
@ -32,7 +33,7 @@ namespace Server.Misc
* properly and fully supports listening on multiple ports. If a client with a public IP address is connecting to a
* locally private address, the server will direct the client to either the AutoDetected IP address or the manually entered
* IP address or hostname, whichever is applicable. Loopback clients will be directed to loopback.
*
*
* If you would like to listen on additional ports (i.e. 22, 23, 80, for clients behind highly restrictive egress
* firewalls) or specific IP adddresses you can do so by modifying the file SocketOptions.cs found in this directory.
*/
@ -111,7 +112,7 @@ namespace Server.Misc
IPHostEntry iphe = Dns.GetHostEntry(addr);
if (iphe.AddressList.Length > 0)
outValue = iphe.AddressList[iphe.AddressList.Length - 1];
outValue = iphe.AddressList[^1];
}
catch
{
@ -119,65 +120,23 @@ namespace Server.Misc
}
}
private static bool HasPublicIPAddress()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
private static bool HasPublicIPAddress() =>
NetworkInterface.GetAllNetworkInterfaces().Select(adapter => adapter.GetIPProperties())
.Any(properties => properties.UnicastAddresses.Select(unicast => unicast.Address)
.Any(ip => !IPAddress.IsLoopback(ip) && ip.AddressFamily != AddressFamily.InterNetworkV6 && !IsPrivateNetwork(ip)));
foreach (NetworkInterface adapter in adapters)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
foreach (IPAddressInformation unicast in properties.UnicastAddresses)
{
IPAddress ip = unicast.Address;
if (!IPAddress.IsLoopback(ip) && ip.AddressFamily != AddressFamily.InterNetworkV6 &&
!IsPrivateNetwork(ip))
return true;
}
}
return false;
/*
IPHostEntry iphe = Dns.GetHostEntry( Dns.GetHostName() );
IPAddress[] ips = iphe.AddressList;
for ( int i = 0; i < ips.Length; ++i )
{
if ( ips[i].AddressFamily != AddressFamily.InterNetworkV6 && !IsPrivateNetwork( ips[i] ) )
return true;
}
return false;
*/
}
private static bool IsPrivateNetwork(IPAddress ip)
{
// 10.0.0.0/8
// 172.16.0.0/12
// 192.168.0.0/16
// 169.254.0.0/16
// 100.64.0.0/10 RFC 6598
if (ip.AddressFamily == AddressFamily.InterNetworkV6)
return false;
if (Utility.IPMatch("192.168.*", ip))
return true;
if (Utility.IPMatch("10.*", ip))
return true;
if (Utility.IPMatch("172.16-31.*", ip))
return true;
if (Utility.IPMatch("169.254.*", ip))
return true;
if (Utility.IPMatch("100.64-127.*", ip))
return true;
return false;
}
// 10.0.0.0/8
// 172.16.0.0/12
// 192.168.0.0/16
// 169.254.0.0/16
// 100.64.0.0/10 RFC 6598
private static bool IsPrivateNetwork(IPAddress ip) =>
ip.AddressFamily != AddressFamily.InterNetworkV6 &&
(Utility.IPMatch("192.168.*", ip) ||
Utility.IPMatch("10.*", ip) ||
Utility.IPMatch("172.16-31.*", ip) ||
Utility.IPMatch("169.254.*", ip) ||
Utility.IPMatch("100.64-127.*", ip));
private static IPAddress FindPublicAddress()
{
@ -193,7 +152,7 @@ namespace Server.Misc
StreamReader sr = new StreamReader(s);
IPAddress ip = IPAddress.Parse(sr.ReadLine());
IPAddress ip = IPAddress.Parse(sr.ReadLine() ?? "");
sr.Close();
s.Close();

View file

@ -4,7 +4,6 @@ using System.Net;
using System.Text.RegularExpressions;
using Server.Gumps;
using Server.Network;
using Server.Prompts;
namespace Server.Misc
{
@ -465,9 +464,7 @@ namespace Server.Misc
public void QueuePoll(ShardPoller poller)
{
if (m_Polls == null)
m_Polls = new Queue<ShardPoller>(4);
m_Polls ??= new Queue<ShardPoller>(4);
m_Polls.Enqueue(poller);
}

View file

@ -224,7 +224,7 @@ namespace Server.Misc
Skills skills = from.Skills;
if (from.Player && skills.Total / skills.Cap >= Utility.RandomDouble()) //( skills.Total >= skills.Cap )
if (from.Player && skills.Total / (double)skills.Cap >= Utility.RandomDouble()) //( skills.Total >= skills.Cap )
for (int i = 0; i < skills.Length; ++i)
{
Skill toLower = skills[i];

View file

@ -373,8 +373,7 @@ namespace Server.Misc
{
int fp = Math.Min(skill.BaseFixedPoint, 1200);
return (fp - 300) / 100;
}
private static int GetTableIndex(Skill skill) => (Math.Min(skill.BaseFixedPoint, 1200) - 300) / 100;
}
public class FameEntry

View file

@ -19,7 +19,7 @@ namespace Server
public static void Initialize()
{
string filePath = Path.Combine(Core.BaseDirectory, "Data/treasure.cfg");
int i = 0, x = 0, y = 0;
int i = 0;
if (File.Exists(filePath))
{
@ -69,4 +69,4 @@ namespace Server
m.SendMessage("You have left a protected treasure map area.");
}
}
}
}

View file

@ -347,8 +347,6 @@ namespace Server
private static bool CanFit(Map map, int x, int y, int z)
{
bool hasSurface = false;
LandTile lt = map.Tiles.GetLandTile(x, y);
int lowZ = 0, avgZ = 0, topZ = 0;
@ -357,8 +355,8 @@ namespace Server
if ((landFlags & TileFlag.Impassable) != 0 && topZ > z && z + 16 > lowZ)
return false;
if ((landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored)
hasSurface = true;
bool hasSurface = (landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored;
StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y);
@ -376,8 +374,8 @@ namespace Server
if ((surface || impassable) && staticTiles[i].Z + id.CalcHeight > z && z + 16 > staticTiles[i].Z)
return false;
if (surface && !impassable && z == staticTiles[i].Z + id.CalcHeight)
hasSurface = true;
hasSurface |= surface && !impassable && z == staticTiles[i].Z + id.CalcHeight;
}
Sector sector = map.GetSector(x, y);
@ -395,8 +393,8 @@ namespace Server
if ((surface || impassable) && item.Z + id.CalcHeight > z && z + 16 > item.Z)
return false;
if (surface && !impassable && z == item.Z + id.CalcHeight)
hasSurface = true;
hasSurface |= surface && !impassable && z == item.Z + id.CalcHeight;
}
}
@ -413,9 +411,9 @@ namespace Server
floor.Add(p);
for (int xo = -1; xo <= 1; ++xo)
for (int yo = -1; yo <= 1; ++yo)
if ((xo != 0 || yo != 0) && IsFloor(map, x + xo, y + yo, false))
RecurseFindFloor(map, x + xo, y + yo, floor);
for (int yo = -1; yo <= 1; ++yo)
if ((xo != 0 || yo != 0) && IsFloor(map, x + xo, y + yo, false))
RecurseFindFloor(map, x + xo, y + yo, floor);
}
[Flags]

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Network;

View file

@ -23,21 +23,12 @@ namespace Server.Misc
public static void FatigueOnDamage(Mobile m, int damage)
{
double fatigue = 0.0;
switch (DFA)
double fatigue = DFA switch
{
case DFAlgorithm.Standard:
{
fatigue = damage * (100.0 / m.Hits) * ((double)m.Stam / 100) - 5.0;
break;
}
case DFAlgorithm.PainSpike:
{
fatigue = damage * (100.0 / m.Hits + (50.0 + m.Stam) / 100 - 1.0) - 5.0;
break;
}
}
DFAlgorithm.Standard => damage * (100.0 / m.Hits) * ((double)m.Stam / 100) - 5.0,
DFAlgorithm.PainSpike => damage * (100.0 / m.Hits + (50.0 + m.Stam) / 100 - 1.0) - 5.0,
_ => 0.0,
};
if (fatigue > 0)
m.Stam -= (int)fatigue;
@ -117,4 +108,4 @@ namespace Server.Misc
return Mobile.BodyWeight + m.TotalWeight > GetMaxWeight(m) + OverloadAllowance;
}
}
}
}