From 00f29432628cba78609b6d36a063f66c8c4a2b60 Mon Sep 17 00:00:00 2001 From: szdytom Date: Mon, 28 Aug 2023 12:34:27 +0800 Subject: [PATCH] add vote & loader Signed-off-by: szdytom --- src/ica-admin.sc | 82 +++++++++++++++++++++++++++++++---------- src/ica-goal.sc | 52 -------------------------- src/ica-libs.sc | 55 ++++++++++++++++++++++++++- src/ica-loader.sc | 16 ++++++++ src/ica-settings.sc | 1 - src/ica-vote.sc | 90 +++++++++++++++++++++++++++++++++++++++++++++ src/ica.sc | 40 +++++++++++++++++--- 7 files changed, 255 insertions(+), 81 deletions(-) delete mode 100644 src/ica-goal.sc create mode 100644 src/ica-loader.sc create mode 100644 src/ica-vote.sc diff --git a/src/ica-admin.sc b/src/ica-admin.sc index 6382b62..8ef03f9 100644 --- a/src/ica-admin.sc +++ b/src/ica-admin.sc @@ -2,7 +2,6 @@ __config() -> { 'scope' -> 'global', 'command_permission' -> 'ops', 'commands' -> { - '' -> 'cmdList', 'list' -> 'cmdList', 'confirm' -> 'cmdStart', 'reset clear' -> 'cmdResetClear', @@ -10,23 +9,42 @@ __config() -> { }, }; -import('ica-libs', 'shuffleList', 'countCareer'); +import('ica-libs', 'shuffleList', 'countCareer', 'playerListNbt', 'findVoteMax', 'resetVotes'); __on_start() -> ( if(nbt_storage('ica:data'):'Goals' == null, ( nbt_storage('ica:data', '{Goals: [], Started: 0b, Preparing: 0b}') )); if(nbt_storage('ica:careers'):'Config' == null, ( - nbt_storage('ica:careers', '{Config: [], Participants: []}') + nbt_storage('ica:careers', '{Config: []}') + )); + if(nbt_storage('ica:voting'):'Created' == null, ( + nbt_storage('ica:voting', '{Created: 1b, Candidates: [], Votes: []}') )) ); clearBossbars() -> ( + // bossbar(name, 'remove') is sometimes buggy. run('bossbar remove ica:prepare_counter'); run('bossbar remove ica:time_counter'); run('bossbar remove ica:collected'); ); +cleanPlayerTags() -> ( + for(player('all'), modify(_, 'clear_tag', ['ica.piggy' + , 'ica.wolf', 'ica.hunter', 'ica.spyglasser', 'ica.spyglass_fireball' + , 'ica.voter', 'ica.flyer', 'ica.spyglasser_cooldown' + , 'ica.coordinator', 'ica.deceased', 'ica.participant'])); +); + +endCleanup() -> ( + clearBossbars(); + cleanPlayerTags(); + put(nbt_storage('ica:data'):'Started', '0b'); + put(nbt_storage('ica:data'):'Preparing', '0b'); + run('ica-effect-applier disable'); +); + createBossbar(nid, name, val, sty) -> ( bossbar(nid); bossbar(nid, 'max', val); @@ -46,9 +64,14 @@ __on_player_dies(p) -> ( ); __on_player_connects(p) -> ( - if(nbt_storage('ica:data'):'Started' - && query(p, 'has_scoreboard_tag', 'ica.deceased'), ( - modify(p, 'gamemode', 'spectator'); + if(nbt_storage('ica:data'):'Started', ( + if(!query(p, 'has_scoreboard_tag', 'ica.participant'), ( + modify(p, 'tag', 'ica.deceased'); + )); + + if(p, 'has_scoreboard_tag', 'ica.deceased', ( + modify(p, 'gamemode', 'spectator'); + )); )); ); @@ -65,7 +88,7 @@ tm_per_goal() -> ( ); getPigPlayers() -> ( - entity_selector('@a[tag=!ica.wolf]') + entity_selector('@a[tag=!ica.wolf,tag=ica.participant]') ); getWolfPlayers() -> ( @@ -78,8 +101,7 @@ endGameTitle(p, m, s) -> ( ); endTimeout(iv) -> ( - clearBossbars(); - put(nbt_storage('ica:data'):'Started', '0b'); + endCleanup(); endGameTitle(getPigPlayers(), 'Timeout!' , str('You didn\'t complete %d goals in time.', iv)); endGameTitle(getWolfPlayers(), 'You won!' @@ -87,8 +109,7 @@ endTimeout(iv) -> ( ); endFinish() -> ( - clearBossbars(); - put(nbt_storage('ica:data'):'Started', '0b'); + endCleanup(); endGameTitle(getPigPlayers(), 'Congratulations!', 'You have completed all the goals.'); endGameTitle(getWolfPlayers(), 'Oh no!' , str('They have completed all the goals.', iv)); @@ -120,6 +141,31 @@ warnDeadline(dt) -> ( )); ); +electionKill(pname) -> ( + modify(player(pname), 'kill'); + print(player('all'), str('Election victim %s killed.', pname)) +); + +checkVotes(tm) -> ( + if(tm % 12000 == 3600, ( + print(player('all'), '[WARN] Vote ends in 1 minute'); + return(false); + )); + if(tm % 12000 == 2400, ( + max_p = findVoteMax(); + phint = if(max_p == null, ( + 'nobody was elected.' + ), ( + ele_p = player(max_p); + schedule(200, 'electionKill', ele_p); + print(ele_p, '[WARN] You were elected! You will be killed in 10 seconds.'); + str('elected player %s', max_p) + )); + resetVotes(); + print(player('all'), str('Election result: %s.\nNew eletion round started.', phint)); + )); +); + runUpdateCollect() -> ( if(!nbt_storage('ica:data'):'Started', return()); tm = bossbar('ica:time_counter', 'value') - 20; @@ -131,6 +177,7 @@ runUpdateCollect() -> ( endTimeout(iv); ), ( warnDeadline(dt); + checkVotes(tm); schedule(20, 'runUpdateCollect'); )) ); @@ -172,9 +219,7 @@ playerInit(p) -> ( ); cmdResetClear() -> ( - clearBossbars(); - put(nbt_storage('ica:data'):'Started', '0b'); - put(nbt_storage('ica:data'):'Preparing', '0b'); + endCleanup(); ); cmdReschedule() -> ( @@ -223,16 +268,13 @@ cmdStart() -> ( put(nbt_storage('ica:data'):'Goals[].Completed', '0b'); createBossbar('ica:prepare_counter', 'Preparing', tm_prepare(), null); - schedule(20, 'runUpdatePrepare'); - for(player('all'), modify(_, 'clear_tag', ['ica.piggy' - , 'ica.wolf', 'ica.hunter', 'ica.spyglasser', 'ica.spyglass_fireball' - , 'ica.voter', 'ica.flyer', 'ica.spyglasser_cooldown' - , 'ica.coordinator', 'ica.deceased'])); + cleanPlayerTags(); + put(nbt_storage('ica:voting'), 'Candidates', playerListNbt(participants_list)); for(participants_list, ( - modify(_, 'tag', ['ica.voter', 'ica.flyer']); + modify(_, 'tag', ['ica.voter', 'ica.flyer', 'ica.participant']); career_tag = 'ica.piggy'; if(_i < hunter_n, career_tag = ['ica.hunter', 'ica.spyglasser', 'ica.spyglasser_cooldown']); if(_i < wolf_n, career_tag = ['ica.wolf', 'ica.spyglasser', 'ica.coordinator']); diff --git a/src/ica-goal.sc b/src/ica-goal.sc deleted file mode 100644 index b5c14f1..0000000 --- a/src/ica-goal.sc +++ /dev/null @@ -1,52 +0,0 @@ -__config() -> { - 'scope' -> 'global', - 'command_permission' -> 'ops', - 'commands' -> { - '' -> 'cmdList', - 'list' -> 'cmdList', - 'set ' -> 'cmdSet', - 'add ' -> 'cmdSetAppend', - }, - 'arguments' -> { - 'slot' -> { 'type' -> 'int', 'min' -> 0, 'max' -> 5 - , 'suggest' -> [0, 1, 2, 3, 4, 5] }, - 'item' -> { 'type' -> 'item' } - } -}; - -getFirstUnsetGoal() -> ( - c_for(i = 0, i <= 5, i = i + 1, ( - p = nbt_storage('ica:data'):str('Goals[{Slot: %db}]', i); - if(p == null, ( - return(i); - )) - )); - return(6); -); - -cmdList() -> ( - print('please use /ica instead'); - run('/ica'); -); - -cmdSet(slot_id, goal_item_tuple) -> ( - if(nbt_storage('ica:data'):'Started', ( - print('Already started, use /ica-admin reset clear to cancel.'); - return(false) - )); - pkey = str('Goals[{Slot: %db}]', slot_id); - etag = nbt(str('{Slot: %db, Item: "%s"}', slot_id, goal_item_tuple:0)); - - if(nbt_storage('ica:data'):pkey != null, delete(nbt_storage('ica:data'):pkey)); - put(nbt_storage('ica:data'), 'Goals', etag, -1); - print(str('Goal #%d set to %s.', slot_id, goal_item_tuple:0)) -); - -cmdSetAppend(goal_item_tuple) -> ( - missing_goal = getFirstUnsetGoal(); - if(missing_goal <= 5, ( - cmdSet(missing_goal, goal_item_tuple) - ), ( - print('All are goals set, please specify slot.') - )); -); diff --git a/src/ica-libs.sc b/src/ica-libs.sc index f629c56..198e99d 100644 --- a/src/ica-libs.sc +++ b/src/ica-libs.sc @@ -1,6 +1,7 @@ __config() -> { 'scope' -> 'global', - 'exports' -> ['shuffleList', 'countCareer'] + 'exports' -> ['shuffleList', 'countCareer', 'findVoteMax', 'resetVotes' + , 'playerListNbt', 'listContain', 'countVotes', 'countAbstainVotes'], }; shuffleList(list) -> ( @@ -23,4 +24,54 @@ countCareer(cartype) -> ( ), nbt_storage('ica:careers'):str('Config[{Type: "%s"}].Count', cartype) ) -); \ No newline at end of file +); + +playerListNbt(plist) -> ( + res = []; + for(plist, ( + put(res, null, query(_, 'command_name'), 'extend'); + )); + encode_nbt(res) +); + +listContain(plist, pele) -> ( + for(plist, if(_ == pele, return(true))); + false +); + +nbtLength(l) -> ( + if(l == null, return(0)); + lp = parse_nbt(l); + if(type(l) == 'list', length(l), 1) +); + +countVotes(pname) -> ( + l = nbt_storage('ica:voting'):str('Votes[{Abstain: 0b, To: "%s"}]', pname); + nbtLength(l) +); + +countAbstainVotes() -> ( + l = nbt_storage('ica:voting'):'Votes[{Abstain: 1b}]'; + nbtLength(l) +); + +findVoteMax() -> ( + cand_names = parse_nbt(nbt_storage('ica:voting'):'Candidates'); + max_p = null; + max_c = countAbstainVotes(); + for(cand_names, ( + v_n = countVotes(_); + if(v_n == max_c, ( + max_p = null; + )); + if(v_n > max_c, ( + max_p = _; + max_c = v_n; + )); + )); + max_p +); + +resetVotes() -> ( + put(nbt_storage('ica:voting'), 'Votes', '[]'); +); diff --git a/src/ica-loader.sc b/src/ica-loader.sc new file mode 100644 index 0000000..4d326e6 --- /dev/null +++ b/src/ica-loader.sc @@ -0,0 +1,16 @@ +__config() -> { + 'scope' -> 'global', + 'command_permission' -> 'ops', + 'commands' -> { + '' -> 'cmdLoad', + }, +}; + +cmdLoad() -> ( + run('script load ica-admin'); + run('script load ica-effect-applier'); + run('script load ica-fireball'); + run('script load ica'); + run('script load ica-vote'); + run('script load ica-settings'); +); diff --git a/src/ica-settings.sc b/src/ica-settings.sc index a2dedcc..d0fba32 100644 --- a/src/ica-settings.sc +++ b/src/ica-settings.sc @@ -2,7 +2,6 @@ __config() -> { 'scope' -> 'global', 'command_permission' -> 'ops', 'commands' -> { - '' -> 'cmdList', 'list' -> 'cmdList', 'set ' -> 'cmdSet', 'add ' -> 'cmdSetAppend', diff --git a/src/ica-vote.sc b/src/ica-vote.sc new file mode 100644 index 0000000..1c4100a --- /dev/null +++ b/src/ica-vote.sc @@ -0,0 +1,90 @@ +__config() -> { + 'commands' -> { + '' -> 'cmdInfo', + 'list' -> 'cmdInfo', + 'info' -> 'cmdInfo', + 'sus ' -> 'cmdVotePlayer', + 'abstain' -> 'cmdVoteAbstain', + }, + 'arguments' -> { + 'candidate_name' -> { 'type' -> 'string', 'suggester' -> _(arg) -> ( + if(nbt_storage('ica:data'):'Started', + parse_nbt(nbt_storage('ica:voting'):'Candidates'), + [] + ) + )}, + } +}; + +import('ica-libs', 'listContain', 'countVotes', 'findVoteMax', 'countAbstainVotes'); + + +cmdInfo() -> ( + if(!nbt_storage('ica:data'):'Started', ( + print('Not started. use /ica-admin confirm to start.'); + return(false) + )); + cand_names = parse_nbt(nbt_storage('ica:voting'):'Candidates'); + cand_n = length(cand_names); + print(str('There are %d candidates:', cand_n)); + for(cand_names, ( + p = player(_); + v_cnt = countVotes(_); + print(str(' - %02d vote%s %s%s', v_cnt, if(v_cnt > 1, 's', ' ') + , _, if(query(p, 'has_scoreboard_tag', 'ica.deceased'), ' [deceased]', ''))); + )); + abv_cnt = countAbstainVotes(); + print(' - %02d vote%s (abstain)', abv_cnt, if(abv_cnt > 1, 's', ' ')); + + max_p = findVoteMax(); + print(str('Current elected: %s', if(max_p == null, '(nobody)', max_p))); +); + +beforeVoteChecks() -> ( + if(!nbt_storage('ica:data'):'Started', ( + print('Not started. use /ica-admin confirm to start.'); + return(false) + )); + myself = player(); + if(query(myself, 'has_scoreboard_tag', 'ica.deceased'), ( + print('You can only bystand.'); + return(false); + )); + if(!query(myself, 'has_scoreboard_tag', 'ica.voter'), ( + print('You don\'t have this ability'); + return(false); + )); + myname = query(myself, 'command_name'); + if(has(nbt_storage('ica:voting'), str('Votes[{From: "%s"}]', myname)), ( + print('You have already voted.'); + return(false); + )); + true +); + +cmdVotePlayer(sus_name) -> ( + if(!beforeVoteChecks(), return(false)); + + cand_names = parse_nbt(nbt_storage('ica:voting'):'Candidates'); + if(!listContain(cand_names, sus_name), ( + print(str('Candidate %s not found.', sus_name)); + return(false); + )); + + myself = player(); + myname = query(myself, 'command_name'); + + etags = nbt(str('{From: "%s", To: "%s", Abstain: 0b}', myname, sus_name)); + put(nbt_storage('ica:voting'), 'Votes', etags, -1); + print('OK.'); +); + +cmdVoteAbstain() -> ( + if(!beforeVoteChecks(), return(false)); + myself = player(); + myname = query(myself, 'command_name'); + + etags = nbt(str('{From: "%s", To: "", Abstain: 1b}', myname)); + put(nbt_storage('ica:voting'), 'Votes', etags, -1); + print('OK.'); +); diff --git a/src/ica.sc b/src/ica.sc index 90b48fa..48493e7 100644 --- a/src/ica.sc +++ b/src/ica.sc @@ -6,6 +6,7 @@ __config() -> { 'refill' -> 'cmdRefill', 'seed' -> 'cmdSeed', 'me' -> 'cmdMe', + 'whoami' -> 'cmdMe', 'locate ' -> 'cmdLocate', }, 'arguments' -> { @@ -28,17 +29,32 @@ cmdLocate(pname) -> ( print('Not started. use /ica-admin confirm to start.'); return(false) )); + myself = player(); + if(query(myself, 'has_scoreboard_tag', 'ica.deceased'), ( + print('You can only bystand.'); + return(false); + )); if(!query(player(), 'has_scoreboard_tag', 'ica.coordinator'), ( print('You don\'t have this ability.'); return(false) )); p = player(pname:0); + if(p == null, ( + print('Not found'); + return(false); + )); + ppos = query(p, 'pos'); pdim = query(p, 'dimension'); - mydim = query(player(), 'dimension'); + mydim = query(myself, 'dimension'); if(pdim == mydim, ( print(str('%s: %.1f %.1f %.1f.', pdim, ppos:0, ppos:1, ppos:2)); + sslot = query(myself, 'selected_slot'); + sitem = inventory_get(myself, sslot); + inventory_set(myself, sslot, 1, 'compass', + str('{LodestonePos: {X: %d, Y: %d, Z: %d}, LodestoneDimension: "%s", LodestoneTracked: 0b}' + , floor(ppos:0), floor(ppos:1), floor(ppos:2), pdim)); ), ( print(str('%s: ? ? ?', pdim)); )); @@ -53,11 +69,18 @@ cmdRefill() -> ( print('Not started. use /ica-admin confirm to start.'); return(false) )); - if(!query(player(), 'has_scoreboard_tag', 'ica.flyer'), ( - print('You cannot fly.'); - return(false) + myself = player(); + if(query(myself, 'has_scoreboard_tag', 'ica.deceased'), ( + print('You can only bystand.'); + return(false); + )); + if(query(myself, 'has_scoreboard_tag', 'ica.flyer'), ( + run('give @s minecraft:firework_rocket 64'); + )); + if(query(myself, 'has_scoreboard_tag', 'ica.spyglasser') + && !nbt_storage('ica:data'):'Preparing', ( + modify(myself, 'tag', 'ica.spyglass_fireball'); )); - run('give @s minecraft:firework_rocket 64'); ); cmdList() -> ( @@ -136,6 +159,11 @@ cmdSubmit(slot_id) -> ( print('Currently preparing, please submit later.'); return(false) )); + me = player(); + if(query(me, 'has_scoreboard_tag', 'ica.deceased'), ( + print('You can only bystand.'); + return(false); + )); pkey = str('Goals[{Slot: %db}]', slot_id); if(nbt_storage('ica:data'):pkey:'Completed', ( @@ -143,7 +171,7 @@ cmdSubmit(slot_id) -> ( nbt_storage('ica:data'):pkey:'Item'))); return() )); - me = player(); + if(inventory_remove(me, nbt_storage('ica:data'):pkey:'Item', 1) == 0, ( print(str('%s not found.', item_display_name( nbt_storage('ica:data'):pkey:'Item')));