Interface IAction
An in-game action. Every action should be replayable, because multiple nodes in a network should execute an action and get the same result.
A “class” which implements this interface is analogous to a function, and its instance is analogous to a partial function application, in other words, a function with some bound arguments. Those parameters that will be bound at runtime should be represented as fields or properties in an action class, and bound argument values to these parameters should be received through a constructor parameters of that class.
Namespace: Libplanet.Action
Assembly: Libplanet.dll
Syntax
public interface IAction
Examples
The following example shows how to implement an action of three types of in-game logic:
using System;
using System.Collections.Immutable;
using Libplanet;
using Libplanet.Action;
public class MyAction : IAction
{
// Declare an enum type to distinguish types of in-game logic.
public enum ActType { CreateCharacter, Attack, Heal }
// Declare properties (or fields) to store "bound" argument values.
public ActType Type { get; private set; }
public Address TargetAddress { get; private set; }
// Action must has a public parameterless constructor.
// Usually this is used only by Libplanet's internals.
public MyAction() {}
// Take argument values to "bind" through constructor parameters.
public MyAction(ActType type, Address targetAddress)
{
Type = type;
TargetAddress = targetAddress;
}
// The main game logic belongs to here. It takes the
// previous states through its parameter named context,
// and is offered "bound" argument values through
// its own properties (or fields).
IAccountStateDelta IAction.Execute(IActionContext context)
{
// Gets the state immediately before this action is executed.
// ImmutableDictionary<string, uint> is just for example,
// As far as it is serializable, you can store any types.
// (We recommend to use immutable types though.)
var state = (ImmutableDictionary<string, uint>)
context.PreviousStates.GetState(TargetAddress);
// This variable purposes to store the state
// right after this action finishes.
ImmutableDictionary<string, uint> nextState;
// Does different things depending on the action's type.
// This way is against the common principals of programming
// as it is just an example. You could compare this with
// a better example of PolymorphicAction<T> class.
switch (Type)
{
case ActType.CreateCharacter:
if (!TargetAddress.Equals(context.Signer))
throw new Exception(
"TargetAddress of CreateCharacter action " +
"only can be the same address to the " +
"Transaction<T>.Signer.");
else if (!(state is null))
throw new Exception(
"Character was already created.");
nextState = ImmutableDictionary<string, uint>.Empty
.Add("hp", 20);
break;
case ActType.Attack:
nextState =
state.SetItem("hp", Math.Max(state["hp"] - 5, 0));
break;
case ActType.Heal:
nextState =
state.SetItem("hp", Math.Min(state["hp"] + 5, 20));
break;
default:
throw new Exception(
"Properties are not properly initialized.");
}
// Builds a delta (dirty) from previous to next states, and
// returns it.
return context.PreviousStates.SetState(TargetAddress,
nextState);
}
// Serializes its "bound arguments" so that they are transmitted
// over network or stored to the persistent storage.
// It uses .NET's built-in serialization mechanism.
IImmutableDictionary<string, object> IAction.PlainValue =>
ImmutableDictionary<string, object>.Empty
.Add("type", Type)
.Add("target_address", TargetAddress);
// Deserializes "bound arguments". That is, it is inverse
// of PlainValue property.
void IAction.LoadPlainValue(
IImmutableDictionary<string, object> plainValue)
{
Type = (ActType)plainValue["type"];
TargetAddress = (Address)plainValue["target_address"];
}
}
Note that the above example has several bad practices. Compare this example with PolymorphicAction<T>'s example.
Properties
| Improve this Doc View SourcePlainValue
Serializes values bound to an action, which is held by properties (or fields) of an action, so that they can be transmitted over network or saved to persistent storage.
Serialized values are deserialized by LoadPlainValue(IImmutableDictionary<String, Object>) method later.
Declaration
IImmutableDictionary<string, object> PlainValue { get; }
Property Value
Type | Description |
---|---|
IImmutableDictionary<String, Object> | A value which encodes this action's bound values (held by properties or fields). It has to be serializable. |
See Also
Methods
| Improve this Doc View SourceExecute(IActionContext)
Executes the main game logic of an action. This should be deterministic.
Through the context
object,
it receives information such as a transaction signer,
its states immediately before the execution,
and a deterministic random seed.
Other “bound” information resides in the action object in itself, as its properties (or fields).
A returned AddressStateMap object functions as a delta which shifts from previous states to next states.
Declaration
IAccountStateDelta Execute(IActionContext context)
Parameters
Type | Name | Description |
---|---|---|
IActionContext | context | A context object containing addresses that signed the transaction, states immediately before the execution, and a PRNG object which produces deterministic random numbers. See IActionContext for details. |
Returns
Type | Description |
---|---|
IAccountStateDelta | A map of changed states (so-called "dirty"). |
Remarks
This method should be deterministic: for structurally (member-wise) equal actions and IActionContexts, the same result should be returned.
For randomness, never use Random nor any other PRNGs provided by other than Libplanet. Use Random instead.
Also do not perform I/O operations such as file system access or networking. These bring an action indeterministic.
See Also
| Improve this Doc View SourceLoadPlainValue(IImmutableDictionary<String, Object>)
Deserializes serialized data (i.e., data PlainValue property made), and then fills this action's properties (or fields) with the deserialized values.
Declaration
void LoadPlainValue(IImmutableDictionary<string, object> plainValue)
Parameters
Type | Name | Description |
---|---|---|
IImmutableDictionary<String, Object> | plainValue | Data (made by PlainValue property) to be deserialized and assigned to this action's properties (or fields). |