commit
172a480c92
15
.github/workflows/dev-image.yml
vendored
Normal file
15
.github/workflows/dev-image.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
name: Docker Images CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ dev ]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build the Unified Docker image
|
||||||
|
run: docker build . --file Dockerfile --tag albertoxamin/bang:dev
|
||||||
|
- name: Log into registry
|
||||||
|
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
|
||||||
|
- name: Push images
|
||||||
|
run: docker push albertoxamin/bang:dev
|
7
.github/workflows/docker-image.yml
vendored
7
.github/workflows/docker-image.yml
vendored
@ -9,12 +9,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Build the Unified Docker image
|
- name: Build the Unified Docker image
|
||||||
run: docker build . --file Dockerfile --tag albertoxamin/bang:latest
|
run: docker build . --file Dockerfile --tag albertoxamin/bang:latest
|
||||||
- name: Build the Backend Docker image
|
|
||||||
run: cd backend;docker build . --file Dockerfile --tag albertoxamin/bang-backend:latest
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Build the Frontend Docker image
|
|
||||||
run: cd frontend;docker build . --file Dockerfile --tag albertoxamin/bang-frontend:latest
|
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
|
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
|
||||||
- name: Push images
|
- name: Push images
|
||||||
run: docker push albertoxamin/bang:latest; docker push albertoxamin/bang-backend:latest; docker push albertoxamin/bang-frontend:latest
|
run: docker push albertoxamin/bang:latest
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -136,3 +136,5 @@ dmypy.json
|
|||||||
|
|
||||||
# Cython debug symbols
|
# Cython debug symbols
|
||||||
cython_debug/
|
cython_debug/
|
||||||
|
|
||||||
|
frontend/package-lock.json
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
|
import random
|
||||||
from typing import List
|
from typing import List
|
||||||
import eventlet
|
import eventlet
|
||||||
import socketio
|
import socketio
|
||||||
@ -17,7 +18,7 @@ games: List[Game] = []
|
|||||||
online_players = 0
|
online_players = 0
|
||||||
|
|
||||||
def advertise_lobbies():
|
def advertise_lobbies():
|
||||||
sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players)} for g in games if not g.started and len(g.players) < 7])
|
sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 7])
|
||||||
|
|
||||||
@sio.event
|
@sio.event
|
||||||
def connect(sid, environ):
|
def connect(sid, environ):
|
||||||
@ -62,11 +63,20 @@ def create_room(sid, room_name):
|
|||||||
advertise_lobbies()
|
advertise_lobbies()
|
||||||
|
|
||||||
@sio.event
|
@sio.event
|
||||||
def join_room(sid, room_name):
|
def private(sid):
|
||||||
|
g = sio.get_session(sid).game
|
||||||
|
g.set_private()
|
||||||
|
advertise_lobbies()
|
||||||
|
|
||||||
|
@sio.event
|
||||||
|
def join_room(sid, room):
|
||||||
|
room_name = room['name']
|
||||||
print(f'{sid} joined a room named {room_name}')
|
print(f'{sid} joined a room named {room_name}')
|
||||||
|
i = [g.name for g in games].index(room_name)
|
||||||
|
if games[i].password != '' and games[i].password != room['password'].upper():
|
||||||
|
return
|
||||||
sio.leave_room(sid, 'lobby')
|
sio.leave_room(sid, 'lobby')
|
||||||
sio.enter_room(sid, room_name)
|
sio.enter_room(sid, room_name)
|
||||||
i = [g.name for g in games].index(room_name)
|
|
||||||
while len([p for p in games[i].players if p.name == sio.get_session(sid).name]):
|
while len([p for p in games[i].players if p.name == sio.get_session(sid).name]):
|
||||||
sio.get_session(sid).name += '_1'
|
sio.get_session(sid).name += '_1'
|
||||||
games[i].add_player(sio.get_session(sid))
|
games[i].add_player(sio.get_session(sid))
|
||||||
|
@ -2,12 +2,8 @@
|
|||||||
from typing import List, Set, Dict, Tuple, Optional
|
from typing import List, Set, Dict, Tuple, Optional
|
||||||
import random
|
import random
|
||||||
import socketio
|
import socketio
|
||||||
import cards
|
|
||||||
from cards import Bang
|
|
||||||
import players
|
import players
|
||||||
from players import PendingAction, Player
|
|
||||||
import characters
|
import characters
|
||||||
from characters import all_characters
|
|
||||||
from deck import Deck
|
from deck import Deck
|
||||||
import roles
|
import roles
|
||||||
|
|
||||||
@ -23,6 +19,7 @@ class Game:
|
|||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
self.waiting_for = 0
|
self.waiting_for = 0
|
||||||
self.initial_players = 0
|
self.initial_players = 0
|
||||||
|
self.password = ''
|
||||||
|
|
||||||
def add_player(self, player: players.Player):
|
def add_player(self, player: players.Player):
|
||||||
if player in self.players or len(self.players) >= 7:
|
if player in self.players or len(self.players) >= 7:
|
||||||
@ -30,16 +27,24 @@ class Game:
|
|||||||
player.join_game(self)
|
player.join_game(self)
|
||||||
self.players.append(player)
|
self.players.append(player)
|
||||||
print(f'Added player {player.name} to game')
|
print(f'Added player {player.name} to game')
|
||||||
self.sio.emit('room', room=self.name, data={'name': self.name, 'started': self.started, 'players': [p.name for p in self.players]})
|
self.sio.emit('room', room=self.name, data={'name': self.name, 'started': self.started, 'players': [p.name for p in self.players], 'password': self.password})
|
||||||
self.sio.emit('chat_message', room=self.name, data=f'{player.name} è entrato nella lobby.')
|
self.sio.emit('chat_message', room=self.name, data=f'{player.name} è entrato nella lobby.')
|
||||||
|
|
||||||
|
def set_private(self):
|
||||||
|
if self.password == '':
|
||||||
|
self.password = ''.join(random.choice("AEIOUJKZT123456789") for x in range(6))
|
||||||
|
print(self.name, 'is now private pwd', self.password)
|
||||||
|
else:
|
||||||
|
self.password = ''
|
||||||
|
self.sio.emit('room', room=self.name, data={'name': self.name, 'started': self.started, 'players': [p.name for p in self.players], 'password': self.password})
|
||||||
|
|
||||||
def notify_character_selection(self):
|
def notify_character_selection(self):
|
||||||
self.readyCount += 1
|
self.readyCount += 1
|
||||||
if self.readyCount == len(self.players):
|
if self.readyCount == len(self.players):
|
||||||
self.distribute_roles()
|
self.distribute_roles()
|
||||||
|
|
||||||
def choose_characters(self):
|
def choose_characters(self):
|
||||||
char_cards = random.sample(all_characters(), len(self.players)*2)
|
char_cards = random.sample(characters.all_characters(), len(self.players)*2)
|
||||||
for i in range(len(self.players)):
|
for i in range(len(self.players)):
|
||||||
self.players[i].set_available_character(char_cards[i * 2 : i * 2 + 2])
|
self.players[i].set_available_character(char_cards[i * 2 : i * 2 + 2])
|
||||||
|
|
||||||
@ -80,7 +85,7 @@ class Game:
|
|||||||
self.players[i].notify_self()
|
self.players[i].notify_self()
|
||||||
self.play_turn()
|
self.play_turn()
|
||||||
|
|
||||||
def attack_others(self, attacker:Player):
|
def attack_others(self, attacker: players.Player):
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = players.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
self.waiting_for = 0
|
self.waiting_for = 0
|
||||||
@ -93,7 +98,7 @@ class Game:
|
|||||||
attacker.pending_action = players.PendingAction.PLAY
|
attacker.pending_action = players.PendingAction.PLAY
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
|
|
||||||
def indian_others(self, attacker:Player):
|
def indian_others(self, attacker: players.Player):
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = players.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
self.waiting_for = 0
|
self.waiting_for = 0
|
||||||
@ -106,14 +111,14 @@ class Game:
|
|||||||
attacker.pending_action = players.PendingAction.PLAY
|
attacker.pending_action = players.PendingAction.PLAY
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
|
|
||||||
def attack(self, attacker:Player, target_username:str):
|
def attack(self, attacker: players.Player, target_username:str):
|
||||||
if self.players[self.players_map[target_username]].get_banged(attacker=attacker, double=isinstance(attacker.character, characters.SlabTheKiller)):
|
if self.players[self.players_map[target_username]].get_banged(attacker=attacker, double=isinstance(attacker.character, characters.SlabTheKiller)):
|
||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
self.waiting_for = 1
|
self.waiting_for = 1
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = players.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
|
|
||||||
def duel(self, attacker:Player, target_username:str):
|
def duel(self, attacker: players.Player, target_username:str):
|
||||||
if self.players[self.players_map[target_username]].get_dueled(attacker=attacker):
|
if self.players[self.players_map[target_username]].get_dueled(attacker=attacker):
|
||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
self.waiting_for = 1
|
self.waiting_for = 1
|
||||||
@ -230,7 +235,7 @@ class Game:
|
|||||||
if died_in_his_turn:
|
if died_in_his_turn:
|
||||||
self.next_turn()
|
self.next_turn()
|
||||||
|
|
||||||
def get_visible_players(self, player:Player):
|
def get_visible_players(self, player: players.Player):
|
||||||
i = self.players.index(player)
|
i = self.players.index(player)
|
||||||
sight = player.get_sight()
|
sight = player.get_sight()
|
||||||
return [{
|
return [{
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
|
"pretty-checkbox-vue": "^1.1.9",
|
||||||
"socket.io-client": "^3.0.3",
|
"socket.io-client": "^3.0.3",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-socket.io": "^3.0.10"
|
"vue-socket.io": "^3.0.10"
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js" crossorigin="anonymous"></script>
|
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -109,7 +109,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
name: lobby.name,
|
name: lobby.name,
|
||||||
icon: "💥",
|
icon: "💥",
|
||||||
number: `${lobby.players}🤠`,
|
number: `${lobby.players}🤠 ${lobby.locked?'🔐':''}`,
|
||||||
is_equipment: true,
|
is_equipment: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -120,7 +120,8 @@ export default {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
joinLobby(lobby) {
|
joinLobby(lobby) {
|
||||||
this.$socket.emit('join_room', lobby.name)
|
let password = lobby.locked ? prompt("Room password:", "") : '';
|
||||||
|
this.$socket.emit('join_room', {name:lobby.name,password:password})
|
||||||
},
|
},
|
||||||
init() {
|
init() {
|
||||||
location.reload();
|
location.reload();
|
||||||
@ -134,6 +135,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@import '../node_modules/pretty-checkbox/dist/pretty-checkbox.css';
|
||||||
#app {
|
#app {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
<div style="flex-grow: 4;">
|
<div style="flex-grow: 4;">
|
||||||
<h2 v-if="!started">Lobby: {{ lobbyName }}</h2>
|
<h2 v-if="!started">Lobby: {{ lobbyName }}</h2>
|
||||||
<h3>Giocatori (tu sei {{username}})</h3>
|
<h3>Giocatori (tu sei {{username}})</h3>
|
||||||
|
<h3 v-if="!started && password !== ''">Password: {{ password }}</h3>
|
||||||
|
<div v-if="!started && isRoomOwner">
|
||||||
|
<PrettyCheck class="p-switch p-fill" v-model="privateRoom">Stanza Privata</PrettyCheck>
|
||||||
|
</div>
|
||||||
<div class="players-table">
|
<div class="players-table">
|
||||||
<Card v-if="startGameCard" :card="startGameCard" @click.native="startGame"/>
|
<Card v-if="startGameCard" :card="startGameCard" @click.native="startGame"/>
|
||||||
<!-- <div style="position: relative;width:260pt;height:400pt;"> -->
|
<!-- <div style="position: relative;width:260pt;height:400pt;"> -->
|
||||||
@ -37,6 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import PrettyCheck from 'pretty-checkbox-vue/check'
|
||||||
import Card from '@/components/Card.vue'
|
import Card from '@/components/Card.vue'
|
||||||
import Chooser from './Chooser.vue'
|
import Chooser from './Chooser.vue'
|
||||||
import Chat from './Chat.vue'
|
import Chat from './Chat.vue'
|
||||||
@ -53,6 +58,7 @@ export default {
|
|||||||
Player,
|
Player,
|
||||||
Deck,
|
Deck,
|
||||||
TinyHand,
|
TinyHand,
|
||||||
|
PrettyCheck,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
username: String
|
username: String
|
||||||
@ -69,11 +75,14 @@ export default {
|
|||||||
chooseCards: [],
|
chooseCards: [],
|
||||||
wantsToEndTurn: false,
|
wantsToEndTurn: false,
|
||||||
selectedInfo: null,
|
selectedInfo: null,
|
||||||
|
privateRoom: false,
|
||||||
|
password: '',
|
||||||
}),
|
}),
|
||||||
sockets: {
|
sockets: {
|
||||||
room(data) {
|
room(data) {
|
||||||
this.lobbyName = data.name
|
this.lobbyName = data.name
|
||||||
this.started = data.started
|
this.started = data.started
|
||||||
|
this.password = data.password
|
||||||
this.players = data.players.map(x => {
|
this.players = data.players.map(x => {
|
||||||
return {
|
return {
|
||||||
name: x,
|
name: x,
|
||||||
@ -98,8 +107,11 @@ export default {
|
|||||||
// },
|
// },
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isRoomOwner() {
|
||||||
|
return this.players[0].name == this.username
|
||||||
|
},
|
||||||
startGameCard() {
|
startGameCard() {
|
||||||
if (!this.started && this.players.length > 2 && this.players[0].name == this.username) {
|
if (!this.started && this.players.length > 2 && this.isRoomOwner) {
|
||||||
return {
|
return {
|
||||||
name: 'Start',
|
name: 'Start',
|
||||||
icon: '▶️',
|
icon: '▶️',
|
||||||
@ -179,6 +191,11 @@ export default {
|
|||||||
this.$socket.emit('draw', name)
|
this.$socket.emit('draw', name)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
privateRoom() {
|
||||||
|
this.$socket.emit('private')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@ Vue.use(new VueSocketIO({
|
|||||||
connection: Vue.config.devtools ? 'http://localhost:5001' : window.location.origin,
|
connection: Vue.config.devtools ? 'http://localhost:5001' : window.location.origin,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
import PrettyCheckbox from 'pretty-checkbox-vue';
|
||||||
|
Vue.use(PrettyCheckbox)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
render: h => h(App),
|
render: h => h(App),
|
||||||
}).$mount('#app')
|
}).$mount('#app')
|
||||||
|
@ -6651,6 +6651,18 @@ prettier@^1.18.2:
|
|||||||
resolved "https://registry.npm.taobao.org/prettier/download/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
resolved "https://registry.npm.taobao.org/prettier/download/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
||||||
integrity sha1-99f1/4qc2HKnvkyhQglZVqYHl8s=
|
integrity sha1-99f1/4qc2HKnvkyhQglZVqYHl8s=
|
||||||
|
|
||||||
|
pretty-checkbox-vue@^1.1.9:
|
||||||
|
version "1.1.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/pretty-checkbox-vue/-/pretty-checkbox-vue-1.1.9.tgz#2d4bfc7f20c54a0e7b94b3d205641dbf8f390fb4"
|
||||||
|
integrity sha512-45HOanzF+BUTD5prwCoNrtEFYVzWtASTIIPtPQxGCajC097pFD/9mbyjEjoTsu8Tk4/rSyA7RNk6JpFWVHpLag==
|
||||||
|
dependencies:
|
||||||
|
pretty-checkbox "^3.0.3"
|
||||||
|
|
||||||
|
pretty-checkbox@^3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/pretty-checkbox/-/pretty-checkbox-3.0.3.tgz#d49c8013a8fc08ee0c2d6ebde453464bfdbc428e"
|
||||||
|
integrity sha1-1JyAE6j8CO4MLW695FNGS/28Qo4=
|
||||||
|
|
||||||
pretty-error@^2.0.2:
|
pretty-error@^2.0.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.2.tgz?cache=0&sync_timestamp=1603050722482&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-error%2Fdownload%2Fpretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6"
|
resolved "https://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.2.tgz?cache=0&sync_timestamp=1603050722482&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-error%2Fdownload%2Fpretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6"
|
||||||
|
Loading…
Reference in New Issue
Block a user