Skip to content

Commit c8ec949

Browse files
authored
Merge pull request #114 from alwaysintreble/split_docs
Split docs into smaller pieces to be more digestible
2 parents 063dfa5 + 3a2c335 commit c8ec949

File tree

10 files changed

+676
-403
lines changed

10 files changed

+676
-403
lines changed

docfx/docfx.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"resource": [
2727
{
2828
"files": [
29-
"images/**"
29+
"img/**"
3030
]
3131
}
3232
],
@@ -36,8 +36,9 @@
3636
"modern"
3737
],
3838
"globalMetadata": {
39-
"_appName": "multiclient",
40-
"_appTitle": "multiclient",
39+
"_appName": "Archipelago.MultiClient.Net",
40+
"_appTitle": "Archipelago.MultiClient.Net",
41+
"_appLogoPath": "img/logo/color-icon.svg",
4142
"_enableSearch": true,
4243
"pdf": false
4344
}

docfx/docs/helpers/datastore.md

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# DataStorage
2+
3+
DataStorage support is included in the library. You may save values on the archipelago server in order to share them
4+
across other player's sessions or to simply keep track of values outside your game's state.
5+
6+
The DataStorage provides an interface based on keys and their scope. By assigning a value to a key, that value is stored
7+
on the server and by reading from a key a value is retrieved from the server.
8+
Assigning and reading values from the store can be done using simple assignments `=`:
9+
10+
* `= session.DataStorage["Key"]`, read value from the data storage synchronously
11+
* `session.DataStorage["Key"] =`, write value to the data storage asynchronously
12+
* Complex objects need to be stored and retrieved in the form of a `JObject`, therefore you must wrap them into a
13+
`JObject.FromObject()`
14+
15+
The DataStorage also provides methods to retrieve the value of a key asynchronously using `[key].GetAsync`.
16+
To set the initial value of a key without overriding any existing value, the `[key].Initialize` method can be used.
17+
If you're interested in keeping track of when a value of a certain key is changed by any client you can use the
18+
`[key].OnValueChanged` handler to register a callback for when the value gets updated.
19+
20+
Mathematical operations on values stored on the server are supported using the following operators:
21+
22+
* `+`, Add right value to left value
23+
* `-`, Subtract right value from left value
24+
* `*`, Multiply left value by right value
25+
* `/`, Divide left value by right value
26+
* `%`, Gets remainder after dividing left value by right value
27+
* `^`, Multiply left value by the power of the right value
28+
29+
Bitwise operations on values stored on the server are supported using the following operations:
30+
31+
* `+ Bitwise.Xor(x)`, apply logical exclusive OR to the left value using value x
32+
* `+ Bitwise.Or(x)`, apply logical OR to the left value using value x
33+
* `+ Bitwise.And(x)`, apply logical AND to the left value using value x
34+
* `+ Bitwise.LeftShift(x)`, binary shift the left value to the left by x
35+
* `+ Bitwise.RightShift(x)`, binary shift the left value to the right by x
36+
37+
Other operations on values stored on the server are supported using the following operations:
38+
39+
* `+ Operation.Min(x)`, get the lowest value of the left value and x
40+
* `+ Operation.Max(x)`, get the highest value of the left value and x
41+
* `+ Operation.Remove(x)`, when the left value is a list, removes the first element with value x
42+
* `+ Operation.Pop(x)`, when the left value is a list or dictionary, removes the element at index x or key x
43+
* `+ Operation.Update(x)`, when the left value is a list or dictionary, updates the dictionary with the keys/values in x
44+
45+
Operation specific callbacks are supported, these get called only once with the results of the current operation:
46+
47+
* `+ Callback.Add((oldValue, newValue) => {});`, calls this method after your operation or chain of operations are
48+
processed by the server
49+
50+
Mathematical operations, bitwise operations and callbacks can be chained, given the extended syntax with `()` around
51+
each operation.
52+
53+
Examples:
54+
55+
```csharp
56+
var session = ArchipelagoSessionFactory.CreateSession("localhost", 38281);
57+
session.TryConnectAndLogin("Timespinner", "Jarno", ItemsHandlingFlags.AllItems);
58+
59+
//Initializing
60+
session.DataStorage["B"].Initialize(20); //Set initial value for B in global scope if it has no value assigned yet
61+
62+
//Storing/Updating
63+
session.DataStorage[Scope.Slot, "SetPersonal"] = 20; //Set `SetPersonal` to 20, in scope of the current connected user\slot
64+
session.DataStorage[Scope.Global, "SetGlobal"] = 30; //Set `SetGlobal` to 30, in global scope shared among all players (the default scope is global)
65+
session.DataStorage["Add"] += 50; //Add 50 to the current value of `Add`
66+
session.DataStorage["Divide"] /= 2; //Divide current value of `Divide` in half
67+
session.DataStorage["Max"] += + Operation.Max(80); //Set `Max` to 80 if the stored value is lower than 80
68+
session.DataStorage["Dictionary"] = JObject.FromObject(new Dictionary<string, int>()); //Set `Dictionary` to a Dictionary
69+
session.DataStorage["SetObject"] = JObject.FromObject(new SomeClassOrStruct()); //Set `SetObject` to a custom object
70+
session.DataStorage["BitShiftLeft"] += Bitwise.LeftShift(1); //Bitshift current value of `BitShiftLeft` to left by 1
71+
session.DataStorage["Xor"] += Bitwise.Xor(0xFF); //Modify `Xor` using the Bitwise exclusive or operation
72+
session.DataStorage["DifferentKey"] = session.DataStorage["A"] - 30; //Get value of `A`, Assign it to `DifferentKey` and then subtract 30
73+
session.DataStorage["Array"] = new []{ "One", "Two" }; //Arrays can be stored directly, List's needs to be converted ToArray() first
74+
session.DataStorage["Array"] += new []{ "Three" }; //Append array values to existing array on the server
75+
76+
//Chaining operations
77+
session.DataStorage["Min"] = (session.DataStorage["Min"] + 40) + Operation.Min(100); //Add 40 to `Min`, then Set `Min` to 100 if `Min` is bigger than 100
78+
session.DataStorage["C"] = ((session.DataStorage["C"] - 6) + Bitwise.RightShift(1)) ^ 3; //Subtract 6 from `C`, then multiply `C` by 2 using bitshifting, then take `C` to the power of 3
79+
80+
//Update callbacks
81+
//EnergyLink deplete pattern, subtract 50, then set value to 0 if its lower than 0
82+
session.DataStorage["EnergyLink"] = ((session.DataStorage["EnergyLink"] - 50) + Operation.Min(0)) + Callback.Add((oldData, newData) => {
83+
var actualDepleted = (float)newData - (float)oldData; //calculate the actual change, might differ if there was less than 50 left on the server
84+
});
85+
86+
//Keeping track of changes
87+
session.DataStorage["OnChangeHandler"].OnValueChanged += (oldData, newData) => {
88+
var changed = (int)newData - (int)oldData; //Keep track of changes made to `OnChangeHandler` by any client, and calculate the difference
89+
};
90+
91+
//Keeping track of change (but for more complex data structures)
92+
session.DataStorage["OnChangeHandler"].OnValueChanged += (oldData, newData) => {
93+
var old_dict = oldData.ToObject<Dictionary<int, int>>();
94+
var new_dict = newData.ToObject<Dictionary<int, int>>();
95+
};
96+
97+
//Retrieving
98+
session.DataStorage["Async"].GetAsync<string>(s => { string r = s }); //Retrieve value of `Async` asynchronously
99+
float f = session.DataStorage["Float"]; //Retrieve value for `Float` synchronously and store it as a float
100+
var d = session.DataStorage["DateTime"].To<DateTime>() //Retrieve value for `DateTime` as a DateTime struct
101+
var array = session.DataStorage["Strings"].To<string[]>() //Retrieve value for `Strings` as string Array
102+
103+
//Handling anonymous object, if the target type is not known you can use `To<JObject>()` and use its interface to access the members
104+
session.DataStorage["Anonymous"] = JObject.FromObject(new { Number = 10, Text = "Hello" }); //Set `Anonymous` to an anonymous object
105+
var obj = session.DataStorage["Anonymous"].To<JObject>(); //Retrieve value for `Anonymous` where an anonymous object was stored
106+
var number = (int)obj["Number"]; //Get value for anonymous object key `Number`
107+
var text = (string)obj["Text"]; //Get value for anonymous object key `Text`
108+
109+
```

docfx/docs/helpers/events.md

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Event Hooks
2+
3+
## ArchipelagoSocket
4+
5+
@"Archipelago.MultiClient.Net.Helpers.ArchipelagoSocketHelper?text=ArchipelagoSocketHelper", accessible through
6+
`Session.Socket`
7+
8+
| Event | Call Event |
9+
|-------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
10+
| @"Archipelago.MultiClient.Net.Helpers.ArchipelagoSocketHelperDelagates.ErrorReceivedHandler?text=ErrorReceived" | Called when there is an error in the socket connection or while parsing a packet. |
11+
| @"Archipelago.MultiClient.Net.Helpers.ArchipelagoSocketHelperDelagates.PacketReceivedHandler?text=PacketReceived" | Called when a packet has been received from the server and identified. |
12+
| @"Archipelago.MultiClient.Net.Helpers.ArchipelagoSocketHelperDelagates.PacketsSentHandler?text=PacketsSent" | Called just before submitting a packet to the server. |
13+
| @"Archipelago.MultiClient.Net.Helpers.ArchipelagoSocketHelperDelagates.SocketClosedHandler?text=SocketClosed" | Called when the underlying socket connection has been closed. |
14+
| @"Archipelago.MultiClient.Net.Helpers.ArchipelagoSocketHelperDelagates.SocketOpenedHandler?text=SocketOpened" | Called when the underlying socket connection is opened to the server. |
15+
16+
## ReceivedItemsHelper
17+
18+
@"Archipelago.MultiClient.Net.Helpers.IReceivedItemsHelper?text=ReceivedItemsHelper", accessible through `Session.Items`.
19+
20+
| Event | Call Event |
21+
|--------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
22+
| @"Archipelago.MultiClient.Net.Helpers.ReceivedItemsHelper.ItemReceivedHandler?text=ItemReceived" | When an item is received. If multiple items are received in a single packet, the event is fired for each individual item. |
23+
24+
## LocationCheckHelper
25+
26+
@"Archipelago.MultiClient.Net.Helpers.LocationCheckHelper?text=LocationCheckHelper", accessible through
27+
`Session.Locations`.
28+
29+
| Event | Call Event |
30+
|------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|
31+
| @"Archipelago.MultiClient.Net.Helpers.LocationCheckHelper.CheckedLocationsUpdatedHandler?text=CheckedLocationsUpdated" | Called when new locations are checked, such as another player using !collect |
32+
33+
## MessageLogHelper
34+
35+
@"Archipelago.MultiClient.Net.Helpers.MessageLogHelper?text=MessageLogHelper", accessible through `Session.MessageLog`
36+
37+
| Event | Call Event |
38+
|-------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
39+
| @"Archipelago.MultiClient.Net.Helpers.MessageLogHelper.MessageReceivedHandler?text=OnMessageReceived" | Called for each message that should be displayed for the player. |
40+
41+
### Message Logging
42+
43+
The Archipelago server can send messages to client to be displayed on screen as a sort of log, this is done by handling
44+
the `PrintJsonPacket` packets. This library simplifies this process into a
45+
@"Archipelago.MultiClient.Net.Helpers.IMessageLogHelper?text='single handler'".
46+
47+
```csharp
48+
var session = ArchipelagoSessionFactory.CreateSession("localhost", 38281);
49+
session.MessageLog.OnMessageReceived += OnMessageReceived;
50+
session.TryConnectAndLogin("Timespinner", "Jarno", ItemsHandlingFlags.AllItems, new Version(0,3,5));
51+
52+
static void OnMessageReceived(LogMessage message)
53+
{
54+
DisplayOnScreen(message.ToString());
55+
}
56+
```
57+
58+
In some cased you might want extra information that is provided by the server in such cases you can use type checking
59+
60+
```csharp
61+
static void OnMessageReceived(LogMessage message)
62+
{
63+
switch (message)
64+
{
65+
case ItemHintLogMessage hintLogMessage:
66+
var receiver = itemSendLogMessage.Receiver;
67+
var sender = itemSendLogMessage.Sender;
68+
var networkItem = itemSendLogMessage.Item;
69+
var found = hintLogMessage.IsFound;
70+
break;
71+
case ItemSendLogMessage itemSendLogMessage:
72+
var receiver = itemSendLogMessage.Receiver;
73+
var sender = itemSendLogMessage.Sender;
74+
var networkItem = itemSendLogMessage.Item;
75+
break;
76+
}
77+
78+
DisplayOnScreen(message.ToString());
79+
}
80+
```
81+
82+
If you want more control over how the message is displayed, like for example you might want to color certain parts of
83+
the message, then you can use the `Parts` property. This returns each part of the message in order of appearance with
84+
the `Text` to be displayed and also the `Color` it would normally be displayed in. If `IsBackgroundColor` is true, then
85+
the color should be applied to the message background instead. The MessagePart message can also contain additional
86+
information that can be retrieved by type checking.
87+
88+
```csharp
89+
foreach (part in message.Parts)
90+
{
91+
switch (part)
92+
{
93+
case ItemMessagePart itemMessagePart:
94+
var itemId = itemMessagePart.ItemId;
95+
var flags = itemMessagePart.Flags;
96+
break;
97+
case LocationMessagePart locationMessagePart:
98+
var locationId = locationMessagePart.LocationId;
99+
break;
100+
case PlayerMessagePart playerMessagePart:
101+
var slotId = playerMessagePart.SlotId;
102+
var isCurrentPlayer = playerMessagePart.IsActivePlayer;
103+
break;
104+
}
105+
106+
DisplayOnScreen(part.Text, part.Color, part.IsBackgroundColor);
107+
}
108+
```

docfx/docs/helpers/helpers.md

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Helper Overview
2+
3+
```csharp
4+
session.Socket // Payload-agnostic interface for sending/receving the most basic transmission units between client/server
5+
session.Items // Helpers for handling receipt of items
6+
session.Locations // Helpers for reporting visited locations to the server
7+
session.Players // Helpers for translating player information such as number, alias, name etc.
8+
session.DataStorage // Helpers for reading/writing data globally accessible to any client connected in the room
9+
session.ConnectionInfo // Helpers for reading/handling useful information on the current connection
10+
session.RoomState // Information on the state of the room
11+
session.MessageLog // Interface for the server to push info messages to the user
12+
```
13+
14+
## Players
15+
16+
The @"Archipelago.MultiClient.Net.Helpers.IPlayerHelper?text=Player Helper" provides methods for accessing details
17+
about the other players currently connected to the Archipelago
18+
session.
19+
20+
## Locations
21+
22+
The @"Archipelago.MultiClient.Net.Helpers.ILocationCheckHelper?text=Locations Helper" provides methods for accessing
23+
information regarding the current player's locations, as well as updating the server on the status of their locations.
24+
25+
### Report Collected Location(s)
26+
27+
Call the following method to inform the server of locations whose items have been "found", and therefore should be
28+
distributed if necessary:
29+
30+
```csharp
31+
// Report multiple at once
32+
session.Locations.CompleteLocationChecks(new []{1,3,8});
33+
34+
// Or report one at a time
35+
session.Locations.CompleteLocationChecks(3);
36+
```
37+
38+
The location ID used is of that defined in the AP world.
39+
40+
### Scout Location Checks
41+
42+
Scouting means asking the server what is stored in a specific location *without* collecting it. This can also be
43+
utilized in order to create a hint, if - for instance - the current player knows what is on the location to inform other
44+
players of this knowledge.
45+
46+
```csharp
47+
session.Locations.ScoutLocationsAsync(locationInfoPacket => Console.WriteLine(locationInfoPacket.Locations.Count), HintCreationPolicy.CreateAndAnnounceOnce, new []{4, 5});
48+
```
49+
50+
## Items
51+
52+
The @"Archipelago.MultiClient.Net.Helpers.IReceivedItemsHelper?text=Received Items Helper" provides methods for
53+
checking the player's current inventory, and receiving items from the server.
54+
55+
### Received Item Callback Handler (Asynchronous)
56+
57+
```csharp
58+
// Must go BEFORE a successful connection attempt
59+
session.Items.ItemReceived += (receivedItemsHelper) => {
60+
var itemReceivedName = receivedItemsHelper.PeekItemName() ?? $"Item: {itemId}";
61+
62+
// ... Handle item receipt here
63+
64+
receivedItemsHelper.DequeueItem();
65+
};
66+
```
67+
68+
*Note: This callback event will occur for every item on connection and reconnection.*
69+
70+
## RoomState
71+
72+
The @"Archipelago.MultiClient.Net.Helpers.IRoomStateHelper?text=RoomState Helper" provides access to values that
73+
represent the current state of the multiworld room, with information such as the cost of a hint and or your current
74+
accumulated amount of hint point or the permissions for things like forfeiting.
75+
76+
```csharp
77+
Console.WriteLine($"You have {session.RoomState.HintPoints}, and need {session.RoomState.HintCost} for a hint");
78+
```
79+
80+
## ConnectionInfo
81+
82+
The @"Archipelago.MultiClient.Net.Helpers.IConnectionInfoProvider?text=ConnectionInfo Helper" provides access to
83+
values under which you are currently connected, such as your slot number or your currently used tags and item handling
84+
flags.
85+
86+
```csharp
87+
Console.WriteLine($"You are connected on slot {session.ConnectionInfo.Slot}, on team {session.ConnectionInfo.Team}");
88+
```
89+
90+
## ArchipelagoSocket
91+
92+
The @"Archipelago.MultiClient.Net.Helpers.IConnectionInfoProvider?text=Socket Helper" is a lower level API allowing
93+
for direct access to the socket which the session object uses to communicate with the Archipelago server. You may use
94+
this object to hook onto when messages are received, or you may use it to send any packets defined in the library.
95+
Various events are exposed to allow for receipt of errors or notifying of socket close.
96+
97+
```csharp
98+
session.Socket.SendPacket(new SayPacket(){Text = "Woof woof!"});
99+
```
100+
101+
## MessageLog
102+
103+
The Archipelago server can send messages to client to be displayed on screen as a sort of log, this is done by handling
104+
the `PrintJsonPacket` packets. This library simplifies this process into a
105+
@"Archipelago.MultiClient.Net.Helpers.IMessageLogHelper?text=single handler" that can be subscribed to with an
106+
[event hook](events.md).
107+
108+
## DeathLink
109+
110+
DeathLink support is included in the library. You may enable it by creating a new
111+
@"Archipelago.MultiClient.Net.BounceFeatures.DeathLink.DeathLinkService?text=DeathLinkService" from the
112+
@"Archipelago.MultiClient.Net.BounceFeatures.DeathLink.DeathLinkProvider?text=DeathLinkProvider", and subscribing to the
113+
`OnDeathLinkReceived` event. Deathlink can then be toggled on and off using the `EnableDeathlink` and `DisableDeathlink`
114+
methods on the service.
115+
116+
```csharp
117+
var session = ArchipelagoSessionFactory.CreateSession("localhost", 38281);
118+
119+
var deathLinkService = session.CreateDeathLinkService();
120+
121+
deathLinkService.OnDeathLinkReceived += (deathLinkObject) => {
122+
// ... Kill your player(s).
123+
};
124+
125+
deathLinkService.EnableDeathlink();
126+
// ... On death:
127+
deathLinkService.SendDeathLink(new DeathLink("Ijwu", "Died to exposure."));
128+
```

0 commit comments

Comments
 (0)