Added deck search and more hotkeys🔍
This commit is contained in:
@ -5,12 +5,14 @@ specifically designed to be used when players share a deck
|
|||||||
definitely not a shameless untap clone
|
definitely not a shameless untap clone
|
||||||
|
|
||||||
# todo
|
# todo
|
||||||
+ Add drag-and-drop from hand and piles
|
+ Add hotkeys for every zone (*Really* almost done!)
|
||||||
+ Add hotkeys for every zone (Almost done!)
|
|
||||||
+ ~~Add untap all hotkey~~
|
+ ~~Add untap all hotkey~~
|
||||||
+ Add viewing top of deck
|
+ Add viewing top of deck
|
||||||
|
+ ~~Add searching deck~~
|
||||||
+ Add score values (usable for life counters)
|
+ Add score values (usable for life counters)
|
||||||
|
+ Make events visible
|
||||||
|
|
||||||
# maybe todo
|
# maybe todo
|
||||||
|
+ Add drag-and-drop from hand and piles
|
||||||
+ Make deck information, piles, and score info json-configurable
|
+ Make deck information, piles, and score info json-configurable
|
||||||
+ Use cookies instead of hardcoded url uuid
|
+ Use cookies instead of hardcoded url uuid
|
||||||
|
|||||||
41
src/game.rs
41
src/game.rs
@ -58,6 +58,9 @@ enum Event {
|
|||||||
Unkill(Uuid, bool),
|
Unkill(Uuid, bool),
|
||||||
TransferDeadCard(Uuid, bool),
|
TransferDeadCard(Uuid, bool),
|
||||||
UntapAll(Player),
|
UntapAll(Player),
|
||||||
|
ViewDeck(Player),
|
||||||
|
Yoink(Player),
|
||||||
|
YoinkMill(Uuid),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone, Debug)]
|
#[derive(Serialize, Clone, Debug)]
|
||||||
@ -168,6 +171,32 @@ pub fn draw(game_state: &mut GameState, count: usize, player: Player) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn yoink(game_state: &mut GameState, deck_index: usize, player: Player) {
|
||||||
|
let player_hand = match player {
|
||||||
|
Player::A => &mut game_state.hands[0],
|
||||||
|
_ => &mut game_state.hands[1],
|
||||||
|
};
|
||||||
|
game_state.events.push(CountedEvent {
|
||||||
|
id: game_state.events.len(),
|
||||||
|
event: Event::Yoink(player.clone()),
|
||||||
|
});
|
||||||
|
player_hand.cards.push(game_state.deck.remove(deck_index).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yoink_mill(game_state: &mut GameState, deck_index: usize, shadow: bool) {
|
||||||
|
let card = game_state.deck.remove(deck_index).unwrap();
|
||||||
|
game_state.events.push(CountedEvent {
|
||||||
|
id: game_state.events.len(),
|
||||||
|
event: Event::YoinkMill(card.clone()),
|
||||||
|
});
|
||||||
|
if shadow {
|
||||||
|
game_state.shadow_realm.push(card);
|
||||||
|
} else {
|
||||||
|
game_state.discard_pile.push(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
pub fn shuffle(game_state: &mut GameState, player: Player) {
|
pub fn shuffle(game_state: &mut GameState, player: Player) {
|
||||||
game_state.events.push(CountedEvent {
|
game_state.events.push(CountedEvent {
|
||||||
id: game_state.events.len(),
|
id: game_state.events.len(),
|
||||||
@ -384,3 +413,15 @@ pub fn untap_all(game_state: &mut GameState, player: Player) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_deck(game_state: &mut GameState, player: Player) -> String {
|
||||||
|
game_state.events.push(CountedEvent {
|
||||||
|
id: game_state.events.len(),
|
||||||
|
event: Event::ViewDeck(player),
|
||||||
|
});
|
||||||
|
let deck_copy = game_state.deck.clone();
|
||||||
|
//let copy_slice = deck_copy.make_contiguous();
|
||||||
|
//copy_slice.sort();
|
||||||
|
/*let final_card_list = copy_slice.into_iter().map(|card| card.braced().to_string()).collect::<Vec<String>>();*/
|
||||||
|
serde_json::to_string(&deck_copy).unwrap()
|
||||||
|
}
|
||||||
|
|||||||
77
src/main.rs
77
src/main.rs
@ -26,7 +26,7 @@ fn get_events(game_state_arc: &State<ArcMutexGameState>) -> String {
|
|||||||
format!("{}", game::get_events(&game_state))
|
format!("{}", game::get_events(&game_state))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/<uuid>/shuffle")]
|
#[get("/<uuid>/shuffle")]
|
||||||
fn shuffle(
|
fn shuffle(
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
game_state_arc: &State<ArcMutexGameState>,
|
game_state_arc: &State<ArcMutexGameState>,
|
||||||
@ -247,6 +247,57 @@ fn unshadow(
|
|||||||
Ok(format!("{}", game::get_events(&game_state)))
|
Ok(format!("{}", game::get_events(&game_state)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/<uuid>/yoink/<index>")]
|
||||||
|
fn yoink(
|
||||||
|
uuid: Uuid,
|
||||||
|
index: usize,
|
||||||
|
game_state_arc: &State<ArcMutexGameState>,
|
||||||
|
player_uuids: &State<PlayerUuids>,
|
||||||
|
) -> Result<String, BadRequest<String>> {
|
||||||
|
let player = match player_uuids.map.get(&uuid) {
|
||||||
|
Some(player) => player,
|
||||||
|
None => return Err(BadRequest(format!("Invalid player {}.", uuid))),
|
||||||
|
};
|
||||||
|
let game_state_mutex = Arc::clone(&game_state_arc.state);
|
||||||
|
let mut game_state = game_state_mutex.lock().unwrap();
|
||||||
|
game::yoink(&mut game_state, index, player.clone());
|
||||||
|
Ok(format!("{}", game::get_events(&game_state)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/<uuid>/yoink_mill/<index>")]
|
||||||
|
fn yoink_mill(
|
||||||
|
uuid: Uuid,
|
||||||
|
index: usize,
|
||||||
|
game_state_arc: &State<ArcMutexGameState>,
|
||||||
|
player_uuids: &State<PlayerUuids>,
|
||||||
|
) -> Result<String, BadRequest<String>> {
|
||||||
|
match player_uuids.map.get(&uuid) {
|
||||||
|
Some(_) => (),
|
||||||
|
None => return Err(BadRequest(format!("Invalid player {}.", uuid))),
|
||||||
|
};
|
||||||
|
let game_state_mutex = Arc::clone(&game_state_arc.state);
|
||||||
|
let mut game_state = game_state_mutex.lock().unwrap();
|
||||||
|
game::yoink_mill(&mut game_state, index, false);
|
||||||
|
Ok(format!("{}", game::get_events(&game_state)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/<uuid>/yoink_xmill/<index>")]
|
||||||
|
fn yoink_xmill(
|
||||||
|
uuid: Uuid,
|
||||||
|
index: usize,
|
||||||
|
game_state_arc: &State<ArcMutexGameState>,
|
||||||
|
player_uuids: &State<PlayerUuids>,
|
||||||
|
) -> Result<String, BadRequest<String>> {
|
||||||
|
match player_uuids.map.get(&uuid) {
|
||||||
|
Some(_) => (),
|
||||||
|
None => return Err(BadRequest(format!("Invalid player {}.", uuid))),
|
||||||
|
};
|
||||||
|
let game_state_mutex = Arc::clone(&game_state_arc.state);
|
||||||
|
let mut game_state = game_state_mutex.lock().unwrap();
|
||||||
|
game::yoink_mill(&mut game_state, index, true);
|
||||||
|
Ok(format!("{}", game::get_events(&game_state)))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/<uuid>/undiscard/<index>")]
|
#[get("/<uuid>/undiscard/<index>")]
|
||||||
fn undiscard(
|
fn undiscard(
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
@ -316,6 +367,24 @@ fn get_state(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/<uuid>/get_deck")]
|
||||||
|
fn get_deck(
|
||||||
|
uuid: Uuid,
|
||||||
|
game_state_arc: &State<ArcMutexGameState>,
|
||||||
|
player_uuids: &State<PlayerUuids>,
|
||||||
|
) -> Result<String, BadRequest<String>> {
|
||||||
|
let game_state_mutex = Arc::clone(&game_state_arc.state);
|
||||||
|
let mut game_state = game_state_mutex.lock().unwrap();
|
||||||
|
let player = match player_uuids.map.get(&uuid) {
|
||||||
|
Some(player) => player,
|
||||||
|
None => return Err(BadRequest(format!("Invalid player {}.", uuid))),
|
||||||
|
};
|
||||||
|
Ok(format!(
|
||||||
|
"{}",
|
||||||
|
game::get_deck(&mut game_state, player.clone())
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/<uuid>/untap_all")]
|
#[get("/<uuid>/untap_all")]
|
||||||
fn untap_all(
|
fn untap_all(
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
@ -427,7 +496,7 @@ struct PlayerUuids {
|
|||||||
|
|
||||||
#[launch]
|
#[launch]
|
||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
let mut game_state = game::new();
|
let game_state = game::new();
|
||||||
//game::draw(&mut game_state, 7, Player::A);
|
//game::draw(&mut game_state, 7, Player::A);
|
||||||
//game::draw(&mut game_state, 7, Player::B);
|
//game::draw(&mut game_state, 7, Player::B);
|
||||||
let game_state_arc = Arc::new(Mutex::new(game_state));
|
let game_state_arc = Arc::new(Mutex::new(game_state));
|
||||||
@ -482,6 +551,10 @@ fn rocket() -> _ {
|
|||||||
undiscard,
|
undiscard,
|
||||||
remember,
|
remember,
|
||||||
untap_all,
|
untap_all,
|
||||||
|
get_deck,
|
||||||
|
yoink,
|
||||||
|
yoink_mill,
|
||||||
|
yoink_xmill,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.manage(ArcMutexGameState {
|
.manage(ArcMutexGameState {
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
</aside>
|
</aside>
|
||||||
<aside id="piles">
|
<aside id="piles">
|
||||||
<div class="pile" id="deck">
|
<div class="pile" id="deck">
|
||||||
<img src="./card_back.png" alt="" id="deck" />
|
<img src="./card_back.png" alt="" id="deck-img" />
|
||||||
<span id="deck-count"></span>
|
<span id="deck-count"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="pile" id="discard-pile">
|
<div class="pile" id="discard-pile">
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
const $view-card-container = document.query-selector '#view-card-container'
|
const $view-card-container = document.query-selector '#view-card-container'
|
||||||
const $param = document.query-selector '#param'
|
const $param = document.query-selector '#param'
|
||||||
const $play = document.query-selector '#play'
|
const $play = document.query-selector '#play'
|
||||||
window.$play = play
|
|
||||||
const $discard-pile = document.query-selector '#discard-pile'
|
const $discard-pile = document.query-selector '#discard-pile'
|
||||||
const $discard-pile-img = document.query-selector '#discard-pile-img'
|
const $discard-pile-img = document.query-selector '#discard-pile-img'
|
||||||
const $discard-pile-count = document.query-selector '#discard-pile-count'
|
const $discard-pile-count = document.query-selector '#discard-pile-count'
|
||||||
@ -19,6 +18,7 @@
|
|||||||
const $shadow-realm-img = document.query-selector '#shadow-realm-img'
|
const $shadow-realm-img = document.query-selector '#shadow-realm-img'
|
||||||
const $shadow-realm-count = document.query-selector '#shadow-realm-count'
|
const $shadow-realm-count = document.query-selector '#shadow-realm-count'
|
||||||
const $deck = document.query-selector '#deck'
|
const $deck = document.query-selector '#deck'
|
||||||
|
const $deck-img = document.query-selector '#deck-img'
|
||||||
const $deck-count = document.query-selector '#deck-count'
|
const $deck-count = document.query-selector '#deck-count'
|
||||||
const $extra = document.query-selector '#extra'
|
const $extra = document.query-selector '#extra'
|
||||||
const [push-param, pop-param] = (->
|
const [push-param, pop-param] = (->
|
||||||
@ -82,7 +82,7 @@
|
|||||||
$view-card.style.opacity = 1
|
$view-card.style.opacity = 1
|
||||||
e.target.add-event-listener \mouseleave hide-card$
|
e.target.add-event-listener \mouseleave hide-card$
|
||||||
state = await get-state!
|
state = await get-state!
|
||||||
const apply-state$ = ->
|
const apply-state$ = ->>
|
||||||
{ player-state } = it
|
{ player-state } = it
|
||||||
gen-opponent-cards$ player-state.opponent_cards_in_hand
|
gen-opponent-cards$ player-state.opponent_cards_in_hand
|
||||||
if document.body.class-list.contains \my-turn
|
if document.body.class-list.contains \my-turn
|
||||||
@ -109,7 +109,8 @@
|
|||||||
| \discard => player-state.discard_pile
|
| \discard => player-state.discard_pile
|
||||||
| \shadow => player-state.shadow_realm
|
| \shadow => player-state.shadow_realm
|
||||||
| \deck => gen-array-of state.player-state.deck_size, null
|
| \deck => gen-array-of state.player-state.deck_size, null
|
||||||
| _ => (console.log that) || []
|
| \deck-revealed => await fetch-log \./get_deck .then (.json!)
|
||||||
|
| _ => (console.error that) || []
|
||||||
open-list list, $extra.get-attribute \data-pile-type
|
open-list list, $extra.get-attribute \data-pile-type
|
||||||
if player-state.hand.length != $own-hand.children.length
|
if player-state.hand.length != $own-hand.children.length
|
||||||
$own-hand.innerHTML = ''
|
$own-hand.innerHTML = ''
|
||||||
@ -212,8 +213,11 @@
|
|||||||
$play.add-event-listener \dragover (.prevent-default!)
|
$play.add-event-listener \dragover (.prevent-default!)
|
||||||
|
|
||||||
$discard-pile-img.add-event-listener \click -> open-list state.player-state.discard_pile, \discard
|
$discard-pile-img.add-event-listener \click -> open-list state.player-state.discard_pile, \discard
|
||||||
|
$discard-pile-count.add-event-listener \click -> open-list state.player-state.discard_pile, \discard
|
||||||
$shadow-realm-img.add-event-listener \click -> open-list state.player-state.shadow_realm, \shadow
|
$shadow-realm-img.add-event-listener \click -> open-list state.player-state.shadow_realm, \shadow
|
||||||
$deck.add-event-listener \click -> open-list (gen-array-of state.player-state.deck_size, null), \deck
|
$shadow-realm-count.add-event-listener \click -> open-list state.player-state.shadow_realm, \shadow
|
||||||
|
$deck-img.add-event-listener \click -> open-list (gen-array-of state.player-state.deck_size, null), \deck
|
||||||
|
$deck-count.add-event-listener \click -> open-list (gen-array-of state.player-state.deck_size, null), \deck
|
||||||
|
|
||||||
set-interval (->>
|
set-interval (->>
|
||||||
const new-state = await get-state!
|
const new-state = await get-state!
|
||||||
@ -234,8 +238,12 @@
|
|||||||
..add-event-listener \keyup ->
|
..add-event-listener \keyup ->
|
||||||
$current-mouse-node = [...document.query-selector-all \:hover][* - 1]
|
$current-mouse-node = [...document.query-selector-all \:hover][* - 1]
|
||||||
switch it.key.to-lower-case!
|
switch it.key.to-lower-case!
|
||||||
|
| \v =>
|
||||||
|
fetch-log \./shuffle
|
||||||
|
if $extra.has-attribute \data-pile-type and \deck-revealed == $extra.get-attribute \data-pile-type
|
||||||
|
$extra.class-list.add \hidden
|
||||||
| \c => fetch-log "./draw/#{pop-param!}"
|
| \c => fetch-log "./draw/#{pop-param!}"
|
||||||
| \e => fetch-log "./pass"
|
| \e => fetch-log \./pass
|
||||||
| \0 \1 \2 \3 \4 \5 \6 \7 \8 \9 => push-param that
|
| \0 \1 \2 \3 \4 \5 \6 \7 \8 \9 => push-param that
|
||||||
| \t =>
|
| \t =>
|
||||||
if $current-mouse-node?.has-attribute \data-hand-index
|
if $current-mouse-node?.has-attribute \data-hand-index
|
||||||
@ -256,6 +264,8 @@
|
|||||||
switch $current-mouse-node.get-attribute \data-list-type
|
switch $current-mouse-node.get-attribute \data-list-type
|
||||||
| \discard
|
| \discard
|
||||||
fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
|
| \deck , \deck-revealed
|
||||||
|
return # will add play button
|
||||||
| \shadow
|
| \shadow
|
||||||
fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||||
@ -269,8 +279,8 @@
|
|||||||
switch $current-mouse-node.get-attribute \data-list-type
|
switch $current-mouse-node.get-attribute \data-list-type
|
||||||
| \discard
|
| \discard
|
||||||
fetch-log "./undiscard/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./undiscard/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
| \deck
|
| \deck , \deck-revealed
|
||||||
void #fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./yoink/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
| \shadow
|
| \shadow
|
||||||
fetch-log "./remember/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./remember/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||||
@ -285,11 +295,11 @@
|
|||||||
else if $current-mouse-node?.has-attribute \data-list-type
|
else if $current-mouse-node?.has-attribute \data-list-type
|
||||||
switch $current-mouse-node.get-attribute \data-list-type
|
switch $current-mouse-node.get-attribute \data-list-type
|
||||||
| \discard
|
| \discard
|
||||||
return #fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
return
|
||||||
| \deck
|
| \deck , \deck-revealed
|
||||||
void #fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./yoink_mill/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
| \shadow
|
| \shadow
|
||||||
fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./undiscard/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||||
if !$extra.child-element-count
|
if !$extra.child-element-count
|
||||||
$extra.class-list.add \hidden
|
$extra.class-list.add \hidden
|
||||||
@ -303,10 +313,10 @@
|
|||||||
switch $current-mouse-node.get-attribute \data-list-type
|
switch $current-mouse-node.get-attribute \data-list-type
|
||||||
| \discard
|
| \discard
|
||||||
fetch-log "./shadow/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./shadow/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
| \deck
|
| \deck , \deck-revealed
|
||||||
void #fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}"
|
fetch-log "./yoink_xmill/#{$current-mouse-node.get-attribute \data-index}"
|
||||||
| \shadow
|
| \shadow
|
||||||
return #fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}"
|
return
|
||||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||||
if !$extra.child-element-count
|
if !$extra.child-element-count
|
||||||
$extra.class-list.add \hidden
|
$extra.class-list.add \hidden
|
||||||
@ -315,10 +325,13 @@
|
|||||||
$extra.class-list.add \hidden
|
$extra.class-list.add \hidden
|
||||||
$extra.remove-attribute \data-pile-type
|
$extra.remove-attribute \data-pile-type
|
||||||
| \x =>
|
| \x =>
|
||||||
console.log
|
|
||||||
if it.shift-key || state.player-state.turn_player == state.player-state.you
|
if it.shift-key || state.player-state.turn_player == state.player-state.you
|
||||||
fetch-log \./untap_all
|
fetch-log \./untap_all
|
||||||
[...$play.children]
|
[...$play.children]
|
||||||
.filter -> \true == it.get-attribute \data-owned
|
.filter -> \true == it.get-attribute \data-owned
|
||||||
.for-each -> it.set-attribute \data-tapped false
|
.for-each -> it.set-attribute \data-tapped false
|
||||||
|
| \f =>
|
||||||
|
fetch-log \./get_deck .then ->>
|
||||||
|
const deck = await it.json!
|
||||||
|
open-list deck, \deck-revealed
|
||||||
)!
|
)!
|
||||||
|
|||||||
Reference in New Issue
Block a user