Recent Posts

ExVenture Updates for August 2018

Posted on 27 Aug 2018

The last month of ExVenture kicked back in action now that Gossip is mostly stable. I tried to stick to a general theme of bug fixes and world building additions though. I wanted to get MidMUD read in advance of ElixirConf.

Links for MidMUD & ExVenture:

Gossip

Just because I let Gossip "sit", doesn't mean I didn't work on it! There were a few minor features that got touched on.

The home page now features a random connected game to be highlighted. Any game that is connected and has a home page url might show up on the front page.

Gossip Homepage

Gossip also got a cleaned up README since a lot of people mistakenly thought you needed to install NodeJS to connect. This was on the README as a requirement, but as a requirement to start the server itself.

There is a media page that contains a footer you can add to your homepage if you're apart of the network and want to show it off.

Gossip Elixir Client

The Elixir client got some updates as well. There were a few bugs hanging out related to the player list. If a game went offline completely with players attached, they would never go away from your games list. The list gets sweeped regularly for games that haven't been seen in a while.

Version 0.5.0 is out now on hex.pm.

Multi-Node Bugs

There were a few multi-node bugs that got cleaned out in preparation for my ElixirConf talk. I wanted to make sure that this was very stable before getting on stage to talk about it. The raft leader selection had a few small bugs in it. If a node went offline zone rebalancing wasn't actually happening (which is bad.)

Everytime a node came back online, a new election was triggered, no matter what. This one wasn't a horrible bug per se, but having the leader force itself should have been enough.

The world leader also now checks to see if all of the zones are online now periodically. I had noticed once that MidMUD had a zone down after a node died. I don't really know what happened, but scanning for all zones being online shouldn't be a bad thing.

I also found a slight issue with using :pg2 as a world leader list. Occasionally :pg2 hadn't caught up with the node dying before the world leader was trying to rebalance. Which resulted in the leader calling a dead node. I got around this by first filtering out the members list against the connected node list.

Performance Enhancements

I was curious about the possible performance of MidMUD during ElixirConf. Of course it will be a huge hit and everyone will be signing into it, so I wanted to make sure it could stand up to the brunt of that.

It's a good thing I did look into this as before any changes ExVenture completely fell over at about 230 connected players. After a few tweaks I was able to push this to 1200 connected players before it fell over due to RAM usage (how crazy is that.)

I will expand upon the changes I did in a future blog post. I don't want to give it all away in this!

Until then, you can checkout ou Venture Bot which is the bot framework I set up to connect as a player to ExVenture.

ExVenture 1200 players

General UX Improvements

No one could figure out how to complete a quest, which is my bad. I updated the hint system to let the player know whenever a quest is completable and also displays exactly how to complete that quest.

HINT: You have a quest that you can complete, use {command}quest complete [quest_id]{/command}. See {command}help quests{/command} for more information.

In addition to completing quests, picking them up was also a tad confusing. The hint message for NPCs talking to you was also updated. This will display only once per sign in.

HINT: You got a tell from an NPC. This might be the lead up to a quest. Please read carefully what they are asking about and you can {command}reply{/command} with your response.

With any luck these two hint additions should make questing much more accessible.

Templating Enhancements

The templating system got a decent set of additions. There is now a context struct that is very similar to a Phoenix conn struct. You can pipe it through a set of assigns and then finally "render" it through a template string. This makes it nicer to read in the code and I think removes some complications in calling template.

A few extra variables are available in room descriptions, such as the name of the room and the zone.

Every NPC, Item, Room, and Zone are also available to template in a lot of game strings via a new global resource template system. I was referring to a lot of these resources in quests and room descriptions on MidMUD and finally got annoyed enough while constantly renaming things to fix the problem.

Now you can refer to any of those 4 resources with [[room:1]] in game strings (the admin will say if it's available) and the templating system will find room 1 and print its name.

Room descriptions can also template room features in specific spots now. The feature key is available as a template item. This lets you weave in the features into specific spots of the description. All features will still be appended to the end of the description if none are used inside the text.

Script Additions

The final "big" thing for the month was an addition to quest scripts. You can now mark a line as triggering to another line with a delay. This lets you break up huge blocks of text with multiple tells, eventually leading to a line that has listeners or triggers a quest.

This was fun to add as the outcome was much more realistic in chatting with an NPC.

Smaller Tweaks

  • Global room features
  • Telnet login link is a link
  • Admin displays inline help for quest steps
  • Runs could parse poorly and cause a crash
  • Duplicate users in the who list due to issues in Session.Registry
  • Players going AFK at the login prompt could show as signed in
  • Channel command by itself was bugged
  • Gossip: API to view currently connected games
  • Multiple message of the days and after sign in messages
  • Updating many depdencies, we're on Elixir 1.7
  • Disable skills so they don't display or are usable
  • Strip colors from notification text
  • Add any flag to users, to add "Patron" text to patrons
  • Older saves did not migrate cleanly when some stats were no longer defaulting

Social Updates

This was a pretty big month for ExVenture and Gossip. The cowboy websockets blog post was picked up a few places and a lot of people found out about both. The discord server has gotten a few new people, some of which are new to Elixir and looking forward to learning it through ExVenture which is great!

If you're interested in joining the server to talk about ExVenture, this is the Discord invite.

I also have stickers if anyone spots me at ElixirConf next week.

ExVenture and Gossip Stickers

Next Month

With ElixirConf over after the first week of September, I might get back to bigger features. I would like to split characters apart from users, which is a huge refactor. But a refactor that has been waiting for a while. Some of this move was started with the tweaks that pushed ExVenture to 1200 players.

Elixir Cowboy Websocket Handler

Posted on 10 Aug 2018

For my side project Gossip I wanted to have a websocket connection for non-Phoenix connections. I did this by going straight to Cowboy and using a handler at that level. This explains how I did this for Gossip.

Gossip is a cross game chat service for MUDs, check it out.

The Handler

The full websocket handler is here on GitHub.

defmodule Web.SocketHandler do
  @behaviour :cowboy_websocket_handler

  def init(_, _req, _opts) do
    {:upgrade, :protocol, :cowboy_websocket}
  end

  def websocket_init(_type, req, _opts) do
    Logger.info("Socket starting")
    {:ok, req, %State{status: "inactive"}}
  end

  def websocket_handle({:text, message}, req, state) do
    with {:ok, message} <- Poison.decode(message),
         {:ok, response, state} <- Implementation.receive(state, message) do
      {:reply, {:text, Poison.encode!(response)}, req, state}
    else
      {:ok, state} ->
        {:ok, req, state}

      _ ->
        {:reply, {:text, Poison.encode!(%{status: "unknown"})}, req, state}
    end
  end
end

This is a snipped version of the full file, but the basics are here. This shows the websocket upgrading, a cowboy and websockets requirement. The init function upgrades to websockets and the websocket_init function is called after the upgrade.

The other function shown is when a new message is received. The message is JSON (or should be), so it gets parsed and then run through an implementation module elsewhere. Depending on the response from that submodule, different responses will get send back.

There are a few other cool things in the real module, so I encourage you to check it out.

Ping/Pong

One thing I had to add that I thought was included as part of the cowboy handler was a pong response to a client side ping. This actually crashed the websocket process a few times so I needed to add this as per the websocket spec:

def websocket_handle({:ping, message}, req, state) do
  {:reply, {:pong, message}, req, state}
end

Phoenix Configuration

Since we're using a lower level websocket (than Phoenix) we have to manually set up the cowboy dispatcher. This configuration shows the cowboy websocket handler along with a separate Phoenix channel, since I want to have both options.

If you go this route, you need to manually specify any Phoenix channels from here on out.

config :gossip, Web.Endpoint,
  http: [dispatch: [
    {:_, [
      {"/socket", Web.SocketHandler, []},
      {"/chat/websocket", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, {Web.Endpoint, Web.UserSocket, :websocket}}},
      {:_, Plug.Adapters.Cowboy.Handler, {Web.Endpoint, []}}
    ]}
  ]]

Conclusion

Setting up your own lower level websocket in Elixir/Phoenix turned out to be pretty simple. I am happy I went this route so I didn't have to worry about forcing the higher level Phoenix channels protocol on top of external clients.

If you're curious about more of the events Gossip sends, the docs are available here.

ExVenture Updates for July 2018

Posted on 25 Jul 2018

The last month of ExVenture has been pretty sparse compared to previous months. This has been due to me starting a new side service called Gossip. Gossip is a cross game chat network for MUDs.

Links for MidMUD & ExVenture:

Gossip

Gossip has been rolling around in my head for a while while working on ExVenture, but there has always been more pressing matters. About a month ago we were talking on the MUD Coders Guild about cross game chat and that inspired me to kick this off.

Gossip is similar to the I3 Network except it uses more standardized technologies. Secure WebSockets are the transport layer and all events are in JSON. You can see the documentation on Gossip.

ExVenture Remote Channels

The first big feature of Gossip is remote channels. You can flag a channel as a Gossip channel and it will try to send all communications up to the network.

ExVenture Remote Player Status

When your game is configured for Gossip, all signed in players are pushed up to Gossip. This lets other connected games see your players sign in and out. Right now all notifications are displayed to users on ExVenture. This is an optional but highly suggested feature for games that are not based on ExVenture.

This should help make your game feel more alive by letting your small pool (maybe just 1!) of players see others on the network.

The local who list will also display remote players, so users can see who is on the network.

Remote player list

ExVenture Remote Tells

The final big feature for Gossip right now is remote tells. If you're syncing your local players up to Gossip (and ExVenture does) then remote games and send tells to your local players. ExVenture lets you initiate tells and also handles reply for remote players.

This degrades nicely for remote games that do not support tells. As part of connecting a Gossip client says what features they support. For games that are not built on ExVenture remote tells are optional, but highly suggested.

First set of remote tells

Gossip Games List

I definitely suggest you check out the Gossip Games list. So far we have 5 games connected, more seem to be checking out Gossip every day!

Gossip Clients

The Gossip client from ExVenture has been pulled out into it's own Elixir hex package. If you're developing your own Elixir MUD (and there are a lot of you out there) then come join the fun and add the package.

Right now you do need to implement the full set of callbacks for all of the features of Gossip, but I would like to let you dictate which features your game supports and slowly add them in.

There is also a Ranvier bundle that supports remote channels and player status updates.

Next Month

Next month I hope to start back on ExVenture more and leave Gossip to sit for a bit. I think Gossip has a good enough feature set to let other games implement what's there and get some more feedback from the community.

Elixir OTP Supervision Tether

Posted on 09 Jul 2018

I got to try out a new OTP Supervision tree pattern in ExVenture, that I am going to call a tether.

Background

I started a new service, named Gossip, that ExVenture creates a persistent websocket connection to.

When this service dies or is not alive when the ExVenture server starts, the websocket connection will crash or refuse to start entirely. It crashes immediately and then cannot reconnect. This ripples up the supervision tree taking the entire application down in short order.

To get around this, I added a layer of supervision trees for just that socket process. My tree looks like this when fully booted:

- ExVenture
  - Gossip.Supverisor
    - Gossip.Monitor
    - Gossip.Supverisor.Tether
      - Gossip.Socket

The Process

The tether supervision starts with no childspecs. After boot the Monitor (or the cluster leader) will start the Socket inside the tether. When the socket process dies, it will eventually crash the tether supervisor causing it to restart.

When the tether supervisor restarts, it will restart with no children breaking the restart loop ("cutting the tether".)

Eventually the monitor process will try to restart the Gossip socket which may crash, causing the tether to crash and so on. Either way the crashing process was contained and the application stayed up.

Conclusion

The code for this was pretty simple, you can see it on GitHub in the gossip folder.

I learned of this at least part of this technique from Adam, over at the MUD Coders Guild. If you are interested in Elixir and multiplayer game programming, come check out the Slack and say Hi.

ExVenture Updates for June 2018

Posted on 29 Jun 2018

The last month of ExVenture was mostly the overworld, which I posted about previously. There were a lot of other smaller tweaks too.

Links for MidMUD & ExVenture:

Overworld

The overworld is a new extremely large feature for ExVenture. Admins can "paint" an overhead map that players can wander around. Exits can be made to rooms in the "old world" for travel back and forth.

I was very happy to get this working, even if there is still a large TODO list.

Overworld movement

Gossip

There was some conversation this week on the MUD Coders Slack that made me finally get around to a cross game chat network. I started the Gossip project for this. It's a simple Phoenix app that has a cowboy websocket handler to get around not using Phoenix channels.

I went with this route so others didn't have implement the Phoenix channels protocol in other languages. I also wanted something that was extremely stable, since Phoenix Channels has bumped versions fairly recently I don't want to have my library bump and break any existing connected game.

So far its been a fun exercise and it's currently working in a simple form of routing messages to connected applciations. I am in the middle of an ExVenture connect.

Mudlet Additions

When connecting via Mudlet, the package down auto downloads the world map. This should save a lot of wandering time for players to get a fully functional mapper.

I also got a patch into Mudlet based on some functionality I pulled out of the ExVenture package. This is available as part of Mudlet 3.10.

Mudlet has been working on Discord integration, and ExVenture is ready whenever that ships. I have basic status setting functionality set up at the moment.

Admin React

To sort of build myself up to what I thought I would need for the overworld, I started adding some nicer interfaces to the admin panel via React components. The first two I did were effects and quest scripts.

Effects are now done via a nice form that dumps to raw JSON. No longer do you need to edit that huge textarea by hand!

Quest scripts are now filled out by a nice form instead of of a text area and I also have a script tester right in the panel. You can see how the NPC would react without having to head in game.

Script Editor for Admins

Exits

Room exits got a massive overhaul in preparation for the overworld (and continued afterwards.) They are now one way, but the admin panel makes and destroys both directions. This drastically simplified the usage of exits inside of the code base.

The only tricky part was getting the reverse exit to be created for the overworld, but I will take one tricky spot over it being littered throughout the whole app.

As a bonus, this let me finally add in diagonal movement. You can go north east now.

Character Stats

I revamped the character stats. Movement points are gone, replaced with Endurance Points. They aren't used yet, but I would really like to let skills use Skill Points or Endurance Points. I might also rename Skill Points sometime in the future to better reflect the split. I want Endurance Points to be more physical based, and Skill Points to be more "mind" based.

The basic attributes have also been reworked. The new six attributes are:

  • Strength
  • Agility
  • Intelligence
  • Awareness
  • Vitality
  • Willpower

They all go in pairs of two to boost the HP, SP, and EP. Strength and Agility boost HP, Intelligence and Awareness boost SP, and Vitality and Willpower boost EP. This feels a lot better than how it was previously and has at least 100% more thought put into what they are and how they're named.

Web Client

The web client got a major face lift over the weekend. It now has a sidebar chat to track channel messages, so they don't get lost in the flow. I also tweaked the bottom bar to feel better, paddings and margins are now similar, along with font and font size. Some panels also got squeezed and moved around. Hopefully the new client looks much nicer to you as it does to me.

Web Client

Next Month

I hope to continue with the overworld and Gossip integration. These are both big features that will be fun to continue with in the coming months.

I am in the process of reading The Art of Game Design by Jesse Schell so I expect some changes to come from that. Namely I want to start thinking of how I want people to experience the game and start tweaking it to better reflect that. I expect this to be a slow process but highly worth the thought put into it.

Eric Oestrich
I am:
All posts
Creative Commons License
This site's content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License unless otherwise specified. Code on this site is licensed under the MIT License unless otherwise specified.