God’s portal: the subversion of VR

Tags

, , , , , , , , , , , ,

Arkwood is wicked. But sad. He said, ‘I have no kingdom. I have no subjects to rule over.’

‘Don’t worry,’ I replied, patting him on the hunchback, ‘there are lots of people roaming around in virtual reality these days. Why not inflict your tyranny upon them?’

But how can we play God to the eyes and ears of those folks who are wearing a VR headset? How can we watch their every move, and – just like a bolt of lightning from our Lord’s finger – abruptly change their environment and emotions? Easy. We simply need to build a portal. God’s portal.

React

We will use the React JavaScript library to render the web page that will be God’s portal. What we need is as way to view all the output of a virtual reality player’s activity. And also a way to send commands to that player’s virtual world:

import React, { Component } from 'react'
import axios from 'axios';

class App extends Component {

  state = {
    outputs: [],
    inputName: ''
  };

  componentDidMount() {
    setInterval(() => {

      // get outputs
      axios
      .get('http://localhost:50609/api/home/outputs')
      .then(response => {

        // create an array of outputs
        const newOutputs = response.data.map(l => {
          return {
            id: l.Id,
            message: l.Message
          };
        });

        // create and store a new state object
        const newState = { outputs: newOutputs };

        this.setState(newState);
      })
      .catch(error => console.log(error));

    }, 1000)
  }

  handleChange = event => {

    // create and store a new state object
    const newState = { inputName: event.target.value };

    this.setState(newState);
  }

  handleSubmit = event => {
    event.preventDefault();
    const name = this.state.inputName;

    // post input name
    axios.post('http://localhost:50609/api/home/input', { name })
      .then(response => {
        console.log(response);
        console.log(response.data);
      })
      .catch(error => console.log(error));
  }

  render() {
    return (
      <div>
        <div>
          <ul>
            {this.state.outputs.map(c => <li key={c.id}>{c.message}</li>)}
          </ul>
        </div>
        <div>
          <form onSubmit={this.handleSubmit}>
            <label>
              Input Name:
              <input type="text" name="name" onChange={this.handleChange} />
            </label>
            <button type="submit">Add</button>
          </form>
        </div>
      </div>
    );
  }
}

export default App;

Nice. Our App component uses axios to receive all the output from the player’s virtual world and store it in state, ready to render. It does this every second, so we can track the player ‘real-time’.

Our App can also send input to the player’s virtual world.

Here’s the no-frills web page that is God’s portal:

Excellent. We can watch the player enter virtual rooms and know how much virtual money the player has. We can also issue decrees such as “Kill Lights” (which will most unsettle our player when the virtual world suddenly goes dark).

Web API

Right now, God’s portal does shit (sorry God, pardon my French). What we need is a web API that can handle those axios calls from React. Here’s my ASP.NET Web API RESTful app:

public class HomeController : ApiController
{
    #region api methods

    [HttpGet]
    public IEnumerable<OutputModel> Outputs()
    {
        return BuildOutputs();
    }

    [HttpOptions]
    public void Input() { }

    [HttpPost]
    public void Input(InputModel inputModel)
    {
        System.IO.File.WriteAllText(FilePaths.Inputs, inputModel.Name);
    }

    #endregion

    #region private methods

    private IEnumerable<OutputModel> BuildOutputs()
    {
        var Outputs = new List<OutputModel>();

        var messages = System.IO.File.ReadLines(FilePaths.Outputs);

        var id = 1;
        foreach (var message in messages)
        {
            Outputs.Add(new OutputModel { Id = id, Message = message });
            id++;
        }

        return Outputs;
    }

    #endregion
}

Our C# code builds the output from the player’s virtual reality world, making it available to the web page that is God’s portal.

The code can also handle commands from God’s portal, such as “Kill Lights”, writing the command to an input file.

Virtual Reality

Okay, now it is getting interesting. We need to update the virtual world to write the player’s activity to an output file, as well as being able to read that “Kill Lights” decree issued from God’s portal:

class FileClient
{
private:
	string FilePathOutputs;
	string FilePathInputs;

public:

	FileClient(string filePathOutputs, string filePathInputs) :
		FilePathOutputs(filePathOutputs),
		FilePathInputs(filePathInputs)
	{
	}

	void WriteLine(string line) {
		
		ofstream file;
		file.open(FilePathOutputs, ios::out | ios::app);

		file << line << endl;

		file.close();
	}

	string ReadLine() {
		
		ifstream file;
		file.open(FilePathInputs);

		string data;
		getline(file, data);

		file.close();

		return data;
	}
};

I have cranked open my C++ Microsoft Visual Studio application (with OpenGL graphics library and the Oculus SDK for Windows) and added some code to write messages to the output file and read the “Kill Lights” name from the input file.

Now when the player enters a room, we can write to the output file:

fileClient = new FileClient(FilePathOutputs, FilePathInputs);

fileClient->WriteLine("The player has entered Room 1 of Barru");
fileClient->WriteLine("The player's number of coins are: " + std::to_string(possessionClient->GetNumberOfCoins()));

Great. Within a second, God’s portal will display a message that the player has entered the room. And also a message of how much virtual money the player has.

We can also read the latest command issued from God’s portal:

if (fileClient->ReadLine() == "Kill Lights") {
	lighting->UsePointLighting = false;
}

If God’s portal has decreed there to be no light, then the player’s virtual world goes from heavenly illumination:

To the black pits of hell:

The player is left in terror and confusion.

Summary

I asked Arkwood what he thought of God’s portal.

‘It’s okay,’ he replied, unenthusiastic. ‘But I need to rule all my subjects with an iron fist. Can you program God’s portal to work across multiple virtual worlds?’

I don’t see why not. And I could even put God’s portal on the world-wide web, so anyone could watch a player’s virtual activity and issue commands.

Arkwood’s eyes widened in horror.

‘No!’ he snapped, ‘The web page is just for me! Only me, you hear!’

He frowned, then said, ‘Actually, I command you to rename the web page as Arkwood’s portal. For I am now God!’ Arkwood’s bottom lip pouted like a dictator.

I reminded him that we were still firmly in the real world, where he held no power. To prove so, I picked up the TV set and dropped it over his head, before stabbing him in the groin with a fork.

The subversion of VR would have to wait.

P.S. Alligator helped with the React code for a axois post.

Advertisements