Initial commit
This commit is contained in:
commit
bb8162e4c1
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.dae filter=lfs diff=lfs merge=lfs -text
|
||||
*.blend filter=lfs diff=lfs merge=lfs -text
|
||||
*.gltf filter=lfs diff=lfs merge=lfs -text
|
||||
*.glb filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
1751
Cargo.lock
generated
Normal file
1751
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "dominion"
|
||||
version = "0.1.0"
|
||||
authors = ["Markus Wagner <murk@ferrum-et-magica.de>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-std = { version = "1.8.0", features = ["attributes"] }
|
||||
html-escape = "0.2.6"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.60"
|
||||
tide = "0.15.0"
|
||||
tide-websockets = "0.1.0"
|
||||
uuid = { version = "0.8.1", features = ["v4", "serde"] }
|
238
src/main.rs
Normal file
238
src/main.rs
Normal file
@ -0,0 +1,238 @@
|
||||
extern crate html_escape;
|
||||
|
||||
use async_std::{
|
||||
prelude::*,
|
||||
sync::RwLock
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc}
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tide::{Body, Redirect, Request, Response};
|
||||
use tide_websockets::{Message, WebSocket, WebSocketConnection};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct CreateGameMessage {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GameStateMessage {
|
||||
id: String,
|
||||
state: GameState,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GameSetupMessage {
|
||||
id: String,
|
||||
setup: GameSetup,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
enum ClientMessage {
|
||||
Chat {
|
||||
message: String,
|
||||
},
|
||||
StartGame,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
enum ServerMessage {
|
||||
Chat {
|
||||
sender: String,
|
||||
message: String,
|
||||
},
|
||||
PlayerJoined {
|
||||
player: String,
|
||||
},
|
||||
}
|
||||
|
||||
struct Player {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Serialize)]
|
||||
enum GameState {
|
||||
Setup,
|
||||
InProgress,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize)]
|
||||
struct GameSetup {
|
||||
deck: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for GameSetup {
|
||||
fn default() -> GameSetup {
|
||||
GameSetup {
|
||||
deck: vec!["Copper".into(), "Copper".into(), "Copper".into(), "Copper".into(), "Copper".into(),
|
||||
"Copper".into(), "Copper".into(), "Estate".into(), "Estate".into(), "Estate".into()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Game {
|
||||
players: Vec<Player>,
|
||||
state: GameState,
|
||||
setup: GameSetup,
|
||||
connections: HashMap<Uuid, WebSocketConnection>,
|
||||
}
|
||||
|
||||
|
||||
impl Game {
|
||||
fn new(player: Player) -> Self {
|
||||
Self {
|
||||
players: vec![player],
|
||||
state: GameState::Setup,
|
||||
setup: GameSetup::default(),
|
||||
connections: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct State {
|
||||
games: Arc<RwLock<HashMap<Uuid, Game>>>,
|
||||
}
|
||||
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
tide::log::with_level(tide::log::LevelFilter::Debug);
|
||||
|
||||
let mut app = tide::with_state(State::default());
|
||||
|
||||
app.with(tide::sessions::SessionMiddleware::new(
|
||||
tide::sessions::MemoryStore::new(),
|
||||
"1234567890abcdef1234567890abcdef".as_bytes(),
|
||||
));
|
||||
|
||||
app.at("/").get(|_| async { Ok(Body::from_file("static/index.html").await?) });
|
||||
app.at("/static").serve_dir("static/")?;
|
||||
|
||||
app.at("/game").post(|mut req: Request<State>| async move {
|
||||
let msg: CreateGameMessage = req.body_form().await?;
|
||||
let session = req.session_mut();
|
||||
|
||||
session.insert("player_name", msg.name.clone()).unwrap();
|
||||
|
||||
let id = Uuid::new_v4();
|
||||
let mut games = req.state().games.write().await;
|
||||
let player = Player { name: msg.name };
|
||||
|
||||
games.insert(id, Game::new(player));
|
||||
|
||||
let url = format!("/game/{}", id.to_simple().to_string());
|
||||
let res: tide::Result = Ok(Redirect::new(url).into());
|
||||
res
|
||||
});
|
||||
|
||||
app.at("/game/:id").get(|req: Request<State>| async move {
|
||||
let games = req.state().games.read().await;
|
||||
let id = req.param("id")?;
|
||||
let game_id = Uuid::parse_str(&id).unwrap();
|
||||
|
||||
match games.get(&game_id) {
|
||||
None => Ok(Response::new(404)),
|
||||
Some(_) => {
|
||||
let mut res = Response::new(200);
|
||||
res.set_body(Body::from_file("static/game.html").await?);
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.at("/game/:id/ws")
|
||||
.get(WebSocket::new(|req: Request<State>, mut stream| async move {
|
||||
let id = req.param("id")?;
|
||||
let game_id = Uuid::parse_str(&id).unwrap();
|
||||
let mut games = req.state().games.write().await;
|
||||
let game = games.get_mut(&game_id).unwrap();
|
||||
let session = req.session();
|
||||
|
||||
let client_id = Uuid::new_v4();
|
||||
game.connections.insert(client_id, stream.clone());
|
||||
|
||||
//Ensure the write locks are freed, possibly better to move to a function
|
||||
//with implicit drop?
|
||||
drop(game);
|
||||
drop(games);
|
||||
|
||||
let games = req.state().games.read().await;
|
||||
let game = games.get(&game_id).unwrap();
|
||||
|
||||
let msg = GameStateMessage {
|
||||
id: "state".into(),
|
||||
state: game.state,
|
||||
};
|
||||
|
||||
stream.send_json(&msg).await?;
|
||||
|
||||
let msg = GameSetupMessage {
|
||||
id: "setup".into(),
|
||||
setup: game.setup.clone(),
|
||||
};
|
||||
|
||||
stream.send_json(&msg).await?;
|
||||
|
||||
let player: String = session.get("player_name").unwrap_or("SOMEONE".into());
|
||||
let sm = ServerMessage::PlayerJoined {
|
||||
player: html_escape::encode_text(&player).into(),
|
||||
};
|
||||
|
||||
for (_, con) in game.connections.iter() {
|
||||
con.send_json(&sm).await?;
|
||||
}
|
||||
|
||||
drop(game); drop(games);
|
||||
|
||||
while let Some(Ok(Message::Text(input))) = stream.next().await {
|
||||
let msg: ClientMessage = serde_json::from_str(&input)?;
|
||||
|
||||
match msg {
|
||||
ClientMessage::Chat { message } => {
|
||||
let sender: String = session.get("player_name").unwrap_or("SOMEONE".into());
|
||||
let sm = ServerMessage::Chat {
|
||||
sender: html_escape::encode_text(&sender).into(),
|
||||
message: html_escape::encode_text(&message).into(),
|
||||
};
|
||||
|
||||
let games = req.state().games.read().await;
|
||||
let game = games.get(&game_id).unwrap();
|
||||
|
||||
for (_, con) in game.connections.iter() {
|
||||
con.send_json(&sm).await?;
|
||||
}
|
||||
}
|
||||
|
||||
ClientMessage::StartGame => {
|
||||
let mut games = req.state().games.write().await;
|
||||
let game = games.get_mut(&game_id).unwrap();
|
||||
|
||||
match game.state {
|
||||
GameState::Setup => {
|
||||
game.state = GameState::InProgress;
|
||||
}
|
||||
_ => {} //Ignore, if game not in setup state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut games = req.state().games.write().await;
|
||||
let game = games.get_mut(&game_id).unwrap();
|
||||
|
||||
game.connections.remove(&client_id);
|
||||
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
app.listen("0.0.0.0:5000").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
523
static/game.html
Normal file
523
static/game.html
Normal file
@ -0,0 +1,523 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>DnD</title>
|
||||
<link rel="stylesheet" href="/static/main.css">
|
||||
<style type="text/css">
|
||||
.pile-counter {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
right: 5px;
|
||||
color: wheat;
|
||||
background-color: darkred;
|
||||
border-radius: 5px;
|
||||
height: 24px;
|
||||
width: 35px;
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
font-family: sans-serif;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.player-area {
|
||||
display: grid;
|
||||
grid-template-columns: 100px auto 100px;
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
height: 145px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
width: 90px;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
.player-hand {
|
||||
border: 1px solid red;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.chat-window {
|
||||
border: 1px solid black;
|
||||
width: 300px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.supply-area {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
padding-right: 300px;
|
||||
background-color: dimgray;
|
||||
box-sizing: border-box;
|
||||
margin: 5px 0;
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
}
|
||||
|
||||
.supply-area h3 {
|
||||
position: relative;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
transform-origin: 0 0;
|
||||
transform: rotate(90deg);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.draw-pile {
|
||||
width: 90px;
|
||||
position: relative;
|
||||
height: 145px;
|
||||
}
|
||||
|
||||
.opponent-hand {
|
||||
width: 90px;
|
||||
position: relative;
|
||||
height: 145px;
|
||||
}
|
||||
|
||||
.setup-screen {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.discard-pile {
|
||||
width: 90px;
|
||||
border: 1px dotted green;
|
||||
height: 145px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.inplay-area {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
transition: height 0.4s ease;
|
||||
background-color: dimgray;
|
||||
box-sizing: border-box;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.inplay-area.inactive {
|
||||
height: 0;
|
||||
transition: height 0.4s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.turn-status {
|
||||
line-height: 24px;
|
||||
height: 24px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
background-color: rgb(255 255 255 / 34%);
|
||||
border-radius: 0 0 20px 20px;
|
||||
padding: 0 20px 0;
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 1;
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
.inplay-area.inactive .turn-status {
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
.opponent-area {
|
||||
height: 180px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.opponent-status {
|
||||
grid-template-rows: 30px auto;
|
||||
grid-template-columns: auto auto auto;
|
||||
box-sizing: border-box;
|
||||
margin: 0 5px;
|
||||
border: 1px solid saddlebrown;
|
||||
display: grid;
|
||||
grid-gap: 2px;
|
||||
}
|
||||
|
||||
.opponent-status.active {
|
||||
box-shadow: 0 0 10px red;
|
||||
}
|
||||
|
||||
.opponent-status .name {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: span 3;
|
||||
text-align: center;
|
||||
grid-row-start: 1;
|
||||
grid-row-end: 1;
|
||||
}
|
||||
|
||||
.opponent-status .discard-pile {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 1;
|
||||
grid-row-start: 2;
|
||||
grid-row-end: 2;
|
||||
}
|
||||
|
||||
.opponent-status .draw-pile {
|
||||
grid-column-start: 2;
|
||||
grid-column-end: 2;
|
||||
grid-row-start: 2;
|
||||
grid-row-end: 2;
|
||||
}
|
||||
|
||||
.opponent-status .opponent-hand {
|
||||
grid-column-start: 3;
|
||||
grid-column-end: 3;
|
||||
grid-row-start: 2;
|
||||
grid-row-end: 2;
|
||||
}
|
||||
|
||||
.game-screen {
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
<script src="/static/mithril.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="game"></div>
|
||||
<script>
|
||||
function Chat(initialVnode) {
|
||||
var keyup = function(e) {
|
||||
if (e.key == "Enter" && e.srcElement.value.length > 0) {
|
||||
let msg = { type: "Chat", message: e.srcElement.value };
|
||||
initialVnode.attrs.socket.send(JSON.stringify(msg));
|
||||
e.srcElement.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".chat-window",
|
||||
m("h4", "Players"),
|
||||
m("ul", m("li", "Markus (you)")),
|
||||
m("h4", "Messages"),
|
||||
m("ul", {id: "chat"}),
|
||||
m("input", {
|
||||
id: "chat_input",
|
||||
placeholder: "Type to chat...",
|
||||
onkeyup: keyup
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SupplyPile(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".card",
|
||||
m("img", {class: "card", src: "/static/images/cards/" + vnode.attrs.name.toLowerCase() + ".jpg"}),
|
||||
m("span", {class: "pile-counter" }, vnode.attrs.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function SupplyArea(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".supply-area",
|
||||
m("h3", "Supply"),
|
||||
vnode.attrs.supply.map(function(pile) {
|
||||
return m(SupplyPile, pile)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function DiscardPile(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".discard-pile", "Discard Pile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DrawPile(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".draw-pile",
|
||||
m("img", {class: "card", src: "/static/images/cards/Card_back.jpg"}),
|
||||
m("span", {class: "pile-counter" }, vnode.attrs.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function PlayerHand(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".player-hand", "Player Hand",
|
||||
vnode.attrs.hand.map(function(card) {
|
||||
return m("img", {class: "card", src: "/static/images/cards/" + card.toLowerCase() + ".jpg"})
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function OpponentHand(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".opponent-hand",
|
||||
m("img", {class: "card", src: "/static/images/cards/Card_back.jpg"}),
|
||||
m("span", {class: "pile-counter" }, vnode.attrs.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function InPlayArea(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
var active = vnode.attrs.active ? "" : "inactive";
|
||||
return m(".inplay-area", {class: active},
|
||||
"Player play area",
|
||||
m(".turn-status",
|
||||
"Actions: " + vnode.attrs.actions + " | Buys: " + vnode.attrs.buys + " | ",
|
||||
m("img", {src: "/static/images/64px-Coin.png", style: "height: 16px;"}),
|
||||
": " + vnode.attrs.coin
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function PlayerArea(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".player-area",
|
||||
m(DrawPile, {count: vnode.attrs.player_drawpile_count}),
|
||||
m(PlayerHand, vnode.attrs.player),
|
||||
m(DiscardPile)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function OpponentStatus(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
var active = vnode.attrs.active ? "active" : "";
|
||||
return m(".opponent-status", {class: active },
|
||||
m(".name", vnode.attrs.name),
|
||||
m(DiscardPile),
|
||||
m(DrawPile, {count: vnode.attrs.draw_pile_count}),
|
||||
m(OpponentHand, {count: vnode.attrs.hand_count })
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function OpponentArea(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".opponent-area",
|
||||
vnode.attrs.opponents.map(function(o) {
|
||||
return m(OpponentStatus, o)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function GameScreen(initialVnode) {
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".game-screen",
|
||||
m(OpponentArea, vnode.attrs),
|
||||
m(InPlayArea, vnode.attrs.opponent_turn_state),
|
||||
m(SupplyArea, vnode.attrs),
|
||||
m(InPlayArea, vnode.attrs.player_turn_state),
|
||||
m(PlayerArea, vnode.attrs)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function SetupScreen(initialVnode) {
|
||||
var start_click = function(e) {
|
||||
console.log("start_click", e);
|
||||
|
||||
let msg = { id: "start_game" };
|
||||
initialVnode.attrs.socket.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return m(".setup-screen",
|
||||
m("h3", "Setup"),
|
||||
m("h4", "Basic cards"),
|
||||
m(".basic-cards",
|
||||
vnode.attrs.basic_cards.map(function(card) {
|
||||
return m("img", {class: "card", src: "/static/images/cards/" + card.toLowerCase() + ".jpg"})
|
||||
})
|
||||
),
|
||||
m("h4", "Kingdom Cards"),
|
||||
m(".kingdom-cards",
|
||||
vnode.attrs.kingdom_cards.map(function(card) {
|
||||
return m("img", {class: "card", src: "/static/images/cards/" + card.toLowerCase() + ".jpg"})
|
||||
})
|
||||
),
|
||||
m("h4", "Starting Deck"),
|
||||
m(".start-deck",
|
||||
vnode.attrs.starting_deck.map(function(card) {
|
||||
return m("img", {class: "card", src: "/static/images/cards/" + card.toLowerCase() + ".jpg"})
|
||||
})
|
||||
),
|
||||
m("button", {onclick: start_click}, "Start Game")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var game_state;
|
||||
|
||||
function App(initialVnode) {
|
||||
if (document.location.protocol == "https:") {
|
||||
url = document.location.href.replace("https://", "wss://") + "/ws";
|
||||
} else {
|
||||
url = document.location.href.replace("http://", "ws://") + "/ws";
|
||||
}
|
||||
const webSocket = new WebSocket(url);
|
||||
|
||||
var setup_state = {
|
||||
starting_deck: [],
|
||||
basic_cards: ["Copper", "Silver", "Gold", "Estate", "Duchery", "Province", "Curse"],
|
||||
kingdom_cards: ["Cellar", "Moat", "Village", "Merchant", "Workshop", "Smithy", "Remodel", "Militia", "Market", "Mine"],
|
||||
socket: webSocket
|
||||
}
|
||||
|
||||
var handle_setup = function(data) {
|
||||
setup_state.starting_deck = data.deck;
|
||||
}
|
||||
|
||||
game_state = {
|
||||
supply: [
|
||||
{ name: "Copper", count: 46 },
|
||||
{ name: "Silver", count: 38 },
|
||||
{ name: "Gold", count: 30 },
|
||||
{ name: "Estate", count: 8 },
|
||||
{ name: "Duchery", count: 8 },
|
||||
{ name: "Province", count: 8 },
|
||||
{ name: "Curse", count: 10 },
|
||||
|
||||
{ name: "Cellar", count: 10},
|
||||
{ name: "Moat", count: 10},
|
||||
{ name: "Village", count: 10},
|
||||
{ name: "Merchant", count: 10},
|
||||
{ name: "Workshop", count: 10},
|
||||
|
||||
{ name: "Smithy", count: 10},
|
||||
{ name: "Remodel", count: 10},
|
||||
{ name: "Militia", count: 10},
|
||||
{ name: "Market", count: 10},
|
||||
{ name: "Mine", count: 10}
|
||||
],
|
||||
opponent_turn_state: {
|
||||
actions: 1,
|
||||
buys: 1,
|
||||
coin: 0,
|
||||
active: false
|
||||
},
|
||||
player_turn_state: {
|
||||
actions: 1,
|
||||
buys: 1,
|
||||
coin: 0,
|
||||
active: true
|
||||
},
|
||||
player_drawpile_count: 10,
|
||||
player: {
|
||||
hand: []
|
||||
},
|
||||
opponents: [
|
||||
{
|
||||
name: "Alice",
|
||||
draw_pile_count: 10,
|
||||
hand_count: 5,
|
||||
active: true
|
||||
},
|
||||
{
|
||||
name: "Bob",
|
||||
draw_pile_count: 8,
|
||||
hand_count: 5
|
||||
},
|
||||
{
|
||||
name: "Mallory",
|
||||
draw_pile_count: 10,
|
||||
hand_count: 3
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
var chat_state = {
|
||||
socket: webSocket
|
||||
}
|
||||
|
||||
webSocket.onopen = function(event) {
|
||||
console.log("ws open");
|
||||
//webSocket.send("HALLO");
|
||||
};
|
||||
|
||||
webSocket.onmessage = function(event) {
|
||||
var msg = JSON.parse(event.data);
|
||||
|
||||
if (msg.type == "Chat") {
|
||||
let chatDiv = document.getElementById("chat");
|
||||
let newmsg = document.createElement("li");
|
||||
newmsg.innerHTML = msg.sender + ": " + msg.message;
|
||||
chatDiv.append(newmsg);
|
||||
//newmsg.scrollIntoView();
|
||||
} else if (msg.type == "PlayerJoined") {
|
||||
let chatDiv = document.getElementById("chat");
|
||||
let newmsg = document.createElement("li");
|
||||
newmsg.innerHTML = msg.player + " joined the game.";
|
||||
chatDiv.append(newmsg);
|
||||
//newmsg.scrollIntoView();
|
||||
} else if (msg.id == "setup") {
|
||||
handle_setup(msg.setup);
|
||||
} else {
|
||||
console.log("event?");
|
||||
console.log(event.data);
|
||||
}
|
||||
|
||||
m.redraw();
|
||||
}
|
||||
|
||||
return {
|
||||
view: function(vnode) {
|
||||
return [
|
||||
m(SetupScreen, setup_state),
|
||||
m(GameScreen, game_state),
|
||||
m(Chat, chat_state)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.mount(document.getElementById("game"), App)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
static/images/64px-Coin.png
(Stored with Git LFS)
Normal file
BIN
static/images/64px-Coin.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/Card_back.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/Card_back.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/abandoned-mine.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/abandoned-mine.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/academy.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/academy.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/acting-troupe.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/acting-troupe.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/advance.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/advance.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/adventurer.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/adventurer.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/advisor.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/advisor.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/alchemist.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/alchemist.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/alms.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/alms.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/altar.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/altar.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/ambassador.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/ambassador.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/amulet.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/amulet.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/annex.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/annex.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/apothecary.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/apothecary.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/apprentice.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/apprentice.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/aqueduct.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/aqueduct.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/archive.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/archive.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/arena.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/arena.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/armory.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/armory.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/artificer.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/artificer.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/artisan.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/artisan.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/avanto.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/avanto.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bad-omens.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bad-omens.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bag-of-gold.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bag-of-gold.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/baker.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/baker.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/ball.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/ball.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/band-of-misfits.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/band-of-misfits.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bandit-camp.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bandit-camp.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bandit-fort.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bandit-fort.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bandit.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bandit.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bank.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bank.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/banquet.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/banquet.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bard.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bard.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/baron.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/baron.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/barracks.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/barracks.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/basilica.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/basilica.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bat.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bat.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/baths.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/baths.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/battlefield.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/battlefield.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bazaar.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bazaar.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/beggar.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/beggar.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bishop.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bishop.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/black-market.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/black-market.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/blessed-village.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/blessed-village.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bonfire.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bonfire.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/border-guard.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/border-guard.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/border-village.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/border-village.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/borrow.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/borrow.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bridge-troll.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bridge-troll.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bridge.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bridge.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bureaucrat.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bureaucrat.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/bustling-village.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/bustling-village.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/butcher.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/butcher.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cache.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cache.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/canal.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/canal.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/candlestick-maker.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/candlestick-maker.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/capital.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/capital.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/capitalism.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/capitalism.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/captain.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/captain.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/caravan-guard.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/caravan-guard.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/caravan.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/caravan.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cargo-ship.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cargo-ship.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cartographer.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cartographer.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/castles.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/castles.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/catacombs.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/catacombs.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/catapult.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/catapult.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cathedral.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cathedral.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cellar.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cellar.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cemetery.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cemetery.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/champion.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/champion.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/chancellor.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/chancellor.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/changeling.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/changeling.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/chapel.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/chapel.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/chariot-race.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/chariot-race.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/charm.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/charm.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/church.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/church.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/citadel.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/citadel.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/city-gate.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/city-gate.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/city-quarter.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/city-quarter.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/city.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/city.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/cobbler.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/cobbler.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/coin-of-the-realm.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/coin-of-the-realm.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/colonnade.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/colonnade.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/colony.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/colony.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/conclave.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/conclave.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/conquest.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/conquest.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/conspirator.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/conspirator.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/contraband.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/contraband.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/copper.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/copper.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/coppersmith.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/coppersmith.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/council-room.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/council-room.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/count.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/count.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
static/images/cards/counterfeit.jpg
(Stored with Git LFS)
Normal file
BIN
static/images/cards/counterfeit.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user