Add full example of simple flask website that hosts the web client

This commit is contained in:
UnknownShadow200 2020-04-02 23:00:37 +11:00 committed by GitHub
parent 41666d939b
commit 04cc22f3dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

238
misc/hosting-flask.md Normal file
View File

@ -0,0 +1,238 @@
The website will be structured like so:
```
websrv.py
templates/tmpl.html
templates/tmpl_lite.html
templates/play.html
static/classisphere.js
static/default.zip
static/style.css
static/jquery.js
```
## Content
#### websrv.py
```Python
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/")
def index():
return '<html><h1>Welcome!</h1>Click <a href="/play">here</a> to play</h1></html>'
@app.route("/play")
@app.route("/play/")
def play():
user = request.args.get('user') or 'Singleplayer'
ver = request.args.get('mppass') or ''
addr = request.args.get('ip')
port = request.args.get('port') or '25565'
if addr:
args = "['%s', '%s', '%s', '%s']" % (user, ver, addr, port)
else:
args = "['%s']" % user
return render_template('play.html', game_args=args)
if __name__ == "__main__":
app.run()
```
#### templates/tmpl.html
```HTML
<html>
<head>
<meta name="viewport" content="width=device-width">
<link href="/static/style.css" rel="stylesheet">
<script src="/static/jquery.js"></script>
</head>
<body>
<div id="header">
<div class="row">
<a href="/"><h1 class="columns">Home</h1></a>
<a href="/play"><h1 class="columns">Play</h1></a>
</div>
</div>
<div id="body">
{% block main %} {% endblock %}
</div>
</body>
</html>
```
#### templates/tmpl_lite.html
```HTML
<html>
<head>
<meta name="viewport" content="width=device-width">
<link href="/static/style.css" rel="stylesheet">
<script src="/static/jquery.js"></script>
</head>
<body>
<div id="body">
{% block main %} {% endblock %}
</div>
</body>
</html>
```
#### templates/play.html
```HTML
{% set mobile_mode = request.user_agent.platform in ('android', 'iphone', 'ipad') %}
{% if mobile_mode %}
{% extends 'tmpl_lite.html' %}
{% else %}
{% extends 'tmpl.html' %}
{% endif %}
{% block main %}
<style>
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
#GameCanvas { display:block; box-sizing:border-box; border-width:0px !important; padding:0 !important; margin:0 auto; background-color: black; width:100%; height:auto; }
</style>
<div class="sec">
<div class="row">
<canvas id="GameCanvas" oncontextmenu="event.preventDefault()" tabindex=-1 width="1000" height="562"></canvas>
<span id="logmsg" style="font-size:18px;color:#F67;"></span>
</div>
</div>
<script type='text/javascript'>
// need to load IndexedDB before running the game
function preloadIndexedDB() {
addRunDependency('load-idb');
FS.mkdir('/classicube');
FS.mount(IDBFS, {}, '/classicube');
FS.syncfs(true, function(err) {
if (err) window.cc_idbErr = err;
removeRunDependency('load-idb');
})
}
function resizeGameCanvas() {
var cc_canv = $('canvas#GameCanvas');
var dpi = window.devicePixelRatio;
var aspect_ratio = 16/9;
var viewport_w = cc_canv.parent().width();
var viewport_h = viewport_w / aspect_ratio;
var canv_w = Math.round(viewport_w);
var canv_h = Math.round(viewport_h);
if (canv_h % 2) { canv_h = canv_h - 1; }
if (canv_w % 2) { canv_w = canv_w - 1; }
{% if mobile_mode %}
canv_h = Math.min(canv_h, window.outerHeight);
{% endif %}
cc_canv[0].width = canv_w * dpi;
cc_canv[0].height = canv_h * dpi;
}
var Module = {
preRun: [ preloadIndexedDB, resizeGameCanvas ],
postRun: [],
arguments: {{game_args|safe}},
print: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
},
printErr: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() { return getElementById('GameCanvas'); })(),
setStatus: function(text) {
console.log(text);
document.getElementById('logmsg').innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module.setStatus('Downloading...');
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
</script>
<script async type="text/javascript" src="/static/classisphere.js"></script>
{% if mobile_mode %}
<style>
#body {min-height: 0px;}
.sec {padding: 0px;}
.row {padding: 0px;}
</style>
{% else %}
{% endif %}
{% endblock %}
```
#### static/classisphere.js
Download `classicube.s3.amazonaws.com/client/latest/ClassiCube.js` for this
#### static/default.zip
Download `classicube.net/static/default.zip` for this
#### static/style.css
```CSS
.row:before, .row:after {
content: " ";
display: table;
}
.row:after { clear: both; }
body { margin: 0; }
.row {
margin-left: auto;
margin-right: auto;
max-width: 62.5em;
}
a { text-decoration: none; }
.columns {
position: relative;
float: left;
}
.sec {
background:#f1ecfa;
padding:10px 0 5px;
}
#header { background-color:#5870b0; }
#header h1 {
color:#fff;
margin:0px 10px 0px 10px;
}
```
#### static/jquery.js
Download some version of jQuery for this. Version 2.1.1 is known to work.
## Results
* If you don't want the game to resize to fit different resolutions, remove the `resizeGameCanvas` code.
* tmpl_lite.html and
## Results
After all this setup, you need to install the flask package for python.
Then in command prompt/terminal enter: `python websrv.py`
Then navigate to `http://127.0.0.1:5000/play` in your web browser. If all goes well you should see the web client start in singleplayer.
To start in multiplayer instead, navigate to `http://127.0.0.1:5000/play?user=test&ip=127.0.0.1&port=25565`