//* ────________________________________* //* methods ───────────────────────────────-* //* -----------------------------------------------------------------------* /// <summary>1フレーム分の更新処理を実行します。</summary> /// /// <param name="entity">この状態を適用されているオブジェクト。</param> /// <param name="privateMembers"> /// オブジェクトと状態クラスのみがアクセス可能なフィールド。 /// </param> /// <param name="gameTime">前フレームが開始してからの経過時間。</param> public override void update( CInputKeyboard entity, CInputKeyboard.CPrivateMembers privateMembers, GameTime gameTime ) { KeyboardState state = Keyboard.GetState(); IList <Keys> assignList = entity.assignList; for (int i = assignList.Count; --i >= 0;) { SInputState inputState = privateMembers.buttonStateList[i]; inputState.refresh(state.IsKeyDown(assignList[i])); privateMembers.buttonStateList[i] = inputState; } for (int i = entity.dirInputState.Length; --i >= 0;) { entity.dirInputState[i].refresh(state.IsKeyDown(entity.directionAssignList[i])); } EDirectionFlags axisFlags; Vector2 axisVector; CHelper.createVector(entity.dirInputState, out axisVector, out axisFlags); privateMembers.axisVector = axisVector; privateMembers.axisFlag = axisFlags; base.update(entity, privateMembers, gameTime); }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="modID">The mod's unique ID.</param> /// <param name="modDirectory">The full path to the mod's folder.</param> /// <param name="jsonHelper">Encapsulate SMAPI's JSON parsing.</param> /// <param name="inputState">Manages the game's input state.</param> /// <param name="events">Manages access to events raised by SMAPI.</param> /// <param name="contentHelper">An API for loading content assets.</param> /// <param name="commandHelper">An API for managing console commands.</param> /// <param name="dataHelper">An API for reading and writing persistent mod data.</param> /// <param name="modRegistry">an API for fetching metadata about loaded mods.</param> /// <param name="reflectionHelper">An API for accessing private game code.</param> /// <param name="multiplayer">Provides multiplayer utilities.</param> /// <param name="translationHelper">An API for reading translations stored in the mod's <c>i18n</c> folder.</param> /// <param name="contentPacks">The content packs loaded for this mod.</param> /// <param name="createContentPack">Create a transitional content pack.</param> /// <param name="deprecationManager">Manages deprecation warnings.</param> /// <exception cref="ArgumentNullException">An argument is null or empty.</exception> /// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception> public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, SInputState inputState, IModEvents events, IContentHelper contentHelper, ICommandHelper commandHelper, IDataHelper dataHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper, IEnumerable <IContentPack> contentPacks, Func <string, IManifest, IContentPack> createContentPack, DeprecationManager deprecationManager) : base(modID) { // validate directory if (string.IsNullOrWhiteSpace(modDirectory)) { throw new ArgumentNullException(nameof(modDirectory)); } if (!Directory.Exists(modDirectory)) { throw new InvalidOperationException("The specified mod directory does not exist."); } // initialise this.DirectoryPath = modDirectory; this.JsonHelper = jsonHelper ?? throw new ArgumentNullException(nameof(jsonHelper)); this.Content = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper)); this.Data = dataHelper ?? throw new ArgumentNullException(nameof(dataHelper)); this.Input = new InputHelper(modID, inputState); this.ModRegistry = modRegistry ?? throw new ArgumentNullException(nameof(modRegistry)); this.ConsoleCommands = commandHelper ?? throw new ArgumentNullException(nameof(commandHelper)); this.Reflection = reflectionHelper ?? throw new ArgumentNullException(nameof(reflectionHelper)); this.Multiplayer = multiplayer ?? throw new ArgumentNullException(nameof(multiplayer)); this.Translation = translationHelper ?? throw new ArgumentNullException(nameof(translationHelper)); this.ContentPacks = contentPacks.ToArray(); this.CreateContentPack = createContentPack; this.DeprecationManager = deprecationManager; this.Events = events; }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="modID">The mod's unique ID.</param> /// <param name="modDirectory">The full path to the mod's folder.</param> /// <param name="jsonHelper">Encapsulate SMAPI's JSON parsing.</param> /// <param name="inputState">Manages the game's input state.</param> /// <param name="events">Manages access to events raised by SMAPI.</param> /// <param name="contentHelper">An API for loading content assets.</param> /// <param name="contentPackHelper">An API for managing content packs.</param> /// <param name="commandHelper">An API for managing console commands.</param> /// <param name="dataHelper">An API for reading and writing persistent mod data.</param> /// <param name="modRegistry">an API for fetching metadata about loaded mods.</param> /// <param name="reflectionHelper">An API for accessing private game code.</param> /// <param name="multiplayer">Provides multiplayer utilities.</param> /// <param name="translationHelper">An API for reading translations stored in the mod's <c>i18n</c> folder.</param> /// <exception cref="ArgumentNullException">An argument is null or empty.</exception> /// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception> public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, SInputState inputState, IModEvents events, IContentHelper contentHelper, IContentPackHelper contentPackHelper, ICommandHelper commandHelper, IDataHelper dataHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper) : base(modID) { // validate directory if (string.IsNullOrWhiteSpace(modDirectory)) { throw new ArgumentNullException(nameof(modDirectory)); } if (!Directory.Exists(modDirectory)) { throw new InvalidOperationException("The specified mod directory does not exist."); } // initialise this.DirectoryPath = modDirectory; this.Content = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper)); this.ContentPacks = contentPackHelper ?? throw new ArgumentNullException(nameof(contentPackHelper)); this.Data = dataHelper ?? throw new ArgumentNullException(nameof(dataHelper)); this.Input = new InputHelper(modID, inputState); this.ModRegistry = modRegistry ?? throw new ArgumentNullException(nameof(modRegistry)); this.ConsoleCommands = commandHelper ?? throw new ArgumentNullException(nameof(commandHelper)); this.Reflection = reflectionHelper ?? throw new ArgumentNullException(nameof(reflectionHelper)); this.Multiplayer = multiplayer ?? throw new ArgumentNullException(nameof(multiplayer)); this.Translation = translationHelper ?? throw new ArgumentNullException(nameof(translationHelper)); this.Events = events; #if !SMAPI_3_0_STRICT this.JsonHelper = jsonHelper ?? throw new ArgumentNullException(nameof(jsonHelper)); #endif }
//* ────________________________________* //* methods ───────────────────────────────-* //* -----------------------------------------------------------------------* /// <summary>1フレーム分の更新処理を実行します。</summary> /// /// <param name="entity">この状態を適用されているオブジェクト。</param> /// <param name="privateMembers"> /// オブジェクトと状態クラスのみがアクセス可能なフィールド。 /// </param> /// <param name="gameTime">前フレームが開始してからの経過時間。</param> public override void update( CInputXBOX360 entity, CInputXBOX360.CPrivateMembers privateMembers, GameTime gameTime) { GamePadState state = GamePad.GetState(entity.playerIndex); if (state.IsConnected) { for (int i = entity.assignList.Count; --i >= 0;) { Buttons button = entity.assignList[i]; SInputState inputState = privateMembers.buttonStateList[i]; if (button.isAvailableAnalogInput()) { inputState.refresh(state.getInputState(button)); } else { inputState.refresh(state.IsButtonDown(button)); } privateMembers.buttonStateList[i] = inputState; } refleshAxis(state, entity, privateMembers, gameTime); } else { entity.Dispose(); } base.update(entity, privateMembers, gameTime); }
//* -----------------------------------------------------------------------* /// <summary>1フレーム分の更新処理を実行します。</summary> /// /// <param name="entity">この状態を適用されているオブジェクト。</param> /// <param name="privateMembers"> /// オブジェクトと状態クラスのみがアクセス可能なフィールド。 /// </param> /// <param name="gameTime">前フレームが開始してからの経過時間。</param> public override void update( CInputLegacy entity, CInputLegacy.CPrivateMembers privateMembers, GameTime gameTime) { JoystickState state = privateMembers.poll(); byte[] buttons = state.GetButtons(); int totalButtons = buttons.Length; for (int i = entity.assignList.Count; --i >= 0;) { short sButtonID = entity.assignList[i]; SInputState inputState = privateMembers.buttonStateList[i]; if (sButtonID < 0) { inputState.refresh(state.getInputState(sButtonID, INPUTRANGE)); } else if (sButtonID < totalButtons) { inputState.refresh(buttons[sButtonID] != 0); } privateMembers.buttonStateList[i] = inputState; } refleshAxis(state, entity, privateMembers, gameTime); base.update(entity, privateMembers, gameTime); }
//* ────────────-_______________________* //* constructor & destructor ───────────────────────* //* -----------------------------------------------------------------------* /// <summary>コンストラクタ。</summary> /// /// <param name="playerNumber">プレイヤー番号。</param> /// <param name="firstState">初期状態。</param> public CInput(short playerNumber, IState firstState) : base(firstState) { for (int i = 4; --i >= 0; dirInputState[i] = new SInputState(this)) { ; } this.playerNumber = playerNumber; }
//* -----------------------------------------------------------------------* /// <summary>1フレーム分の更新処理を実行します。</summary> /// /// <param name="entity">この状態を適用されているオブジェクト。</param> /// <param name="privateMembers"> /// オブジェクトと状態クラスのみがアクセス可能なフィールド。 /// </param> /// <param name="gameTime">前フレームが開始してからの経過時間。</param> public override void update(CInputCollection entity, CInputCollection.CPrivateMembers privateMembers, GameTime gameTime) { int nLength = privateMembers.buttonStateList.Count; // HACK : GC対策をする bool[] buttonFlagBuffer = new bool[nLength]; SDirArray dirFlagBuffer = new SDirArray(); privateMembers.axisFlag = EDirectionFlags.None; privateMembers.axisVector = Vector2.Zero; foreach (CInput input in privateMembers.childs) { // 毎回isConnectするのは大変な気がするが……。 if (!entity.releaseAwayController || input.connect) { input.update(gameTime); for (int i = nLength; --i >= 0;) { buttonFlagBuffer[i] = buttonFlagBuffer[i] || input.buttonStateList[i].press; } for (int i = 4; --i >= 0;) { dirFlagBuffer[i] = MathHelper.Max(dirFlagBuffer[i], input.dirInputState[i].analogValue); } Vector2 axis = entity.axisVector; float axisLength = axis.Length(); axis += input.axisVector; if (axis != Vector2.Zero) { axis.Normalize(); } axis *= MathHelper.Max(axisLength, input.axisVector.Length()); privateMembers.axisVector = axis; privateMembers.axisFlag |= input.axisFlag; } else { input.Dispose(); } } for (int i = nLength; --i >= 0;) { SInputState inputState = privateMembers.buttonStateList[i]; inputState.refresh(buttonFlagBuffer[i]); privateMembers.buttonStateList[i] = inputState; } for (int i = 4; --i >= 0;) { entity.dirInputState[i].refresh(dirFlagBuffer[i]); } base.update(entity, privateMembers, gameTime); }
/********* ** Private methods *********/ /// <summary>Get the buttons that were pressed, held, or released since the previous tick.</summary> /// <param name="inputState">The game's current input state.</param> private Dictionary <SButtonState, SButton[]> GetButtonsByState(SInputState inputState) { Dictionary <SButtonState, SButton[]> lookup = inputState.ButtonStates .GroupBy(p => p.Value) .ToDictionary(p => p.Key, p => p.Select(p => p.Key).ToArray()); foreach (var state in new[] { SButtonState.Pressed, SButtonState.Held, SButtonState.Released }) { if (!lookup.ContainsKey(state)) { lookup[state] = new SButton[0]; } } return(lookup); }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="inputState">Manages input visible to the game.</param> /// <param name="gameLocations">The observable list of game locations.</param> public WatcherCore(SInputState inputState, ObservableCollection <GameLocation> gameLocations) { // init watchers this.CursorWatcher = WatcherFactory.ForEquatable(() => inputState.CursorPosition); this.MouseWheelScrollWatcher = WatcherFactory.ForEquatable(() => inputState.LastMouse.ScrollWheelValue); this.SaveIdWatcher = WatcherFactory.ForEquatable(() => Game1.hasLoadedGame ? Game1.uniqueIDForThisGame : 0); this.WindowSizeWatcher = WatcherFactory.ForEquatable(() => new Point(Game1.viewport.Width, Game1.viewport.Height)); this.TimeWatcher = WatcherFactory.ForEquatable(() => Game1.timeOfDay); this.ActiveMenuWatcher = WatcherFactory.ForReference(() => Game1.activeClickableMenu); this.LocationsWatcher = new WorldLocationsTracker(gameLocations, MineShaft.activeMines); this.LocaleWatcher = WatcherFactory.ForGenericEquality(() => LocalizedContentManager.CurrentLanguageCode); this.Watchers.AddRange(new IWatcher[] { this.CursorWatcher, this.MouseWheelScrollWatcher, this.SaveIdWatcher, this.WindowSizeWatcher, this.TimeWatcher, this.ActiveMenuWatcher, this.LocationsWatcher, this.LocaleWatcher }); }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="button">The button on the controller, keyboard, or mouse.</param> /// <param name="cursor">The cursor position.</param> /// <param name="inputState">The game's current input state.</param> internal ButtonPressedEventArgs(SButton button, ICursorPosition cursor, SInputState inputState) { this.Button = button; this.Cursor = cursor; this.InputState = inputState; }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="button">The button on the controller, keyboard, or mouse.</param> /// <param name="cursor">The cursor position.</param> /// <param name="inputState">The game's current input state.</param> internal InputButtonReleasedArgsInput(SButton button, ICursorPosition cursor, SInputState inputState) { this.Button = button; this.Cursor = cursor; this.InputState = inputState; }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="modID">The unique ID of the relevant mod.</param> /// <param name="inputState">Manages the game's input state.</param> public InputHelper(string modID, SInputState inputState) : base(modID) { this.InputState = inputState; }
/// <summary> /// /// </summary> /// <param name="playerIndex">The player index.</param> /// <param name="instanceIndex">The instance index.</param> /// <param name="monitor">Encapsulates monitoring and logging for SMAPI.</param> /// <param name="reflection">Simplifies access to private game code.</param> /// <param name="eventManager">Manages SMAPI events for mods.</param> /// <param name="input">Manages the game's input state.</param> /// <param name="modHooks">Handles mod hooks provided by the game.</param> /// <param name="multiplayer">The core multiplayer logic.</param> /// <param name="exitGameImmediately">Immediately exit the game without saving. This should only be invoked when an irrecoverable fatal error happens that risks save corruption or game-breaking bugs.</param> /// <param name="onUpdating">Raised when the instance is updating its state (roughly 60 times per second).</param> internal void PreInitialize(PlayerIndex playerIndex, int instanceIndex, Monitor monitor, Reflector reflection, EventManager eventManager, SInputState input, SModHooks modHooks, SMultiplayer multiplayer, Action <string> exitGameImmediately, Action onInitialized, Action onContentLoaded, Action <SGame, GameTime, Action> onUpdating, Action <SGame, GameTime, Action> onPlayerInstanceUpdating) { this.OnInitialized = onInitialized; this.OnContentLoaded = onContentLoaded; this.OnUpdating = onUpdating; this.OnPlayerInstanceUpdating = onPlayerInstanceUpdating; }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="cursor">The cursor position.</param> /// <param name="inputState">The game's current input state.</param> internal ButtonsChangedEventArgs(ICursorPosition cursor, SInputState inputState) { this.Cursor = cursor; this.ButtonsByState = new Lazy <Dictionary <SButtonState, SButton[]> >(() => this.GetButtonsByState(inputState)); }
/// <summary>Create a game instance for a local player.</summary> /// <param name="playerIndex">The player index.</param> /// <param name="instanceIndex">The instance index.</param> public override Game1 CreateGameInstance(PlayerIndex playerIndex = PlayerIndex.One, int instanceIndex = 0) { SInputState inputState = new SInputState(); return(new SGame(playerIndex, instanceIndex, this.Monitor, this.Reflection, this.Events, inputState, this.ModHooks, this.Multiplayer, this.ExitGameImmediately, this.OnPlayerInstanceUpdating, this.OnGameContentLoaded)); }