Giter Site home page Giter Site logo

thorium-sim / thorium Goto Github PK

View Code? Open in Web Editor NEW
148.0 14.0 67.0 208.82 MB

Platform for starship simulator controls

Home Page: https://thoriumsim.com

License: Apache License 2.0

JavaScript 69.16% HTML 0.22% CSS 0.12% TypeScript 25.69% Shell 0.01% SCSS 4.80%
thorium graphql light-controller realtime javascript simulator-controls react video apollo spaceship

thorium's Introduction

Thorium

Be sure to check out Thorium Nova, the next generation of Spaceship Simulator controls

Test Discord All Contributors Version GitHub last commit (branch)

Thorium

A simulator controls platform

New here? Check out the contributing document.

Want something to work on? Here's where we need help. Not sure what it is or how to work with Thorium? Guides are in the docs website.

What is Thorium?

Thorium is a guided narrative multiplayer cooperative real-time spaceship bridge simulator. Let's unpack all that vocabulary

  • Narrative: Thorium prioritizes storytelling and narrative over action and spectacle.
  • Guided: The narrative is lead by a Flight Director, who works to help players feel connected to the story.
  • Multiplayer: Thorium is intended to be played by multiple players.
  • Cooperative: Players are intended to work together to win the game.
  • Spaceship: The gameplay of Thorium takes place in space.
  • Bridge Simulator: Players each run an individual station that runs a small part of the entire ship.
  • Real-time: The action in Thorium is immediate and non-stop.

Thorium is flexible enough to provide a system for creating an integrated, distributed, fault-tolerant show-control system that can power lights, sound, video, and take input and provide output to a wide variety of devices.

Created with โค by Alex Anderson and Fyreworks.

A note about support

Thorium is a self-organized "community support" project. We encourage everyone to use it and continue to submit issues and bug reports. Alex is the maintainer, and will continue to:

  • Review issues
  • Review pull requests and provide feedback
  • Merge pull requests
  • Create new builds/releases
  • Encourage and assist other developers
  • Focus his efforts on long-term projects and keeping the codebase modern.

Fortunately, you can get help from the excellent people on Thorium's Discord Server.

If you need better support for your Thorium simulator, Alex is happy to contract with you to do so. Reach out via Discord to start the process.

If you want to learn to contribute to Thorium, check out the development video series for some ideas for how to get started.

Hope this helps!

Guiding Principles

Thorium is based on years of experience building starship simulator controls for Space Edventures centers in Utah. This experience drives a number of guiding principles which should underscore all feature development in the project:

  • The Flight Director is the master of the simulation. Therefore, everything in Thorium should support the flight director. New features should not remove control or power from the flight director. Features should also strive to not distract the flight director from giving the crew the best experience possible. The best features both give the flight director more ability to help the crew while not detracting from the flight director's focus.
  • Crew enjoyment is the primary reason for Thorium's use. Education, research, and training are all secondary objectives to the crew having a good time. Why? Because if the crew is not having a good time, they likely aren't learning or aren't providing good data for research. Features in Thorium should certainly foster good environments for education, but not understanding how a card works or a task being too difficult or too boring can quickly take away from students learning.
  • While Thorium works hard to be the end-all-be-all of starship simulator controls, there is no reason every single feature has to be bundled with Thorium itself. The core of Thorium is a way to distribute and configure data between multiple clients. Using the same mechanisms which crew clients connect, external clients, like lighting controllers and hardware panels, can also connect.
  • Thorium is a powerful platform. Regrettably, while its design allows for powerful interactions and screens, it isn't friendly for beginning developers like many previous simulator controls sets have been. This is one of the biggest downsides to Thorium. Something that could improve Thorium's experience for beginning developers would be ideal.

Getting Started

Install Yarn from https://yarnpkg.com

then

yarn install
yarn start

Then open the app or GraphiQL

Building the App

yarn build

Builds the app for production and bundles it into a packaged terminal app.

Deploying

Thorium releases are automatically deployed when changes are merged into Master.

Migrating

Thorium does not use a traditional database; instead, it stores information in a json file. To migrate your Thorium instance to another computer, simply copy the snapshot.json and snapshot-restore.json files along with any assets you may be using and drop them in the new thorium directory. Startup the Thorium app and you'll be on your way.

Translations

Thorium is currently in the process of supporting i18n translations. Want to add translated strings for your language? If the language doesn't exist, add it to the package.json file. Also be sure to add the locale data to the /src/helpers/intl.js.

Translations are done with react-intl. A good example of how this can be used is the /src/containers/FilghtDirector/Welcome.js file.

Contributors

Thanks goes to these wonderful people (emoji key):


Alex

๐Ÿ’ป ๐Ÿ“– ๐ŸŽจ

Emrix

๐Ÿ’ป ๐Ÿ‘€ ๐Ÿค”

ctolley6

๐Ÿค” โœ…

Todd Rasband

๐ŸŽจ

Brent Anderson

๐Ÿค”

Farpoint

๐Ÿ›

Isaac Ostler

๐Ÿ›

Jed Fox

๐Ÿ’ป

Lilah

๐Ÿ’ป

kimballfrank

๐ŸŽจ ๐Ÿค”

aBlueShadow

๐Ÿค” ๐ŸŒ

John Robe

๐Ÿ› ๐Ÿ’ป

Keith Smith

๐Ÿ› ๐Ÿ’ป

MaesonBusk

๐Ÿ“–

Eric Mansfield

๐Ÿ’ป โš ๏ธ

sassyspock

๐Ÿ“– ๐Ÿ› ๐Ÿ’ป

Justin

๐Ÿ“– ๐Ÿ› ๐Ÿ“

thoriumsim

๐Ÿ“– โœ… ๐Ÿ“น

JordanDeSmith

๐Ÿ’ป

Mason Edmondson

๐Ÿ›

Isaac Evans

๐Ÿ› โš ๏ธ

SoshJam

๐Ÿ’ป

This project follows the all-contributors specification. Contributions of any kind welcome!

thorium's People

Contributors

ablueshadow avatar alexanderson1993 avatar codacy-badger avatar ctolley6 avatar dependabot-support avatar dependabot[bot] avatar emrix avatar ericman314 avatar gitter-badger avatar greenkeeper[bot] avatar isaaccubeman avatar j-f1 avatar jordandesmith avatar jrobe avatar justintime50 avatar ksmithut avatar lilith-nightrose avatar matweaver7 avatar miketweaver avatar mitchell-foote avatar mitchell-foote-adobe avatar sassyspock avatar semantic-release-bot avatar soshjam avatar thoriumsim avatar trajkov avatar unit1229 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thorium's Issues

Sticky Client Information

Create some method of linking a specific client to an entry in the database. Perhaps when a client first connects, check to see if there is a localStorage key in place with the ID for the client. If there isn't, insert a new client record and store the resulting ID in that localStorage key. Use it to maintain client state.

Thrusters

Like Galileo: Remove impulse control and docking control

Create a Flight Director Ticketing System

Allow flight directors to write tickets for problems or suggestions. It would be a dropdown on the core. It would use the Github API to create an issue for this project.

Different levels of difficulties for cards in a station

Use navigation as an example:

Level 1: Calculate course, click "Lock in course"
Level 2: Calculate course, type in coordinates
Level 3: Triangulate location, calculate angle to destination, set thrusters

On the core, you could change the level for individual stations: eg. 5th grader vs 30 year old.

Analytics

Flights need a mechanism for keeping telemetry. This should be a timestamped log (time according to the server, probably) of JSON documents or something similar. Rethink wouldn't be bad for this. As long as it's not tightly coupled with the database, you're fine.

Psychometrics

This is definitely far down the list of stuff for your platform, but I think it's worth mentioning here.

Thorium would benefit from having the ability to collect information from participants about their aptitude with certain concepts, aspects of self esteem, how they hold their peers, and other areas of feedback. Collecting this information in bulk would enable us to profile students and help us better cater the simulations to them (although we would need to be careful to respect privacy laws governing the collection of student information - of which I'm not an expert).

Create offline card mechanism

This will be attached to the card container, so it uses the same layout. it will default to 'Station Offline' text, and will lock out all access to other cards. Should also be included in the layouts themselves. Information about the offline status should be attached to the simulator object.

Panel support for Stations

Make it so panels appear as clients on the Thorium server; have stations specifically for hardware panels which don't have cards, but can still initialize to a specific simulator and send messages as part of that flight.

Shields

Reactive based on the number of shield systems available

Exocomps

Exocomps are small robots which can be used to repair the ship. They are provided with parts and assigned a system to repair or upgrade. Upgraded systems have special powers or abilities provided to them.

The current UI shows a diagram of the ship, along with where each exocomp is. While this is cool, it is just as effective to show the status of the exocomps:

  • Idle
  • Traveling
  • Repairing/Upgrading

This creates a simple finite state machine which can be applied to the exocomps.

Create status card

Specifically for the command station

Fly flights, not simulators

A flight is an instance of one or more simulators (with all the sub components), dropped into an instance of the universe. By flying flights, The same simulator can have multiple simultaneous experiences. It also gives easier management of long running flight experiences.

Create login card

The login card will be tied to the client object stored in the database to keep track of who is logged into which client. It will automatically be shown if the client is not logged in.

Effective state management

State needs to be managed effectively in order to achieve the following objectives:

  • Freeze and thaw flight state to save/reload flight configuration
  • Track mutation events triggered by simulator events and time
  • Track mutation events triggered by inbound input from clients
  • Broadcast the latest state to subscribed clients

Freeze/Thaw vs Cloning

There are two approaches to creating a flight. One is to have a fully serialized flight state that is used to build the runtime of the flight (OTP Supervisor tree). This flight's state can then be serialized and stored back in the database as a new snapshot of a flight. This approach is similar to how Flint tackled this problem - it would simply scan all documents for the right simulator_id and it would build everything it needed for runtime based on that factor.

An alternative approach would be to have a mechanism for keeping track of flight state, and another mechanism for generating a flight in the first place. I'll call this "cloning". Essentially, a mission template would exist that describes the initial state of the flight (e.g. the number of simulators, their configuration, baseline sensor contacts for the universe, etc.). This initial state would serve as the foundation for the actual runtime events of the flight itself.

If Freeze/Thaw is sufficient, that's great. The biggest issue I see there is in the case of running the same "simulator" in multiple instances (e.g. online games). Due to primary keys and uniqueness, when "thawing" flight state, it would be necessary for the flight to not exist as an instantiated, running flight. Otherwise you'd see data overwritten and the flights would effectively merge in weird ways.

Perhaps, to synthesize all of this into a single workable solution, you need to have the following patterns established:

  1. A flight is essentially a bucket for redux-style events that describe the global state of the flight. Each event consists of a numeric counter (or, if multiple event processors exist, a vector clock), the event payload, and optionally a delta of the state tree or the full state tree.
  2. These redux-style events are generated server-side only, and are not directly shared with clients or generated by clients. This doesn't mean that clients can't change server state, it only means that clients cannot create their own events and drop them directly into the server's state management system. They must go through an endpoint of some kind that filters the logic (authentication/authorization, etc.)
  3. When a redux-style event is triggered, it generates a new state in the store and makes that state available.
  4. It may make sense to have multiple stores (relay-style), where one store is responsible for the simulator, one is responsible for the global sensors state, etc. If this is the case, then the flight becomes a collection of stores, and each store has its own series of events. When serialized, each even stream needs to be stored in order relative to its own store.
  5. Serialization of the flight comes through storing the event stream associated with each store. If we feel that we can effectively store the flight data with the event, then each event could also include the new state associated with the event's application (the root state would be an empty map).
  6. Periodically, it may make sense to "compact" the event stream. This is easily achieved if we have a copy of the latest simulator state attached to each event after it has been processed - simply discard events older than a certain threshold. If we do not have the latest state, then we would need to capture the latest state (up to whatever threshold of latest events we want to keep), log that as a "special" event with the full state, and then discard anything before that state.
  7. To publish to clients, there are a few things that I can see working out. One would be that clients would have some sort of path selector through a store's tree, e.g. "flight.simulators[parent].reactor.heatIndex" or "flight.sensorContacts.*", and the store would search all of these subscriptions for the latest data. Another approach would be similar to Meteor's pub/sub, where a client would subscribe to a channel, and that channel would have a set of designated selectors that it would watch for in the tree with changes (this is why having the delta between events in the stream would be super helpful, since it simplifies identifying what's changed and which subscriptions need updating). Another approach would be to throw all of this out and stick to simply publishing on a given document's channel like you're already doing, however you may lose out on a lot of power, flexibility, and decoupling if you don't explore this road first.
  8. It might make sense to have events "roll up" into more localized stores, so that systems of sufficient complexity have their own stores, such as a store for the simulator, a store for sensors contacts, a store for the overall flight (if that's even needed?), and then when an entity from one store interacts with another (e.g. a torpedo is fired by the ship, creating an event in the sensors contacts store, or one ship shoots another ship causing damage), there is some mechanism for one entity to generate events in any given store, according to game logic.

This is a bit of a brain dump, and there's a lot going on here, so to simplify, the following may be a tenable way forward:

Server side state management

  1. Flights are buckets of stores, and stores are the stream of events in a simulation. There should probably be a store for each simulator, a store for the flight itself (maybe?), a store for sensor contacts, and a store for anything else that would need to have its own internal namespace for events, either for performance or organizational reasons.
  2. When a flight template is "cloned", it takes a set of template events and drops them into the stores to generate state. These template events would have "magic" keywords in them to generate new ID's, where needed, in order to avoid global state conflict. This may not be necessary, if uniqueness is ensured at the flight level, so if a flight is uniquely keyed then everything else can rely on that uniqueness.
    • Perhaps this means that there are events that mutate "state" and then events that mutate OTP structure - in other words, a flight template could say "there are 4 simulators in this simulation, and a sensors arena, each with their own store. Simulator A has this set of systems..." etc. As the events are processed, it either mutates state or it mutates the genserver structure to build up/tear down whatever scaffolding is needed
    • This is making my Elixir metaprogramming spidey sense tingle a little bit. I don't know enough about it to say for certain, but it feels like metaprogramming on some level.
  3. Events would be dispatched to the store, which consists of an Agent for storing the series of events, and a GenServer for processing the series of events. Figuring out how to capture all of the event reducers (a la Redux's combineReducers) would be an important part of this. Otherwise, it's actually conceptually quite simple, I think.
  4. Serialization would consist of capturing the current state (for brevity's sake) and/or the stream of events. I'm of the opinion that the stream of events should be serialized to a database in the long-term, so that it can be used for advanced flight analytics.

Client-side state management

A naive implementation could be that the stream of events for a given store would stream through to the client and be played directly into Redux. Client-side mutations could be optimistic: When a client side event is dispatched, it is applied tentatively (assuming success), the event is sent to the server, the server approves or denies the event, and the true result based on server-side computation is then pushed back to the client. This is very similar to Meteor's approach. The downside is figuring out how to not push all the data to all the clients - there needs to be a subscription mechanism of some kind. Apollo should be trying to solve this problem in some way, but so far it's not fast enough based on your past experience.

Another approach would be to declare specific paths in the data structure of each store to watch for changes, and then react when those changes occur.

This is admittedly the part that is toughest for me to figure out at the moment, and will likely take some further thought.

Entity Component System

Something that would flip all of this around quite a bit is if we were to look at applying principles from https://en.wikipedia.org/wiki/Entity_component_system - Essentially everything is an "entity" in the simulation, and each entity can have a "component" attached to it. A "system" is a loop that scoops up each component during each tick of the game cycle, makes adjustments based on current input states, and then sets those values as a result. The advantages to this approach would be that it's already successful as a strategy in other games. The disadvantage is that we've never done it before. It would probably throw all this other stuff out the window, and I'm not advocating for it, but it's worth looking at to see how others are solving this problem. It would simplify a lot of how the data is managed. Note that each entity would not be a process, but each "system" would likely be an elixir process. I'm not sure how subscribing to a given entity would work, but it could work out alright.

Latency compensation

One thing that would make a lot of this better would be some kind of latency compensation. At its most basic form, I would expect two pieces - one would be "key frames" that would define the current state at a given moment in snapshots, to enforce client integrity, and another would be optimistically assuming certain conditions in the simulation. In other words, when a sensors contact is dragged to a new location at a given speed, only one event is emitted: "The contact is moving at this speed to this new place". The sever and the client would start animating the position of the contact based on this data, but the server would periodically send out "the client is at x,y,z location" so that there is still an authoritative answer about positioning. This periodic update would not have to be at 60 fps, though, so you get efficient networking coupled with realtime simulation.

Timeline System

There should be configuration options for the following actions:

  • Step Description (describing what is going on during the mission, etc.)
  • Send long range message
  • Break/Repair system
  • Set sensors scan mission presets
  • Send processed data to sensors/ Probe network
  • Add a short range comm
  • Remove a short range comm
  • Print a document
  • Change the view screen
  • Set sensor army contacts

Maybe more...?

Mission Management System

Missions are objects that have configurations for the simulators which run the mission - not specific simulators, but instances of a simulator which are configured with an actual simulator when the mission is instantiated as a flight. These mission simulator objects would be very sparse - all they have is a timeline of actions which is applied to the simulator when the mission is instantiated. These actions would configure and set the simulator up in nearly every way.

This part is a little bit hazy - how much of a simulator is inherit in the simulator itself and how much is defined by the mission which is being run? On one end of the spectrum, the simulator could be defined entirely by the mission, including the decks, rooms, and personnel on the ship. On the other, the simulator is very static with definite decks, rooms, and personnel, etc which remain the same regardless of which mission is being run.

Missions are created simply by creating a timeline. Timelines are created by manipulating elements on Core (I suppose you could do the same with stations too). All actions performed during a given time are placed into a timeline cue. The flight director then commits that cue. This cue is the initial state of the mission. The process is repeated for every part of the timeline. Note that things which the crew must do should be excluded from this. For example, activating the engines should not be part of the timeline.

If the mission defines the simulator, then part of the initial cue of the timeline could be creating all of the parts of the simulator, such as the systems which it has, etc. This would mean that there would need to be a method for adding and removing systems from the simulator. This could include adding and removing cards from stations. Example: A card for controlling the Phase Cloaking Device during the Parameter mission - the system and card don't exist till the device is on the ship.

Accounts system

We need some kind of system for accounts. This will be used to differentiate standard users from admin users and can also be used to keep track of user data across simulator experiences. This is useful for tracking volunteer and flight director hours, student points, the missions which FDs and Students are running, etc. Maybe it could eventually be integrated with a complete online point tracking system.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.