using System; using System.Reflection; using Server.Accounting; using Server.Items; using Server.Mobiles; namespace Server.Custom { /// /// Spawns a reachable, houseless player vendor next to the `tester` character (wttest) and /// gives tester gold, so the PlayerVendorSale core patch can be exercised by a real in-game /// purchase. The buyer must be a non-GM — IsOwner() treats any GameMaster+ as the owner of /// every player vendor, so an Owner-level character can never buy. /// /// Owner is a seed_000 character, so buyer (wttest) and owner (seed_000) are different /// accounts — a clean cheat-detection example. /// /// Test scaffolding. Never deployed. Spawns a mobile and hands out gold; run only on the /// throwaway seeded world. /// public static class BridgeVendorTestProbe { private static readonly MethodInfo SetVendorItem = typeof(PlayerVendor).GetMethod( "SetVendorItem", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Item), typeof(int), typeof(string) }, null); public static void Initialize() { if (Config.Get("Bridge.VendorTestOnStart", false)) EventSink.ServerStarted += () => Timer.DelayCall(TimeSpan.FromSeconds(3.0), Run); } private static void Run() { try { var ownerAcct = Accounting.Accounts.GetAccount("seed_000") as Account; var owner = ownerAcct == null ? null : ownerAcct[0]; var buyerAcct = Accounting.Accounts.GetAccount("wttest") as Account; var buyer = buyerAcct == null ? null : buyerAcct[0] as PlayerMobile; if (owner == null || buyer == null) { Console.WriteLine("[VendorTest] need seed_000 owner and wttest/tester; not found"); return; } // Remove any prior test vendor (e.g. one orphaned on the Internal map). if (PlayerVendor.PlayerVendors != null) { var doomed = new System.Collections.Generic.List(); foreach (var v in PlayerVendor.PlayerVendors) if (v != null && !v.Deleted && v.ShopName == "Bridge Test Shop") doomed.Add(v); foreach (var v in doomed) v.Delete(); } // A confirmed-walkable spot where tester was already standing this session, so the // vendor is on solid ground and reachable. Then force tester's logout location right // next to it, so tester logs in beside the vendor regardless of where it was. var map = Map.Trammel; var loc = new Point3D(3533, 2546, 20); // vendor buyer.LogoutMap = map; buyer.LogoutLocation = new Point3D(3532, 2546, 20); // tester appears here var vendor = new PlayerVendor(owner, null) { Name = "test vendor", ShopName = "Bridge Test Shop" }; vendor.MoveToWorld(loc, map); var blade = new Longsword(); vendor.Backpack.DropItem(blade); if (SetVendorItem != null) SetVendorItem.Invoke(vendor, new object[] { blade, 100, "a test blade" }); // Make sure tester can afford it. if (buyer.Backpack != null) buyer.Backpack.DropItem(new Gold(1000)); Console.WriteLine( "[VendorTest] spawned '{0}' (owner {1}/seed_000) next to {2}/wttest at {3} on {4}; test blade = 100 gold; gave tester 1000 gold", vendor.ShopName, owner.Name, buyer.Name, loc, map); } catch (Exception ex) { Console.WriteLine("[VendorTest] FAILED: " + ex); } } } }