oestrich / grapevine Goto Github PK
View Code? Open in Web Editor NEWThe MUD Chat Network
Home Page: https://grapevine.haus/
License: MIT License
The MUD Chat Network
Home Page: https://grapevine.haus/
License: MIT License
Whenever an event is viewed as a webpage, increase it's view count. Display in the admin panel.
Trying to follow the instructions for getting this working, I have exactly the required software versions specified. I see this:
[master] grapevine $ mix deps.get
** (CompileError) config/config.exs:1: module Config is not loaded and could not be found
(elixir) lib/code.ex:232: Code.eval_string/3
(mix) lib/mix/config.ex:220: Mix.Config.eval!/2
Is the assumption that one will set this up via vagrant or docker instead of locally?
• • • • •
I kind of expected a bin/setup
or something similar to get started working on an issue. :)
Allow games to have a hosted site, which has a nice display and access to the web client.
Send a remote player a tells. This should be placed behind a tells
support flag. Suggested you also support the players
flag.
To send a new message, use this event.
{
"event": "tells/send",
"ref": "5c528fc3-cb9e-4867-98ea-6e235594241e",
"payload": {
"from": "Player",
"game": "MidMUD",
"player": "eric",
"sent_at": "2018-07-17T13:12:28Z",
"message": "hi"
}
}
from
- local playergame
- remote game, this is the short name of a gameplayer
- remote playersent_at
- ISO8601 formatted timestamp of when the message was sent, in the UTC timezonemessage
- the messageIf the game and player is online on Gossip, then the message will be forwarded. A ref
is required.
{
"event": "tells/send",
"ref": "5c528fc3-cb9e-4867-98ea-6e235594241e",
"status": "success"
}
{
"event": "tells/send",
"ref": "5c528fc3-cb9e-4867-98ea-6e235594241e",
"status": "failure",
"error": "game offline"
}
Possible errors:
When the game receives a new direct message from another game on the network, this event will be pushed.
{
"event": "tells/receive",
"ref": "d4a08749-acbe-45ab-bc0f-51609fd6b95b",
"payload": {
"game": "AMud",
"from": "Player",
"player": "eric",
"sent_at": "2018-07-17T13:12:28Z",
"message": "hi"
}
}
from
- remove playergame
- remote game, this is the short name of a gameplayer
- local playersent_at
- ISO8601 formatted timestamp of when the message was sent, in the UTC timezonemessage
- the messageThe current /events
page should look like a calendar.
On connect optionally send the client's known version of Gossip, save this.
{
"event": "authenticate",
"payload": {
"client_id": "client id",
"client_secret": "client secret",
"version": "1.0.0",
"supports": ["channels"],
"channels": ["gossip"],
"user_agent": "ExVenture 0.23.0"
}
}
This will let the app display a notification for the game's admin to let them know new features of Gossip are available. For instance when direct messaging is added (#2) it will be more obvious.
If the version is not sent, default to 1.0.0
.
I want to help contribute to the web client, and I guess this is the only way to get it running.
So I followed the instructions laid out. I have all the deps installed.
Under Setup, when I get to yarn --cwd assets
, I get:
gesslar@LIAM:~/git/grapevine/apps/grapevine$ yarn --cwd assets
Usage: yarn [options]
yarn: error: no such option: --cwd
I'm not really sure what the above is supposed to do, so I powered on anyway, and tried to run mix ecto.reset
and got the following results:
gesslar@LIAM:~/git/grapevine/apps/grapevine$ mix ecto.reset
23:45:53.952 [error] GenServer #PID<0.417.0> terminating
** (RuntimeError) connect raised KeyError exception: key :password not found. The exception details are hidden, as they may contain sensitive data such as database credentials. You may set :show_sensitive_data_on_connection_error to true when starting your connection if you wish to see all of the details
(elixir) lib/keyword.ex:393: Keyword.fetch!/2
(postgrex) lib/postgrex/protocol.ex:720: Postgrex.Protocol.auth_md5/4
(postgrex) lib/postgrex/protocol.ex:577: Postgrex.Protocol.handshake/2
(db_connection) lib/db_connection/connection.ex:69: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: nil
State: Postgrex.Protocol
** (Mix) The database for GrapevineData.Repo couldn't be dropped: killed
This all seems like a lot to just work on the client. Am I doing something wrong?
Send out an incoming restart event.
{
"event": "restart",
"payload": {
"downtime": 15
}
}
downtime
is the number of seconds the server expects to be down. The server should stagger each connected socket +/- a random amount of seconds from the expected value given.
Once the event is sent the server may stop at any moment.
In order for game admins to see how people land on the web client, allow for tracking a referral query parameter and display via a simple report.
Report:
Gossip will soon have achievements, games can unlock them for players and they will be displayed on Grapevine if the character has been associated to a profile.
To enable discovery of smaller games by letting players collect and share achievements.
This is what Gossip will hold on to. Grapevine will handle the character association. This is for a single achievement.
Games will manage their achievements on Gossip, from the game show page, similar to connections. Create, edit, update achievements. Possibly delete them, deleting would clear out all associated player unlocks.
On any state change for an achievement, a backbone sync event will occur and update on Grapevine for display. Grapevine will have a public listing on the game profile page.
Games can have a maximum of 500 points in achievements.
To unlock an achievement for one of your players, send this event. The achievement must be from your game's list.
{
"event": "achievements/unlock",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964",
"payload": {
"achievement": "bbba4676-ac94-4e47-ad6c-f24c0192ac23",
"unlocked_at": "2018-12-29T13:12:28Z",
"name": "Player"
}
}
Response if a ref is provided:
{
"event": "achievements/unlock",
"status": "success",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964"
}
This will echo to the system backbone for Grapevine to catch on and unlock the achievement from there. Grapevine must ack this request before a response is sent back to the game. If Grapevine fails to ack within X seconds then the request is failed and the game is notified.
To record partial progress for one of your players, send this event. The achievement must be from your game's list.
{
"event": "achievements/record",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964",
"payload": {
"achievement": "bbba4676-ac94-4e47-ad6c-f24c0192ac23",
"progress": 10,
"recorded_at": "2018-12-29T13:12:28Z",
"name": "Player"
}
}
To request the achievements Gossip knows about send this event:
{
"event": "achievements/sync",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964"
}
ref
is requiredThe response will be a series of sync events back to you:
{
"event": "achievements/sync",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964",
"payload": {
"total": 45,
"achievements": []
}
}
This response is "paginated" by sending chunked up events, correlated by the same ref
. Each event will contain up to 10 achievements. The total number of achievements is included in each event so you know how many are being sent.
To manage achievements inside your game, Gossip can provide a set of CRUD events. refs are required. A response event will be sent back with possible errors.
{
"event": "achievements/create",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964",
"payload": {
"title": "Achievement"
}
}
{
"event": "achievements/update",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964",
"payload": {
"key": "bbba4676-ac94-4e47-ad6c-f24c0192ac23",
"title": "An Achievement"
}
}
{
"event": "achievements/delete",
"ref": "22d61b78-5ad4-4cfa-933f-02c6172d0964",
"payload": {
"key": "bbba4676-ac94-4e47-ad6c-f24c0192ac23"
}
}
Add a url to the games home page.
I made a simple image file for my test game Age of Elements and the page https://grapevine.haus/manage/games/157/edit presents an Internal Server Error when I upload the image file, which is a small PNG file, attached.
Could you take a look when you get a chance?
Instead of everyone reading the README, the server should host its own docs.
Moderation is hard. Let's start thinking about how to tackle this. Raisin will be the tool that handles this.
Some ideas, note that they may not be implemented - food for thought for now:
Switch games from belongs_to :user
to has_many :admins
Create a new join table that let's multiple users administrate a game. No special roles at the moment, all admins can manage the full aspect of a game.
Maybe we keep the current belongs_to :user
and rename to be the "owner" so we can tell who originally made it and maybe who should have slight extra power in the future. Other systems have the concept of owner and admin, and just admin.
Criteria:
I am able to securely telnet from Mudlet to my test game with ageofelements.org 8680. This does not function for Grapevine at this time when I register this address into Grapevine. This is not a high priority for me as normal telnet functions just fine, but I wanted to register the issue. Thank you!
Move the games listing to the sidebar, always display the full list, Games
becomes a header, each game is a link to the manage page
Right now when MSSP cannot be found in a single check, MSSP checking is completely disabled. Instead of completely disabling, create an admin alert and leave it turned on.
I have noticed you can't send a multiline message using the client. The enter button sends the message, which is fine, but It would be good to be able to use shift+enter to insert a new line.
I've also noticed that if you copy some text with line breaks and you paste it into the client input the line breaks get replaced by whitespaces.
My use case for this is the game I'm developing where users may enter descriptions for items or rooms they create. Splitting the message in different lines is great to make the descriptions more readable. I believe it would be useful for other games too.
API to generate a new phoenix token to use as a session token for the web client. This should generate a token similar to the SessionToken
plug.
For use in oestrich/grapevine-mobile#3
On a new message, gossip should strip MXP tags before broadcast.
Add a new games
support flag to unlock events related to games.
First event would be games/status
. To request updates on connected games run:
{
"event": "games/status",
"ref": "2134c964-5223-4ea7-99db-c499c13565fe"
}
The connected game would then receive a new event for each connected game. Similar to:
{
"event":"games/status",
"ref": "2134c964-5223-4ea7-99db-c499c13565fe",
"payload":{
"game": "Olympia",
"display_name": "Olympia MUD",
"description": "...",
"homepage_url": "https://...",
"user_agent": "ExVenture 0.26.0",
"user_agent_repo_url": "https://...",
"connections": [
{"type": "telnet", "host": "example.com", "port": "4000"},
{"type": "web", "url": "https://example.com/play"}
],
"supports": ["channels", "players", "tells", "games"],
"players_online_count": 3,
"uptime_seconds": 123
}
}
A single game can also be requested, by short name:
{
"event": "games/status",
"ref": "2134c964-5223-4ea7-99db-c499c13565fe",
"payload": {
"short_name": "Olympia",
}
}
{[reason: :function_clause, mfa: {Web.SocketHandler, :websocket_handle, 3},
stacktrace: [{Web.SocketHandler, :websocket_handle, [{:ping, ""}, {:http_req,
On https://gossip.haus/register/new, Register your game
doesn't quite jive with the information asked for or the current working model that allows you to register many games per user account.
Button on the settings page to generate new keys
Games that have an open socket(s) should be listed as online and have a websocket query for it.
Inspired by MSP
The client will enable sound by including "Client.Sounds 1"
as part of the initial Core.Supports
messages.
Core.Supports.Set ["Client.Media 1", ...]
You can set the default values for certain other messages by sending this message.
Client.Media.Default {
"url": "https://www.example.com/sounds/"
}
Send a Client.Sounds.Start
event to start playing a sound or music file.
Client.Media.Start {
"key": "zone-background-music",
"url": "https://example.com/",
"name": background.mp3",
"type": "music",
"tag": "zones",
"volume": 100,
"loops": -1,
"continue": true,
"priority": 51
}
"sound"
, options "music"
or "sound"
1-100
, default 50
, relative volume that the sound will play at-1
or 1+
, default 1
, number of loops that the sound file should play before stopping, -1
continues until a stop event is senttrue
, if true
the sound file will continue playing if already playing, false
will restart the sound1-100
, default 50
, if a higher priority sound comes in, all sounds of the same type under it will stop playingTo stop a media file that may be running, send an event with a filter to stop all matching media.
Client.Media.Stop {
"key": "zone-background-music",
"type": "music",
"priority": 50,
"tag": "zones",
"name": "background.mp3"
}
The filter above will check all active media files, and any matching media is stopped. For key, type, tag, and name, a simple string match is performed. For priority, anything below or equal to the sent value is matched.
Media must match all sent values in order to be considered a match and stopped.
To stop all sounds, send an event with no key.
Client.Media.Stop {}
Play a combat sound.
Client.Media.Start {
"key": "combat",
"url": "https://example.com/sword-swing.mp3"
}
Interrupt your sword swing with the enemy blocking.
Client.Media.Start {
"key": "block",
"url": "https://example.com/block.mp3",
"priority": 51
}
Play zone background music.
Client.Media.Start {
"key": "zone-background-music",
"url": "https://example.com/background.mp3",
"type": "music",
"loops": -1,
"continue": true
}
Migrate to a new zone.
Client.Media.Start {
"key": "zone-background-music",
"url": "https://example.com/background2.mp3",
"type": "music",
"loops": -1,
"continue": false
}
Continue playing the zone's background, but add in a passing storm.
Client.Media.Start {
"key": "storm",
"url": "https://example.com/background-storm.mp3",
"type": "music",
"loops": -1,
"continue": false
}
Stop the storm, the zone background will continue playing.
Client.Media.Stop {
"key": "storm"
}
In order to provide extra information for your game, you should be able to attach links, things such as an interview on Titans of Text, a well thought out review, game help, etc.
Follows up #121
Add in a new message for core
that will let you replay a channel from a UID. This will let you catch up if your game was briefly offline.
The server will send:
{
"event": "channels/replay",
"ref": "28523394-6dcf-4c2a-ad1d-2d0ef8bb823b",
"payload": {
"channel": "grapevine",
"since": "b35198e0-07cb-43f9-b644-7bb6640d2c0f"
}
}
This could then send broadcast messages for anything missed. Since they have a timestamp this might be ok. Alternatively there can be a separate replay response that includes paginated messages.
Should be just supports: ["channels"]
for now, but eventually a game can opt into direct messaging. This should be validated against a list on the server and refuse entry for extra values.
Games should handle disconnects without crashing, should reconnect, etc.
A simple report to see the number of opened web client sessions for a time range.
Report:
Ties with #70
Set up prometheus metrics:
#{name}@#{game}
Have a "Surprise Me" game picker on the game listing page.
Two modes:
Part of the players
support flag.
Request:
{
"events": "players/status",
"ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4"
}
ref
is required.
Response:
{
"events": "players/status",
"ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4",
"payload": {
"MidMUD": ["eric"],
"Myelin": ["Admin"],
"Apotheosis": ["Adam"]
}
}
In order to group games together, let's have a tagging system. This will be managed by admins and not freeform. This will allow for highly curated tags.
Extra:
Example tags:
As a MUD owner
I want to be able to generate modal window on the web-client
So that I can create a richer experience for my web-client players
No posting, read only
channels/subscribe
messagechannels/unsubscribe
messageWe should add a UID and timestamp field to messages. The server would add both of these fields when broadcasting out.
timestamp
will be a ISO8601 timestamp in UTCuid
will be a string that uniquely identifies this messageSending stays as normal:
{
"event": "channels/send",
"ref": "28523394-6dcf-4c2a-ad1d-2d0ef8bb823b",
"payload": {
"channel": "grapevine",
"name": "Player",
"message": "Hello everyone!"
}
}
Games listening on your channel now receive these extra fields.
{
"event": "channels/broadcast",
"ref": "89036074-446f-41ab-b87a-44ef1f962f2e",
"payload": {
"uid": "a61a2913-84c6-410d-bee0-e2bd8d34374e",
"timestmap": "2019-11-22T18:00:00Z",
"channel": "grapevine",
"message": "Hello everyone!",
"game": "ExVenture",
"name": "Player"
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.