Revert "Updates Packets & Randomizer (#43)" (#61)

This reverts commit 179cb50557.
This commit is contained in:
Kamron Batman 2019-11-11 08:46:11 -08:00 • committed by GitHub
parent 179cb50557
commit c2ecc76457
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
588 changed files with 16260 additions and 10926 deletions

View file

@ -9,7 +9,7 @@ using Server.Spells.Seventh;
namespace Server
{
public static class AOS
public class AOS
{
public static void DisableStatInfluences()
{
@ -1019,7 +1019,8 @@ namespace Server
if (!GetValues(i, out SkillName skill, out double bonus))
continue;
m_Mods ??= new List<SkillMod>();
if (m_Mods == null)
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 static class AccountPrompt
public class AccountPrompt
{
public static void Initialize()
{
@ -22,7 +22,8 @@ namespace Server.Misc
Console.Write("Password: ");
string password = Console.ReadLine();
Account a = new Account(username, password) {AccessLevel = AccessLevel.Owner};
Account a = new Account(username, password);
a.AccessLevel = AccessLevel.Owner;
Console.WriteLine("Account created.");
}
@ -35,4 +36,4 @@ namespace Server.Misc
}
}
}
}
}

View file

@ -1,6 +1,6 @@
namespace Server.Misc
{
public static class Animations
public 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 static class AttackMessage
public 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[^1], GetTimeStamp()));
Directory.Move(saves, FormatDirectory(root, m_Backups[m_Backups.Length - 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 static class Broadcasts
public class Broadcasts
{
public static void Initialize()
{

View file

@ -1,5 +1,4 @@
using System;
using Server.Buffers;
using Server.Mobiles;
using Server.Network;
@ -19,11 +18,13 @@ namespace Server
};
}
#region Properties
public BuffIcon ID{ get; }
public int Title{ get; }
public int TitleCliloc{ get; }
public TextDefinition Description{ get; }
public int SecondaryCliloc{ get; }
public TimeSpan TimeLength{ get; }
@ -31,30 +32,50 @@ namespace Server
public Timer Timer{ get; }
public bool RetainThroughDeath { get; }
public bool RetainThroughDeath{ get; }
public BuffInfo(BuffIcon iconId, int title, TimeSpan time = default, Mobile m = null) :
this(iconId, title, title + 1, time, m)
public TextDefinition Args{ get; }
#endregion
#region Constructors
public BuffInfo(BuffIcon iconID, int titleCliloc)
: this(iconID, titleCliloc, titleCliloc + 1)
{
}
public BuffInfo(BuffIcon iconId, int title, string args, TimeSpan time = default, Mobile m = null) :
this(iconId, title, title + 1, args, 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, int desc, TimeSpan time = default, Mobile m = null) :
this(iconId, title, desc, null, 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)
{
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 title, int desc, string args, TimeSpan time, Mobile m = null) :
this(iconId, title, new TextDefinition(desc, args), DateTime.UtcNow, time, false, m)
public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args)
: this(iconID, titleCliloc, titleCliloc + 1, args)
{
}
@ -62,8 +83,8 @@ namespace Server
: this(iconID, titleCliloc, secondaryCliloc) =>
Args = args;
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)
public BuffInfo(BuffIcon iconID, int titleCliloc, bool retainThroughDeath)
: this(iconID, titleCliloc, titleCliloc + 1, retainThroughDeath)
{
}
@ -71,17 +92,9 @@ namespace Server
: this(iconID, titleCliloc, secondaryCliloc) =>
RetainThroughDeath = retainThroughDeath;
public BuffInfo(BuffIcon iconId, int title, TextDefinition desc, DateTime start = default, TimeSpan time = default, bool retain = false,
Mobile m = null)
public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args, bool retainThroughDeath)
: this(iconID, titleCliloc, titleCliloc + 1, args, retainThroughDeath)
{
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)
@ -118,17 +131,20 @@ namespace Server
public static void AddBuff(Mobile m, BuffInfo b)
{
(m as PlayerMobile)?.AddBuff(b);
if (m is PlayerMobile pm)
pm.AddBuff(b);
}
public static void RemoveBuff(Mobile m, BuffInfo b)
{
(m as PlayerMobile)?.RemoveBuff(b);
if (m is PlayerMobile pm)
pm.RemoveBuff(b);
}
public static void RemoveBuff(Mobile m, BuffIcon b)
{
(m as PlayerMobile)?.RemoveBuff(b);
if (m is PlayerMobile pm)
pm.RemoveBuff(b);
}
#endregion
@ -192,68 +208,80 @@ namespace Server
Fly
}
public static class BuffPackets
public sealed class AddBuffPacket : Packet
{
public static void SendAddBuff(Mobile m, BuffInfo info)
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)
{
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 static void SendRemoveBuffPacket(NetState ns, Serial m, int icon)
public AddBuffPacket(Mobile mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args,
TimeSpan length)
: base(0xDF)
{
SpanWriter writer = new SpanWriter(stackalloc byte[13]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)13); // Dynamic Length
bool hasArgs = args != null;
writer.Write(m);
EnsureCapacity(hasArgs ? 48 + args.ToString().Length * 2 : 44);
m_Stream.Write(mob.Serial);
writer.Write((short)icon); //ID
writer.Write((short)0x0); //Type 0 for removal. 1 for add 2 for Data
writer.Position += 4;
m_Stream.Write((short)iconID); //ID
m_Stream.Write((short)0x1); //Type 0 for removal. 1 for add 2 for Data
ns.Send(writer.Span);
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);
}
}
}
}
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 static class CharacterCreation
public class CharacterCreation
{
private static readonly CityInfo m_NewHavenInfo =
new CityInfo("New Haven", "The Bountiful Harvest Inn", 3503, 2574, 14, Map.Trammel);
@ -22,8 +22,15 @@ namespace Server.Misc
private static void AddBackpack(Mobile m)
{
if (m.Backpack == null)
m.AddItem(new Backpack {Movable = false});
Container pack = m.Backpack;
if (pack == null)
{
pack = new Backpack();
pack.Movable = false;
m.AddItem(pack);
}
PackItem(new RedBook("a book", m.Name, 20, true));
PackItem(new Gold(1000)); // Starting gold can be customized here
@ -45,8 +52,16 @@ namespace Server.Misc
item.Location = new Point3D(x, y, 0);
}
private static Item MakePotionKeg(PotionEffect type, int hue) =>
MakeNewbie(new PotionKeg {Held = 100, Type = type, Hue = hue});
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 void FillBankAOS(Mobile m)
{
@ -60,8 +75,11 @@ namespace Server.Misc
m.StatCap = 250;
Container cont;
// Begin box of money
Container cont = new WoodenBox();
cont = new WoodenBox();
cont.ItemID = 0xE7D;
cont.Hue = 0x489;
@ -79,7 +97,8 @@ namespace Server.Misc
// Begin bag of potion kegs
cont = new Backpack {Name = "Various Potion Kegs"};
cont = new Backpack();
cont.Name = "Various Potion Kegs";
PlaceItemIn(cont, 45, 149, MakePotionKeg(PotionEffect.CureGreater, 0x2D));
PlaceItemIn(cont, 69, 149, MakePotionKeg(PotionEffect.HealGreater, 0x499));
@ -94,7 +113,8 @@ namespace Server.Misc
// Begin bag of tools
cont = new Bag {Name = "Tool Bag"};
cont = new Bag();
cont.Name = "Tool Bag";
PlaceItemIn(cont, 30, 35, new TinkerTools(1000));
PlaceItemIn(cont, 60, 35, new HousePlacementTool());
@ -125,7 +145,8 @@ namespace Server.Misc
// Begin bag of archery ammo
cont = new Bag {Name = "Bag Of Archery Ammo"};
cont = new Bag();
cont.Name = "Bag Of Archery Ammo";
PlaceItemIn(cont, 48, 76, new Arrow(5000));
PlaceItemIn(cont, 72, 76, new Bolt(5000));
@ -135,7 +156,8 @@ namespace Server.Misc
// Begin bag of treasure maps
cont = new Bag {Name = "Bag Of Treasure Maps"};
cont = new Bag();
cont.Name = "Bag Of Treasure Maps";
PlaceItemIn(cont, 30, 35, new TreasureMap(1, Map.Trammel));
PlaceItemIn(cont, 45, 35, new TreasureMap(2, Map.Trammel));
@ -159,7 +181,9 @@ namespace Server.Misc
// Begin bag of raw materials
cont = new Bag {Hue = 0x835, Name = "Raw Materials Bag"};
cont = new Bag();
cont.Hue = 0x835;
cont.Name = "Raw Materials Bag";
PlaceItemIn(cont, 92, 60, new BarbedLeather(5000));
PlaceItemIn(cont, 92, 68, new HornedLeather(5000));
@ -192,7 +216,9 @@ namespace Server.Misc
// Begin bag of spell casting stuff
cont = new Backpack {Hue = 0x480, Name = "Spell Casting Stuff"};
cont = new Backpack();
cont.Hue = 0x480;
cont.Name = "Spell Casting Stuff";
PlaceItemIn(cont, 45, 105, new Spellbook(ulong.MaxValue));
PlaceItemIn(cont, 65, 105, new NecromancerSpellbook((ulong)0xFFFF));
@ -208,7 +234,8 @@ namespace Server.Misc
toHue.Hue = 0x2D;
PlaceItemIn(cont, 45, 150, toHue);
toHue = new BagOfNecroReagents(150) {Hue = 0x488};
toHue = new BagOfNecroReagents(150);
toHue.Hue = 0x488;
PlaceItemIn(cont, 65, 150, toHue);
PlaceItemIn(cont, 140, 150, new BagOfAllReagents(500));
@ -223,7 +250,9 @@ namespace Server.Misc
// Begin bag of ethereals
cont = new Backpack {Hue = 0x490, Name = "Bag Of Ethy's!"};
cont = new Backpack();
cont.Hue = 0x490;
cont.Name = "Bag Of Ethy's!";
PlaceItemIn(cont, 45, 66, new EtherealHorse());
PlaceItemIn(cont, 69, 82, new EtherealOstard());
@ -239,7 +268,9 @@ namespace Server.Misc
// Begin first bag of artifacts
cont = new Backpack {Hue = 0x48F, Name = "Bag of Artifacts"};
cont = new Backpack();
cont.Hue = 0x48F;
cont.Name = "Bag of Artifacts";
PlaceItemIn(cont, 45, 66, new TitansHammer());
PlaceItemIn(cont, 69, 82, new InquisitorsResolution());
@ -251,7 +282,9 @@ namespace Server.Misc
// Begin second bag of artifacts
cont = new Backpack {Hue = 0x48F, Name = "Bag of Artifacts"};
cont = new Backpack();
cont.Hue = 0x48F;
cont.Name = "Bag of Artifacts";
PlaceItemIn(cont, 45, 66, new GauntletsOfNobility());
PlaceItemIn(cont, 69, 82, new MidnightBracers());
@ -291,7 +324,10 @@ namespace Server.Misc
// End second bag of artifacts
// Begin bag of minor artifacts
cont = new Backpack {Hue = 0x48F, Name = "Bag of Minor Artifacts"};
cont = new Backpack();
cont.Hue = 0x48F;
cont.Name = "Bag of Minor Artifacts";
PlaceItemIn(cont, 45, 66, new LunaLance());
PlaceItemIn(cont, 69, 82, new VioletCourage());
@ -332,7 +368,9 @@ namespace Server.Misc
if (Core.SE)
{
cont = new Bag {Hue = 0x501, Name = "Tokuno Minor Artifacts"};
cont = new Bag();
cont.Hue = 0x501;
cont.Name = "Tokuno Minor Artifacts";
PlaceItemIn(cont, 42, 70, new Exiler());
PlaceItemIn(cont, 38, 53, new HanzosBow());
@ -360,7 +398,8 @@ namespace Server.Misc
if (Core.SE) //This bag came only after SE.
{
cont = new Bag {Name = "Bag of Bows"};
cont = new Bag();
cont.Name = "Bag of Bows";
PlaceItemIn(cont, 31, 84, new Bow());
PlaceItemIn(cont, 78, 74, new CompositeBow());
@ -393,7 +432,11 @@ namespace Server.Misc
bank.DropItem(new BankCheck(1000000));
// Full spellbook
bank.DropItem(new Spellbook {Content = ulong.MaxValue});
Spellbook book = new Spellbook();
book.Content = ulong.MaxValue;
bank.DropItem(book);
Bag bag = new Bag();
@ -598,7 +641,10 @@ namespace Server.Misc
newChar.Female = args.Female;
//newChar.Body = newChar.Female ? 0x191 : 0x190;
newChar.Race = Core.Expansion >= args.Race.RequiredExpansion ? args.Race : Race.DefaultRace;
if (Core.Expansion >= args.Race.RequiredExpansion)
newChar.Race = args.Race; //Sets body
else
newChar.Race = Race.DefaultRace;
//newChar.Hue = Utility.ClipSkinHue( args.Hue & 0x3FFF ) | 0x8000;
newChar.Hue = newChar.Race.ClipSkinHue(args.Hue & 0x3FFF) | 0x8000;
@ -646,7 +692,12 @@ namespace Server.Misc
if (TestCenter.Enabled)
FillBankbox(newChar);
if (young) newChar.BankBox.DropItem(new NewPlayerTicket {Owner = newChar});
if (young)
{
NewPlayerTicket ticket = new NewPlayerTicket();
ticket.Owner = newChar;
newChar.BankBox.DropItem(ticket);
}
CityInfo city = GetStartLocation(args, young);
@ -659,8 +710,19 @@ namespace Server.Misc
new WelcomeTimer(newChar).Start();
}
public static bool VerifyProfession(int profession) =>
profession >= 0 && (profession < 4 || Core.AOS && profession < 6 || Core.SE && profession < 8);
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;
}
private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool isYoung)
{
@ -692,7 +754,9 @@ namespace Server.Misc
break;
}
case 5: //Paladin
{
return m_NewHavenInfo;
}
case 6: //Samurai
{
if ((flags & ClientFlags.Tokuno) != 0)
@ -731,7 +795,10 @@ namespace Server.Misc
}
}
return useHaven ? m_NewHavenInfo : args.City;
if (useHaven)
return m_NewHavenInfo;
return args.City;
}
private static void FixStats(ref int str, ref int dex, ref int intel, int max)
@ -1097,7 +1164,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);
@ -1110,7 +1177,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);
@ -1666,18 +1733,18 @@ namespace Server.Misc
private class BadStartMessage : Timer
{
private int m_Message;
private Mobile m_From;
private Mobile m_Mobile;
public BadStartMessage(Mobile m, int message) : base(TimeSpan.FromSeconds(3.5))
{
m_From = m;
m_Mobile = m;
m_Message = message;
Start();
}
protected override void OnTick()
{
m_From.SendLocalizedMessage(m_Message);
m_Mobile.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,7 +43,9 @@ namespace Server.Misc
if (relEntity.Entity is Item item1)
validItems.Add(item1);
validItems.AddRange(house.VendorInventories.SelectMany(inventory => inventory.Items));
foreach (VendorInventory inventory in house.VendorInventories)
foreach (Item subItem in inventory.Items)
validItems.Add(subItem);
}
else if (item is BankBox box)
{

View file

@ -1,4 +1,4 @@
using Server.Items;
using Server.Accounting;
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[^1])
if (id > list[list.Length - 1])
return false;
for (int i = 0; i < list.Length; ++i)

View file

@ -6,17 +6,17 @@ using System.Threading;
namespace Server.Misc
{
public static class Email
public 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:yyyyMMdd}.{now:HHmmssff}@{EmailServer}>";
string messageID = $"<{now.ToString("yyyyMMdd")}.{now.ToString("HHmmssff")}@{EmailServer}>";
message.Headers.Add("Message-ID", messageID);
message.Headers.Add("X-Mailer", "RunUO");
@ -89,8 +89,10 @@ namespace Server.Misc
{
MailMessage message = (MailMessage)state;
Console.WriteLine(Send(message) ? "Sent e-mail '{0}' to '{1}'." : "Failure sending e-mail '{0}' to '{1}'.",
message.Subject, message.To);
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);
}
}
}
}

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 static class Fastwalk
public 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,19 +19,26 @@ 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;
int sideA = (int)Math.Round(radius * Math.Sin(DegreesToRadians(angle)));
int sideB = (int)Math.Round(radius * Math.Cos(DegreesToRadians(angle)));
sideA = (int)Math.Round(radius * Math.Sin(DegreesToRadians(angle)));
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, int angleStart = 0, int angleEnd = 360)
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)
{
if (angleStart < 0 || angleStart > 360)
angleStart = 0;
@ -140,9 +147,13 @@ 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;
}
@ -207,4 +218,4 @@ namespace Server.Misc
public int Quadrant{ get; }
}
}
}
}

View file

@ -129,7 +129,9 @@ 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
{
@ -138,9 +140,11 @@ 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 readonly RankDefinition[] Ranks =
public static 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 readonly List<Guild> m_Members;
private readonly List<Guild> m_PendingMembers;
private List<Guild> m_Members;
private List<Guild> m_PendingMembers;
public AllianceInfo(Guild leader, string name, Guild partner)
{
@ -154,9 +154,21 @@ namespace Server.Guilds
}
}
public bool IsPendingMember(Guild g) => g.Alliance == this && m_PendingMembers.Contains(g);
public bool IsPendingMember(Guild g)
{
if (g.Alliance != this)
return false;
public bool IsMember(Guild g) => g.Alliance == this && m_Members.Contains(g);
return m_PendingMembers.Contains(g);
}
public bool IsMember(Guild g)
{
if (g.Alliance != this)
return false;
return m_Members.Contains(g);
}
public void Serialize(GenericWriter writer)
{
@ -320,18 +332,29 @@ 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++)
{
NetState ns = g.Members[j].NetState;
Mobile m = g.Members[j];
if (ns != null)
Packets.SendUnicodeMessage(ns, from.Serial, from.Body, MessageType.Alliance, hue, 3, from.Language, from.Name, text);
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);
}
}
}
Packet.Release(p);
}
public void AllianceChat(Mobile from, string text)
@ -660,7 +683,9 @@ 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)
@ -695,7 +720,7 @@ namespace Server.Guilds
if (o is Guildstone stone)
{
if (stone.Guild.Disbanded)
if (stone?.Guild.Disbanded != false)
{
from.SendMessage("The guild associated with that Guildstone no longer exists");
return;
@ -704,7 +729,9 @@ namespace Server.Guilds
g = stone.Guild;
}
else if (o is Mobile mobile)
{
g = mobile.Guild as Guild;
}
if (g == null)
{
@ -746,7 +773,13 @@ namespace Server.Guilds
public AllianceInfo Alliance
{
get => m_AllianceInfo ?? m_AllianceLeader?.m_AllianceInfo;
get
{
if (m_AllianceInfo != null)
return m_AllianceInfo;
return m_AllianceLeader?.m_AllianceInfo;
}
set
{
AllianceInfo current = Alliance;
@ -789,7 +822,10 @@ namespace Server.Guilds
{
AllianceInfo alliance = g.Alliance;
return alliance?.Leader != null && alliance.IsMember(g) ? alliance.Leader : g;
if (alliance?.Leader != null && alliance.IsMember(g))
return alliance.Leader;
return g;
}
#endregion
@ -801,9 +837,31 @@ namespace Server.Guilds
public List<WarDeclaration> AcceptedWars{ get; private set; }
public WarDeclaration FindPendingWar(Guild g) => PendingWars.FirstOrDefault(w => w.Opponent == g);
public WarDeclaration FindPendingWar(Guild g)
{
for (int i = 0; i < PendingWars.Count; i++)
{
WarDeclaration w = PendingWars[i];
public WarDeclaration FindActiveWar(Guild g) => AcceptedWars.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 void CheckExpiredWars()
{
@ -878,7 +936,8 @@ namespace Server.Guilds
if (!NewGuildSystem)
return;
killer ??= victim.FindMostRecentDamager(false);
if (killer == null)
killer = victim.FindMostRecentDamager(false);
if (killer == null || victim.Guild == null || killer.Guild == null)
return;
@ -1089,10 +1148,24 @@ namespace Server.Guilds
}
}
AllyDeclarations ??= new List<Guild>();
AllyInvitations ??= new List<Guild>();
AcceptedWars ??= new List<WarDeclaration>();
PendingWars ??= new List<WarDeclaration>();
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();
*/
Timer.DelayCall(TimeSpan.Zero, VerifyGuild_Callback);
}
@ -1261,14 +1334,24 @@ namespace Server.Guilds
public void GuildChat(Mobile from, int hue, string text)
{
Packet p = null;
for (int i = 0; i < Members.Count; i++)
{
NetState ns = Members[i].NetState;
Mobile m = Members[i];
if (ns != null)
Packets.SendUnicodeMessage(ns, from.Serial, from.Body, MessageType.Guild, hue, 3,
from.Language, from.Name, text);
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);
}
}
Packet.Release(p);
}
public void GuildChat(Mobile from, string text)
@ -1319,12 +1402,17 @@ namespace Server.Guilds
Mobile winner = null;
int highVotes = 0;
foreach ((Mobile m, int val) in votes)
foreach (KeyValuePair<Mobile, int> kvp in votes)
{
Mobile m = kvp.Key;
int val = kvp.Value;
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 static class Keywords
public 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 static class LanguageStatistics
public class LanguageStatistics
{
private static InternationalCode[] InternationalCodes =
{
@ -317,10 +317,13 @@ namespace Server.Misc
public int Compare(InternationalCodeCounter x, InternationalCodeCounter y)
{
string a = x?.Code;
int ca = x?.Count ?? 0;
string b = y?.Code;
int cb = y?.Count ?? 0;
string a = null, b = null;
int ca = 0, cb = 0;
a = x.Code;
ca = x.Count;
b = y.Code;
cb = y.Count;
if (ca > cb)

View file

@ -4,7 +4,7 @@ using Server.Network;
namespace Server
{
public static class LightCycle
public 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<NightSightTimer>();
m_Owner.EndAction<LightCycle>();
m_Owner.LightLevel = 0;
BuffInfo.RemoveBuff(m_Owner, BuffIcon.NightSight);
}
}
}
}
}

View file

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

View file

@ -1,16 +1,17 @@
namespace Server.Misc
{
public static class MapDefinitions
public 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);
@ -22,7 +23,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
@ -39,7 +40,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, byte season,
public static void RegisterMap(int mapIndex, int mapID, int fileIndex, int width, int height, int season,
string name, MapRules rules)
{
Map newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules);
@ -48,4 +49,4 @@ namespace Server.Misc
Map.AllMaps.Add(newMap);
}
}
}
}

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@ using Server.Network;
namespace Server.Misc
{
public static class Paperdoll
public class Paperdoll
{
public static void Initialize()
{
@ -13,22 +13,21 @@ namespace Server.Misc
public static void EventSink_PaperdollRequest(PaperdollRequestEventArgs e)
{
Mobile beholder = e.Beholder;
NetState ns = beholder.NetState;
Mobile beheld = e.Beheld;
Packets.SendDisplayPaperdoll(ns, beholder, Titles.ComputeTitle(beholder, beheld),
beheld.AllowEquipFrom(beholder));
beholder.Send(new DisplayPaperdoll(beheld, Titles.ComputeTitle(beholder, beheld),
beheld.AllowEquipFrom(beholder)));
if (ObjectPropertyList.Enabled)
{
List<Item> items = beheld.Items;
for (int i = 0; i < items.Count; ++i)
items[i].PropertyList.SendOPLInfo(ns);
beholder.Send(items[i].OPLPacket);
// 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,7 +99,10 @@ namespace Server.Misc
return false;
}
default:
case ProfanityAction.Other: // TODO: Provide custom implementation if this is chosen
{
return true;
}
}
}
@ -115,4 +118,4 @@ namespace Server.Misc
e.Blocked = !OnProfanityDetected(from, e.Speech);
}
}
}
}

View file

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

View file

@ -3,9 +3,9 @@ using Server.Network;
namespace Server.Misc
{
public static class ProtocolExtensions
public class ProtocolExtensions
{
private static readonly PacketHandler[] m_Handlers = new PacketHandler[0x100];
private static PacketHandler[] m_Handlers = new PacketHandler[0x100];
public static void Initialize()
{
@ -17,34 +17,48 @@ namespace Server.Misc
m_Handlers[packetID] = new PacketHandler(packetID, 0, ingame, onReceive);
}
public static PacketHandler GetHandler(int packetID) => packetID >= 0 && packetID < m_Handlers.Length ? m_Handlers[packetID] : null;
public static PacketHandler GetHandler(int packetID)
{
if (packetID >= 0 && packetID < m_Handlers.Length)
return m_Handlers[packetID];
return null;
}
public static void DecodeBundledPacket(NetState state, PacketReader pvSrc)
{
int packetID = pvSrc.ReadByte();
PacketHandler ph = GetHandler(packetID);
if (ph == null)
return;
if (ph.Ingame)
if (ph != null)
{
if (state.Mobile == null)
if (ph.Ingame && 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;
}
if (state.Mobile.Deleted)
else if (ph.Ingame && state.Mobile.Deleted)
{
state.Dispose();
return;
}
else
{
ph.OnReceive(state, pvSrc);
}
}
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,5 +1,3 @@
using System.Linq;
namespace Server.Misc
{
public class RaceDefinitions
@ -32,9 +30,22 @@ namespace Server.Misc
{
}
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 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 int RandomHair(bool female) //Random hair doesn't include baldness
{
@ -79,18 +90,32 @@ namespace Server.Misc
return (rand < 4 ? 0x203E : 0x2047) + rand;
}
public override int ClipSkinHue(int hue) => hue < 1002 ? 1002 : hue > 1058 ? 1058 : hue;
public override int ClipSkinHue(int hue)
{
if (hue < 1002)
return 1002;
if (hue > 1058)
return 1058;
return hue;
}
public override int RandomSkinHue() => Utility.Random(1002, 57) | 0x8000;
public override int ClipHairHue(int hue) => hue < 1102 ? 1102 : hue > 1149 ? 1149 : hue;
public override int ClipHairHue(int hue)
{
if (hue < 1102)
return 1102;
if (hue > 1149)
return 1149;
return hue;
}
public override int RandomHairHue() => Utility.Random(1102, 48);
}
private class Elf : Race
{
private static readonly int[] m_SkinHues =
private static int[] m_SkinHues =
{
0x0BF, 0x24D, 0x24E, 0x24F, 0x353, 0x361, 0x367, 0x374,
0x375, 0x376, 0x381, 0x382, 0x383, 0x384, 0x385, 0x389,
@ -98,7 +123,7 @@ namespace Server.Misc
0x51D, 0x53F, 0x579, 0x76B, 0x76C, 0x76D, 0x835, 0x903
};
private static readonly int[] m_HairHues =
private static int[] m_HairHues =
{
0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x058, 0x08E,
0x08F, 0x090, 0x091, 0x092, 0x101, 0x159, 0x15A, 0x15B,
@ -114,10 +139,10 @@ namespace Server.Misc
{
}
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);
public override bool ValidateHair(bool female, int itemID)
{
if (itemID == 0)
return true;
if (female && (itemID == 0x2FCD || itemID == 0x2FBF) || !female && (itemID == 0x2FCC || itemID == 0x2FD0))
return false;
@ -161,9 +186,14 @@ namespace Server.Misc
public override int RandomSkinHue() => m_SkinHues[Utility.Random(m_SkinHues.Length)] | 0x8000;
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 ClipHairHue(int hue) => m_HairHues.Any(t => t == hue) ? hue : m_HairHues[0];
return m_HairHues[0];
}
public override int RandomHairHue() => m_HairHues[Utility.Random(m_HairHues.Length)];
}
@ -195,11 +225,13 @@ namespace Server.Misc
{
}
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 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 int RandomHair(bool female)
{
@ -230,9 +262,14 @@ namespace Server.Misc
public override int RandomSkinHue() => m_BodyHues[Utility.Random(m_BodyHues.Length)] | 0x8000;
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 ClipHairHue(int hue) => m_HornHues.Any(t => t == hue) ? hue : m_HornHues[0];
return m_HornHues[0];
}
public override int RandomHairHue() => m_HornHues[Utility.Random(m_HornHues.Length)];
}

View file

@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@ -10,18 +9,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.
@ -33,7 +32,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.
*/
@ -112,7 +111,7 @@ namespace Server.Misc
IPHostEntry iphe = Dns.GetHostEntry(addr);
if (iphe.AddressList.Length > 0)
outValue = iphe.AddressList[^1];
outValue = iphe.AddressList[iphe.AddressList.Length - 1];
}
catch
{
@ -120,23 +119,65 @@ namespace Server.Misc
}
}
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)));
private static bool HasPublicIPAddress()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
// 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));
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;
}
private static IPAddress FindPublicAddress()
{
@ -152,7 +193,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,6 +4,7 @@ using System.Net;
using System.Text.RegularExpressions;
using Server.Gumps;
using Server.Network;
using Server.Prompts;
namespace Server.Misc
{
@ -464,7 +465,9 @@ namespace Server.Misc
public void QueuePoll(ShardPoller poller)
{
m_Polls ??= new Queue<ShardPoller>(4);
if (m_Polls == null)
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 / (double)skills.Cap >= Utility.RandomDouble()) //( skills.Total >= skills.Cap )
if (from.Player && skills.Total / skills.Cap >= Utility.RandomDouble()) //( skills.Total >= skills.Cap )
for (int i = 0; i < skills.Length; ++i)
{
Skill toLower = skills[i];

View file

@ -373,7 +373,8 @@ namespace Server.Misc
{
int fp = Math.Min(skill.BaseFixedPoint, 1200);
private static int GetTableIndex(Skill skill) => (Math.Min(skill.BaseFixedPoint, 1200) - 300) / 100;
return (fp - 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;
int i = 0, x = 0, y = 0;
if (File.Exists(filePath))
{
@ -69,4 +69,4 @@ namespace Server
m.SendMessage("You have left a protected treasure map area.");
}
}
}
}

View file

@ -347,6 +347,8 @@ 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;
@ -355,8 +357,8 @@ namespace Server
if ((landFlags & TileFlag.Impassable) != 0 && topZ > z && z + 16 > lowZ)
return false;
bool hasSurface = (landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored;
if ((landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored)
hasSurface = true;
StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y);
@ -374,8 +376,8 @@ namespace Server
if ((surface || impassable) && staticTiles[i].Z + id.CalcHeight > z && z + 16 > staticTiles[i].Z)
return false;
hasSurface |= surface && !impassable && z == staticTiles[i].Z + id.CalcHeight;
if (surface && !impassable && z == staticTiles[i].Z + id.CalcHeight)
hasSurface = true;
}
Sector sector = map.GetSector(x, y);
@ -393,8 +395,8 @@ namespace Server
if ((surface || impassable) && item.Z + id.CalcHeight > z && z + 16 > item.Z)
return false;
hasSurface |= surface && !impassable && z == item.Z + id.CalcHeight;
if (surface && !impassable && z == item.Z + id.CalcHeight)
hasSurface = true;
}
}
@ -411,9 +413,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,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Network;

View file

@ -23,12 +23,21 @@ namespace Server.Misc
public static void FatigueOnDamage(Mobile m, int damage)
{
double fatigue = DFA switch
double fatigue = 0.0;
switch (DFA)
{
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,
};
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;
}
}
if (fatigue > 0)
m.Stam -= (int)fatigue;
@ -108,4 +117,4 @@ namespace Server.Misc
return Mobile.BodyWeight + m.TotalWeight > GetMaxWeight(m) + OverloadAllowance;
}
}
}
}