public static int Run([NotNull, ItemNotNull] string[] args, GraphicsBackend graphicsBackend, [NotNull] string loggerName = "theater-days") { GraphicsBackend = graphicsBackend; GameLog.Initialize(loggerName); GameLog.Enabled = true; var exitCode = -1; var parser = new Parser(settings => { settings.IgnoreUnknownArguments = true; }); var optionsParsingResult = parser.ParseArguments <Options>(args); #if ENABLE_GUI_CONSOLE GuiConsole.Initialize(); GuiConsole.Error.WriteLine(); #endif #if SAFE_STARTUP try { #endif if (optionsParsingResult.Tag == ParserResultType.Parsed) { var options = ((Parsed <Options>)optionsParsingResult).Value; GameLog.Enabled = options.IsDebugEnabled; using (var pluginManager = new TheaterDaysPluginManager()) { pluginManager.LoadPlugins(); var configurationStore = ConfigurationHelper.CreateConfigurationStore(pluginManager); var cultureSpecificInfo = CultureSpecificInfoHelper.CreateCultureSpecificInfo(); using (var game = new Theater(options, pluginManager, configurationStore, cultureSpecificInfo)) { game.Run(); } exitCode = 0; } } else { var helpText = CommandLine.Text.HelpText.AutoBuild(optionsParsingResult); GameLog.Info(helpText); } #if SAFE_STARTUP } catch (Exception ex) { GameLog.Error(ex.Message); GameLog.Error(ex.StackTrace); } #endif #if ENABLE_GUI_CONSOLE GuiConsole.Uninitialize(); #endif return(exitCode); }
public void CallToTalk() { TelepathyBehaviour.CallToTalk(hero); var textObject = new TextObject("{=Telepathy_Hero_Will_Talk}{HeroName} will talk to you soon...", null); textObject.SetTextVariable("HeroName", hero.Name); GameLog.Info(textObject.ToString()); base.OnPropertyChanged(nameof(WillNotTalk)); }
private static int Main([NotNull, ItemNotNull] string[] args) { BaseGame.GraphicsBackend = GraphicsBackend.Direct3D11; GameLog.Initialize("arcaea-debug"); GameLog.Enabled = true; var exitCode = -1; var parser = new Parser(settings => { settings.IgnoreUnknownArguments = true; settings.CaseInsensitiveEnumValues = true; }); var optionsParsingResult = parser.ParseArguments <Options>(args); try { if (optionsParsingResult.Tag == ParserResultType.Parsed) { var options = ((Parsed <Options>)optionsParsingResult).Value; // Enable game log if the app is launched with "--debug" switch. GameLog.Enabled = options.IsDebugEnabled; using (var pluginManager = new ArcaeaSimPluginManager()) { pluginManager.LoadPlugins(); var configurationStore = ConfigurationHelper.CreateConfigurationStore(pluginManager); var cultureSpecificInfo = CultureSpecificInfoHelper.CreateCultureSpecificInfo(); using (var game = new ArcaeaSimApplication(pluginManager, configurationStore, cultureSpecificInfo)) { game.Run(); } exitCode = 0; } } else { var helpText = CommandLine.Text.HelpText.AutoBuild(optionsParsingResult); GameLog.Info(helpText); } } catch (Exception ex) { GameLog.Error(ex.Message); GameLog.Error(ex.StackTrace); Debug.Print(ex.ToString()); } return(exitCode); }
public bool RemoveGold(uint gold) { if (gold <= CurrentGold) { CurrentGold -= gold; GameLog.Info($"{gold} gold removed from vault {OwnerGuid}"); return(true); } else { GameLog.Info($"Attempt to remove {gold} gold from vault {OwnerGuid}, but only {CurrentGold} available"); return(false); } }
public bool AddGold(uint gold) { if (gold <= RemainingGold) { CurrentGold += gold; GameLog.Info($"{gold} gold added to vault {OwnerGuid}"); return(true); } else { GameLog.Info($"Attempt to add {gold} gold to vault {OwnerGuid}, but only {RemainingGold} available"); return(false); } }
IEnumerator InitializeLog() { if (isHeadless) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN ConsoleWindow.Instance.Initialize(); ConsoleWindow.Instance.SetTitle("DedicatedServer"); #endif yield return(StartCoroutine(Logging.Initialize("Config/headless_log.xml"))); } else { yield return(StartCoroutine(Logging.Initialize("Config/log.xml"))); } GameLog.Info("Log Initialize"); }
/// <summary> /// Perform the exchange once confirmation from both sides is received. /// </summary> /// <returns></returns> public void PerformExchange() { GameLog.Info("Performing exchange"); foreach (var item in _sourceItems) { _target.AddItem(item); } foreach (var item in _targetItems) { _source.AddItem(item); } _source.AddGold(_targetGold); _target.AddGold(_sourceGold); _source.ActiveExchange = null; _target.ActiveExchange = null; _source.Condition.InExchange = false; _target.Condition.InExchange = false; }
public bool RemoveItem(string itemName, ushort quantity = 1) { if (Items.ContainsKey(itemName)) { if (Items[itemName] > quantity) { Items[itemName] -= quantity; GameLog.Info($"{itemName} [{quantity}] removed from existing item in vault {OwnerGuid}"); } else { Items.Remove(itemName); GameLog.Info($"{itemName} removed from vault {OwnerGuid}"); } return(true); } else { return(false); } }
public void Redirect(Redirect redirect, bool isLogoff = false, int transmitDelay = 0) { GameLog.InfoFormat("Processing redirect"); GlobalConnectionManifest.RegisterRedirect(this, redirect); GameLog.InfoFormat("Redirect: cid {0}", this.ConnectionId); GameLog.Info($"Redirect EncryptionKey is {Encoding.ASCII.GetString(redirect.EncryptionKey)}"); if (isLogoff) { GlobalConnectionManifest.DeregisterClient(this); } redirect.Destination.ExpectedConnections.TryAdd(redirect.Id, redirect); var endPoint = Socket.RemoteEndPoint as IPEndPoint; byte[] addressBytes; if (Game.RedirectTarget != null) { addressBytes = Game.RedirectTarget.GetAddressBytes(); } else { addressBytes = IPAddress.IsLoopback(endPoint.Address) ? IPAddress.Loopback.GetAddressBytes() : Game.IpAddress.GetAddressBytes(); } Array.Reverse(addressBytes); var x03 = new ServerPacket(0x03); x03.Write(addressBytes); x03.WriteUInt16((ushort)redirect.Destination.Port); x03.WriteByte((byte)(redirect.EncryptionKey.Length + Encoding.ASCII.GetBytes(redirect.Name).Length + 7)); x03.WriteByte(redirect.EncryptionSeed); x03.WriteByte((byte)redirect.EncryptionKey.Length); x03.Write(redirect.EncryptionKey); x03.WriteString8(redirect.Name); x03.WriteUInt32(redirect.Id); x03.TransmitDelay = transmitDelay == 0 ? 250 : transmitDelay; Enqueue(x03); }
public bool AddItem(string itemName, ushort quantity = 1) { if (CurrentItemCount < ItemLimit) { if (Items.ContainsKey(itemName)) { Items[itemName] += quantity; GameLog.Info($"{itemName} [{quantity}] added to existing item in vault {OwnerGuid}"); } else { Items.Add(itemName, quantity); GameLog.Info($"{itemName} [{quantity}] added as new item in vault {OwnerGuid}"); } return(true); } else { GameLog.Info($"Attempt to add {itemName} [{quantity}] to vault {OwnerGuid}, but user doesn't have it?"); return(false); } }
/// <summary> /// Confirm the exchange. Once both sides confirm, perform the exchange. /// </summary> /// <returns>Boolean indicating success.</returns> public void ConfirmExchange(User requestor) { if (_source == requestor) { GameLog.InfoFormat("Exchange: source ({0}) confirmed", _source.Name); _sourceConfirmed = true; _target.SendExchangeConfirmation(false); } if (_target == requestor) { GameLog.InfoFormat("Exchange: target ({0}) confirmed", _target.Name); _targetConfirmed = true; _source.SendExchangeConfirmation(false); } if (_sourceConfirmed && _targetConfirmed) { GameLog.Info("Exchange: Both sides confirmed"); _source.SendExchangeConfirmation(); _target.SendExchangeConfirmation(); PerformExchange(); } }
public IEnumerator Initialize() { yield return(GameInitializer.Instance.StartCoroutine(BytesReader.Read(mConfigFileName, bytes => { if (null == bytes) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE File.WriteAllText( Path.Combine(Application.streamingAssetsPath, mConfigFileName), JsonUtility.ToJson(Instance, true), Encoding.UTF8); #endif GameLog.ErrorFormat("Read Config {0} Failed", mConfigFileName); } else { // NOTE(llisper): detect BOM mark // http://stackoverflow.com/questions/26101859/why-is-file-readallbytes-result-different-than-when-using-file-readalltext string json; if (bytes.Length > 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { json = Encoding.UTF8.GetString(bytes, 3, bytes.Length - 3); } else { json = Encoding.UTF8.GetString(bytes); } JsonUtility.FromJsonOverwrite(json, Instance); } }))); StringBuilder log = new StringBuilder("AppConfig:\n"); LogConfig(log, "AppConfig", this); GameLog.Info(log.ToString()); }
/// <summary> /// Write a message to the game (server) informational log. /// </summary> /// <param name="message">The message to be written</param> public void WriteLog(string message) { GameLog.Info(message); }
public static void Info(string message, string color = "#00ff00ff") { GameLog.Info(string.Format("<color={0}>{1}</color>", color, message)); }
public virtual List <Creature> GetTargets(Xml.Castable castable, Creature target = null) { List <Creature> actualTargets = new List <Creature>(); /* INTENT HANDLING FOR TARGETING * * This is particularly confusing so it is documented here. * UseType=Target Radius=0 Direction=None -> exact clicked target * UseType=Target Radius=0 Direction=!None -> invalid * UseType=Target Radius=>0 Direction=None -> rect centered on target * UseType=Target Radius>0 Direction=(anything but none) -> directional rect target based on click x/y * UseType=NoTarget Radius=0 Direction=None -> self (wings of protection, maybe custom spells / mentoring / lore / etc)? * UseType=NoTarget Radius>0 Direction=None -> rect from self in all directions * UseType=NoTarget Radius>0 Direction=!None -> rect from self in specific direction */ var intents = castable.Intents; foreach (var intent in intents) { var possibleTargets = new List <VisibleObject>(); if (intent.UseType == Xml.SpellUseType.NoTarget && intent.Target.Contains(Xml.IntentTarget.Group)) { // Targeting group members var user = this as User; if (user != null && user.Group != null) { possibleTargets.AddRange(user.Group.Members.Where(m => m.Map.Id == Map.Id && m.Distance(this) < intent.Radius)); } } else if (intent.UseType == Xml.SpellUseType.Target && intent.Radius == 0 && intent.Direction == Xml.IntentDirection.None) { // Targeting the exact clicked target if (target == null) { GameLog.Error($"GetTargets: {castable.Name} - intent was for exact clicked target but no target was passed?"); } else // If we're doing damage, ensure the target is attackable if (!castable.Effects.Damage.IsEmpty && target.Condition.IsAttackable) { possibleTargets.Add(target); } else if (castable.Effects.Damage.IsEmpty) { possibleTargets.Add(target); } } else if (intent.UseType == Xml.SpellUseType.NoTarget && intent.Radius == 0 && intent.Direction == Xml.IntentDirection.None) { // Targeting self - which, currently, is only allowed for non-damaging spells if (castable.Effects.Damage.IsEmpty) { possibleTargets.Add(this); } } else { // Area targeting, directional or otherwise Rectangle rect = new Rectangle(0, 0, 0, 0); byte X = this.X; byte Y = this.Y; // Handle area targeting with click target as the source if (intent.UseType == Xml.SpellUseType.Target) { X = target.X; Y = target.Y; } switch (intent.Direction) { case Xml.IntentDirection.Front: { switch (Direction) { case Xml.Direction.North: { //facing north, attack north rect = new Rectangle(X, Y - intent.Radius, 1, intent.Radius); } break; case Xml.Direction.South: { //facing south, attack south rect = new Rectangle(X, Y, 1, 1 + intent.Radius); } break; case Xml.Direction.East: { //facing east, attack east rect = new Rectangle(X, Y, 1 + intent.Radius, 1); } break; case Xml.Direction.West: { //facing west, attack west rect = new Rectangle(X - intent.Radius, Y, intent.Radius, 1); } break; } } break; case Xml.IntentDirection.Back: { switch (Direction) { case Xml.Direction.North: { //facing north, attack south rect = new Rectangle(X, Y, 1, 1 + intent.Radius); } break; case Xml.Direction.South: { //facing south, attack north rect = new Rectangle(X, Y - intent.Radius, 1, intent.Radius); } break; case Xml.Direction.East: { //facing east, attack west rect = new Rectangle(X - intent.Radius, Y, intent.Radius, 1); } break; case Xml.Direction.West: { //facing west, attack east rect = new Rectangle(X, Y, 1 + intent.Radius, 1); } break; } } break; case Xml.IntentDirection.Left: { switch (Direction) { case Xml.Direction.North: { //facing north, attack west rect = new Rectangle(X - intent.Radius, Y, intent.Radius, 1); } break; case Xml.Direction.South: { //facing south, attack east rect = new Rectangle(X, Y, 1 + intent.Radius, 1); } break; case Xml.Direction.East: { //facing east, attack north rect = new Rectangle(X, Y, 1, 1 + intent.Radius); } break; case Xml.Direction.West: { //facing west, attack south rect = new Rectangle(X, Y - intent.Radius, 1, intent.Radius); } break; } } break; case Xml.IntentDirection.Right: { switch (Direction) { case Xml.Direction.North: { //facing north, attack east rect = new Rectangle(X, Y, 1 + intent.Radius, 1); } break; case Xml.Direction.South: { //facing south, attack west rect = new Rectangle(X - intent.Radius, Y, intent.Radius, 1); } break; case Xml.Direction.East: { //facing east, attack south rect = new Rectangle(X, Y - intent.Radius, 1, intent.Radius); } break; case Xml.Direction.West: { //facing west, attack north rect = new Rectangle(X, Y, 1, 1 + intent.Radius); } break; } } break; case Xml.IntentDirection.Nearby: case Xml.IntentDirection.None: { //attack radius rect = new Rectangle(X - intent.Radius, Y - intent.Radius, Math.Max(intent.Radius, (byte)1) * 2, Math.Max(intent.Radius, (byte)1) * 2); } break; } GameLog.Info($"Rectangle: x: {X - intent.Radius} y: {Y - intent.Radius}, radius: {intent.Radius} - LOCATION: {rect.Location} TOP: {rect.Top}, BOTTOM: {rect.Bottom}, RIGHT: {rect.Right}, LEFT: {rect.Left}"); if (rect.IsEmpty) { continue; } possibleTargets.AddRange(Map.EntityTree.GetObjects(rect).Where(obj => obj is Creature && obj != this)); } // Remove merchants possibleTargets = possibleTargets.Where(e => !(e is Merchant)).ToList(); // Handle intent flags if (this is Monster) { // No hostile flag: remove users // No friendly flag: remove monsters // Group / pvp: do not apply here if (!intent.Target.Contains(Xml.IntentTarget.Friendly)) { possibleTargets = possibleTargets.Where(e => !(e is Monster)).ToList(); } if (!intent.Target.Contains(Xml.IntentTarget.Hostile)) { possibleTargets = possibleTargets.Where(e => !(e is User)).ToList(); } } else if (this is User && intent.UseType != Xml.SpellUseType.NoTarget) { var user = this as User; // No hostile flag: remove monsters // No friendly flag: remove users with pvp disabled // No pvp: remove // If we aren't targeting friendlies or pvp, remove all users entirely if (!intent.Target.Contains(Xml.IntentTarget.Pvp)) { possibleTargets = possibleTargets.Where(e => !(e is User && (e as Creature).Condition.PvpEnabled == true)).ToList(); } if (!intent.Target.Contains(Xml.IntentTarget.Friendly)) { possibleTargets = possibleTargets.Where(e => !(e is User && (e as Creature).Condition.PvpEnabled == false)).ToList(); } // If we aren't targeting hostiles, remove all monsters if (!intent.Target.Contains(Xml.IntentTarget.Hostile)) { possibleTargets = possibleTargets.Where(e => !(e is Monster)).ToList(); } } // Finally, add the targets to our list List <Creature> possible = intent.MaxTargets > 0 ? possibleTargets.Take(intent.MaxTargets).OfType <Creature>().ToList() : possibleTargets.OfType <Creature>().ToList(); if (possible != null && possible.Count > 0) { actualTargets.AddRange(possible); } else { GameLog.Info("No targets found"); } } return(actualTargets); }