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
|
||||
|
||||
# todo
|
||||
+ Add drag-and-drop from hand and piles
|
||||
+ Add hotkeys for every zone (Almost done!)
|
||||
+ Add hotkeys for every zone (*Really* almost done!)
|
||||
+ ~~Add untap all hotkey~~
|
||||
+ Add viewing top of deck
|
||||
+ ~~Add searching deck~~
|
||||
+ Add score values (usable for life counters)
|
||||
+ Make events visible
|
||||
|
||||
# maybe todo
|
||||
+ Add drag-and-drop from hand and piles
|
||||
+ Make deck information, piles, and score info json-configurable
|
||||
+ Use cookies instead of hardcoded url uuid
|
||||
|
||||
41
src/game.rs
41
src/game.rs
@ -58,6 +58,9 @@ enum Event {
|
||||
Unkill(Uuid, bool),
|
||||
TransferDeadCard(Uuid, bool),
|
||||
UntapAll(Player),
|
||||
ViewDeck(Player),
|
||||
Yoink(Player),
|
||||
YoinkMill(Uuid),
|
||||
}
|
||||
|
||||
#[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) {
|
||||
game_state.events.push(CountedEvent {
|
||||
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))
|
||||
}
|
||||
|
||||
#[post("/<uuid>/shuffle")]
|
||||
#[get("/<uuid>/shuffle")]
|
||||
fn shuffle(
|
||||
uuid: Uuid,
|
||||
game_state_arc: &State<ArcMutexGameState>,
|
||||
@ -247,6 +247,57 @@ fn unshadow(
|
||||
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>")]
|
||||
fn undiscard(
|
||||
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")]
|
||||
fn untap_all(
|
||||
uuid: Uuid,
|
||||
@ -427,7 +496,7 @@ struct PlayerUuids {
|
||||
|
||||
#[launch]
|
||||
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::B);
|
||||
let game_state_arc = Arc::new(Mutex::new(game_state));
|
||||
@ -482,6 +551,10 @@ fn rocket() -> _ {
|
||||
undiscard,
|
||||
remember,
|
||||
untap_all,
|
||||
get_deck,
|
||||
yoink,
|
||||
yoink_mill,
|
||||
yoink_xmill,
|
||||
],
|
||||
)
|
||||
.manage(ArcMutexGameState {
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
</aside>
|
||||
<aside id="piles">
|
||||
<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>
|
||||
</div>
|
||||
<div class="pile" id="discard-pile">
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
const $view-card-container = document.query-selector '#view-card-container'
|
||||
const $param = document.query-selector '#param'
|
||||
const $play = document.query-selector '#play'
|
||||
window.$play = play
|
||||
const $discard-pile = document.query-selector '#discard-pile'
|
||||
const $discard-pile-img = document.query-selector '#discard-pile-img'
|
||||
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-count = document.query-selector '#shadow-realm-count'
|
||||
const $deck = document.query-selector '#deck'
|
||||
const $deck-img = document.query-selector '#deck-img'
|
||||
const $deck-count = document.query-selector '#deck-count'
|
||||
const $extra = document.query-selector '#extra'
|
||||
const [push-param, pop-param] = (->
|
||||
@ -82,7 +82,7 @@
|
||||
$view-card.style.opacity = 1
|
||||
e.target.add-event-listener \mouseleave hide-card$
|
||||
state = await get-state!
|
||||
const apply-state$ = ->
|
||||
const apply-state$ = ->>
|
||||
{ player-state } = it
|
||||
gen-opponent-cards$ player-state.opponent_cards_in_hand
|
||||
if document.body.class-list.contains \my-turn
|
||||
@ -109,7 +109,8 @@
|
||||
| \discard => player-state.discard_pile
|
||||
| \shadow => player-state.shadow_realm
|
||||
| \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
|
||||
if player-state.hand.length != $own-hand.children.length
|
||||
$own-hand.innerHTML = ''
|
||||
@ -212,8 +213,11 @@
|
||||
$play.add-event-listener \dragover (.prevent-default!)
|
||||
|
||||
$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
|
||||
$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 (->>
|
||||
const new-state = await get-state!
|
||||
@ -234,8 +238,12 @@
|
||||
..add-event-listener \keyup ->
|
||||
$current-mouse-node = [...document.query-selector-all \:hover][* - 1]
|
||||
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!}"
|
||||
| \e => fetch-log "./pass"
|
||||
| \e => fetch-log \./pass
|
||||
| \0 \1 \2 \3 \4 \5 \6 \7 \8 \9 => push-param that
|
||||
| \t =>
|
||||
if $current-mouse-node?.has-attribute \data-hand-index
|
||||
@ -256,6 +264,8 @@
|
||||
switch $current-mouse-node.get-attribute \data-list-type
|
||||
| \discard
|
||||
fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \deck , \deck-revealed
|
||||
return # will add play button
|
||||
| \shadow
|
||||
fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}"
|
||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||
@ -269,8 +279,8 @@
|
||||
switch $current-mouse-node.get-attribute \data-list-type
|
||||
| \discard
|
||||
fetch-log "./undiscard/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \deck
|
||||
void #fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \deck , \deck-revealed
|
||||
fetch-log "./yoink/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \shadow
|
||||
fetch-log "./remember/#{$current-mouse-node.get-attribute \data-index}"
|
||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||
@ -285,11 +295,11 @@
|
||||
else if $current-mouse-node?.has-attribute \data-list-type
|
||||
switch $current-mouse-node.get-attribute \data-list-type
|
||||
| \discard
|
||||
return #fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \deck
|
||||
void #fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}"
|
||||
return
|
||||
| \deck , \deck-revealed
|
||||
fetch-log "./yoink_mill/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \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
|
||||
if !$extra.child-element-count
|
||||
$extra.class-list.add \hidden
|
||||
@ -303,10 +313,10 @@
|
||||
switch $current-mouse-node.get-attribute \data-list-type
|
||||
| \discard
|
||||
fetch-log "./shadow/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \deck
|
||||
void #fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \deck , \deck-revealed
|
||||
fetch-log "./yoink_xmill/#{$current-mouse-node.get-attribute \data-index}"
|
||||
| \shadow
|
||||
return #fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}"
|
||||
return
|
||||
$current-mouse-node.parent-element.remove-child $current-mouse-node
|
||||
if !$extra.child-element-count
|
||||
$extra.class-list.add \hidden
|
||||
@ -315,10 +325,13 @@
|
||||
$extra.class-list.add \hidden
|
||||
$extra.remove-attribute \data-pile-type
|
||||
| \x =>
|
||||
console.log
|
||||
if it.shift-key || state.player-state.turn_player == state.player-state.you
|
||||
fetch-log \./untap_all
|
||||
[...$play.children]
|
||||
.filter -> \true == it.get-attribute \data-owned
|
||||
.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