Sui Move 简易版扫雷 —— 以传统的扫雷游戏规则为模板,将扫雷区域简化成 5 × 10 的正方形,点开所有安全格子视为获得胜利。
以传统的扫雷游戏规则为模板,将扫雷区域简化成 $\text 5\ \times\ \text {10}$ 的正方形,点开所有安全格子视为获得胜利。
借助 $\mathit {One}$-$\mathit {Time}$-$\mathit {Witness}$ 生成Publisher
,需要一个与模块同名并全大写的结构体:
public struct ADMIN has drop {}
存储游戏发布者的相关信息,主要是 $\mathit {Sui}$ 余额和发布者的地址:
public struct GameCap has key {
id: UID,
balance: Balance<SUI>,
publisher_address: address,
}
奖励金额和发布者收益是必须的,为了清楚任务发布者是谁,还需要他/她的地址,除此之外,还可以维护两个数 —— 正在挑战的人数和尝试挑战的总人数,为游戏更增添一份紧张刺激感:
public struct Task has store {
in_task: u64,
total_attempts: u64,
reward: Balance<SUI>,
earned: Balance<SUI>,
task_publisher_address: address,
}
任务信息的结构设计并不能单独存在,我们另外开辟一个列表来存储一系列任务:
public struct TaskList has key {
id: UID,
task_ids: vector<ID>,
tasks: Table<ID, Task>,
}
通过任务编号查询其信息,触发事件并返回时使用的结构体:
public struct QueryTaskEvent has copy, drop {
task_id: ID,
in_task: u64,
total_attempts: u64,
cur_reward: u64,
}
存储有扫雷区域现状,每个格子是否安全的哈希码,如果是从任务进入的游戏,还需要对应的任务编号:
public struct GameInfo has key {
id: UID,
task_id: ID,
checkerboard: vector<vector<Char>>,
hash_code: vector<u8>,
}
一个任务可以同时被多个人开启,但最终完成并获得奖励的只有一人,此时其他人再尝试该任务时触发:
public struct PlayTooLate has copy, drop {
loser: String,
}
一系列在游戏过程中可能触发的情况事件,包括每一次扫雷后的区域变化事件、游戏成功事件以及游戏失败事件:
public struct GameEvent has copy, drop {
checkerboard: vector<String>,
}
public struct GameSuccessEvent has copy, drop {
reward: u64,
}
public struct GameOverEvent has copy, drop {
loser: String,
}
通过 $\mathit {One}$-$\mathit {Time}$-$\mathit {Witness}$ 生成Publisher
,同时根据发布者信息创建并共享GameCap
:
fun init(otw: ADMIN, ctx: &mut TxContext) {
// create and transfer Publisher
package::claim_and_keep(otw, ctx);
// create and transfer GameCap
let game_cap = GameCap {
id: object::new(ctx),
balance: balance::zero(),
publisher_address: ctx.sender(),
};
transfer::share_object(game_cap);
}
根据游戏设计,提现到游戏发布者钱包有两种情况,一种是手动(仅限发布者本人调用),另一种是到达一定金额是自动,为了更好地满足这两种情况,将提现的函数进行拆分:
public(package) fun withdraw_(game_cap: &mut GameCap, ctx: &mut TxContext) {
// check the balance value
assert!(game_cap.balance.value() > 0, ENotEarnBalance);
// withdraw all the balance
let all = game_cap.balance.withdraw_all();
transfer::public_transfer(coin::from_balance(all, ctx), game_cap.publisher_address);
}
entry fun withdraw(_: &Publisher, game_cap: &mut GameCap, ctx: &mut TxContext) {
withdraw_(game_cap, ctx);
}
entry
提现函数中用Publisher
来限制可调用的用户,public
提现函数用(package)
来限制只能由包内的其它模块调用,功能是当赚取到收益时体现到游戏发布者的钱包。
创建并共享TaskList
:
fun init(ctx: &mut TxContext) {
// create and transfer task list
let task_list = TaskList {
id: object::new(ctx),
task_ids: vector<ID>[],
tasks: table::new<ID, Task>(ctx),
};
transfer::share_object(task_list);
}
支付一定金额(不能低于最小值)来创建一个挑战任务,同时别忘了维护TaskList
:
entry fun create_task(task_list: &mut TaskList, mut coin: Coin<SUI>, amount: u64, ctx: &mut TxContext) {
// check the balance number
assert!(coin.value() >= amount && amount >= MinimumBonus, ENotEnoughBalance);
// split coin
let reward_coin = coin.split(amount, ctx);
let reward_balance = reward_coin.into_balance();
// deal with the remaining coin
if (coin.value() > 0) {
transfer::public_transfer(coin, ctx.sender());
} else {
coin.destroy_zero();
};
// generate ID
let id = object::id_from_address(ctx.fresh_object_address());
// create task
let task = Task {
in_task: 0,
total_attempts: 0,
reward: reward_balance,
earned: balance::zero(),
task_publisher_address: ctx.sender(),
};
// store it
task_list.task_ids.push_back(id);
task_list.tasks.add(id, task);
}
当有玩家完成任务时被调用,需要删除该任务相关的信息,以此来保证后续不再有人能够参与该任务,包括正在任务中的玩家再一次游戏时会被告知任务不存在,当然,对应的收益要按照游戏设计的规则发给对应的用户:
#[allow(lint(self_transfer))]
public fun complete_task(game_cap: &mut GameCap, task_id: ID, task_list: &mut TaskList, ctx: &mut TxContext) {
// get task_ids
let task_ids = &mut task_list.task_ids;
// get index
let (_, idx) = task_ids.index_of(&task_id);
// remove it
task_ids.remove(idx);
// remove and get task
let task = task_list.tasks.remove(task_id);
// get task details
let Task {
in_task: _,
total_attempts: _,
reward,
mut earned,
task_publisher_address,
} = task;
// player reward
transfer::public_transfer(coin::from_balance(reward, ctx), ctx.sender());
// package publisher earned
let amount = earned.value();
let publisher_earned = earned.split(amount / 3);
let publisher_balance = game_cap.borrow_balance_mut();
publisher_balance.join(publisher_earned);
// if the balance exceeds 10SUI then withdraw it
if (publisher_balance.value() >= 10000000000) {
game_cap.withdraw_(ctx);
};
// task publisher earned
transfer::public_transfer(coin::from_balance(earned, ctx), task_publisher_address);
}
开篇的#[allow(lint(self_transfer))]
是为了忽略一个警告,警告内容是函数中存在转移给自己的操作,经过分析判断,并没有什么逻辑上的问题,所以加这一句来忽略它。
当有玩家参加挑战时,挑战金额需要实时更新到对应的Task
当中,尤其需要关注的是Coin
如何根据游戏设计的规则进行拆分并存储:
#[allow(lint(self_transfer))]
public fun update(task: &mut Task, mut coin: Coin<SUI>, ctx: &mut TxContext) {
// get reward and earned
let reward = &mut task.reward;
let earned = &mut task.earned;
// check the coin value
let amount = reward.value() / 2;
assert!(coin.value() >= amount, ENotEnoughBalanceStart);
let mut pay_coin = coin.split(amount, ctx);
// deal with the remaining coin
if (coin.value() > 0) {
transfer::public_transfer(coin, ctx.sender());
} else {
coin.destroy_zero();
};
// update reward and earned
let earned_amount = amount / 2;
let earned_coin = pay_coin.split(earned_amount, ctx);
earned.join(earned_coin.into_balance());
reward.join(pay_coin.into_balance());
}
根据任务编号查询其相关信息:
entry fun query_task(task_id: ID, task_list: &TaskList) {
// check id
assert!(task_list.tasks.contains(task_id), ENotCorrectTaskOrCompleted);
// get task and emit event
let task = &task_list.tasks[task_id];
event::emit(QueryTaskEvent {
task_id,
in_task: task.in_task,
total_attempts: task.total_attempts,
cur_reward: task.reward.value(),
});
}
开启游戏(非挑战),只要支付的金额足够就可以启动游戏,对应的金额存储到GameCap
下,同时生成GameInfo
并将其所有权移交用户:
entry fun start_game(game_cap: &mut GameCap, mut coin: Coin<SUI>, ctx: &mut TxContext) {
// check the coin value
assert!(coin.value() >= MinimumStartBonus, ENotEnoughBalanceStart);
let pay_coin = coin.split(MinimumStartBonus, ctx);
// deal with the remaining coin
if (coin.value() > 0) {
transfer::public_transfer(coin, ctx.sender());
} else {
coin.destroy_zero();
};
// transfer the exact amount of coin
let publisher_balance = game_cap.borrow_balance_mut();
publisher_balance.join(pay_coin.into_balance());
// if the balance exceeds 10SUI then withdraw it
if (publisher_balance.value() >= 10000000000) {
game_cap.withdraw_(ctx);
};
// prepare the GameInfo's id and taskid(fake)
let id = object::new(ctx);
let task_id = id.uid_to_inner();
// create GameInfo
let game_info = GameInfo {
id,
task_id,
checkerboard: game::generate_empty_checkerboard(),
hash_code: vector<u8>[],
};
transfer::transfer(game_info, ctx.sender());
}
GameInfo
中的游戏区域是空的,包括地雷所在地的哈希码也是空的,这将在用户第一次尝试扫雷时生成。<br>因为链上一切都是公开的,若是一开始就将所有东西固定,连第一手的试错都没有,那还有人发布任务么? 还怎么收钱 <br>当然,在有了码之后可以根据代码中的地雷规则来自行开启上帝视角。 可能有了前端之后会有办法解决这个问题?
开启游戏(挑战任务),通过任务编号来确定想要挑战哪个人物,同时传入的参数Coin
余额必须足够,大体的代码任务与上面一致,不过别忘了维护Task
当中的两个数 —— 正在挑战的人数和尝试挑战的总人数:
entry fun start_task(task_id: ID, task_list: &mut TaskList, coin: Coin<SUI>, ctx: &mut TxContext) {
// check the task id
assert!(task_list.contains(task_id), ENotCorrectTaskOrCompleted);
// get task
let task = task_list.borrow_task_mut(task_id);
task.add_attempt();
// update reward and earned
task.update(coin, ctx);
// create GameInfo
let game_info = GameInfo {
id: object::new(ctx),
task_id,
checkerboard: game::generate_empty_checkerboard(),
hash_code: vector<u8>[],
};
transfer::transfer(game_info, ctx.sender());
}
扫雷(非挑战),通过传入的行、列,以及GameInfo
来进行游戏,如果是该局游戏第一次点击,那么会生成哈希码来对应地雷位置,接着通过一些列分支条件进行判断,对游戏区域进行更新,判定游戏成功与失败,大部分都是直接调用的game
模块的代码,这将在本文后续进行阐述:
entry fun game_click(mut r: u64, mut l: u64, mut game_info: GameInfo, ctx: &mut TxContext) {
// check the r and l
assert!(r >= 1 && r <= max_row() && l >= 1 && l <= max_list(), ENotCorrectRowOrList);
// change the r and l to satisfy subscript
r = r - 1;
l = l - 1;
// check the hash code
if (game_info.hash_code.length() == 0) {
let seed = ctx.epoch_timestamp_ms() % (l + r + 1);
game_info.hash_code = game::generate_hash(seed, ctx);
};
// get checkerboard and hash
let mut checkerboard = game_info.checkerboard;
let hash = game_info.hash_code;
// check click safe
if (game::confirm_safe(r, l, &hash)) {
// update checkerboard
game::dfs(r, l, &mut checkerboard, &hash);
// check success
if (game::success_clear(&checkerboard, &hash)) {
// emit event and destroy game info
game::success_emit(0, &checkerboard);
destroy_game_info(game_info);
} else {
// emit event and transfer game info for next click
game::emit(&checkerboard);
game_info.checkerboard = checkerboard;
transfer::transfer(game_info, ctx.sender());
};
} else {
// update checkerboard
let square = &mut checkerboard[r][l];
*square = char(b"x"[0]);
// emit and destroy game info
game::failure_emit(&checkerboard);
destroy_game_info(game_info);
};
}
扫雷(挑战任务),一旦挑战成功,将涉及金额转移,所以需要传入的参数比较多,但大体的代码思路与上面一致,区别的核心就是在适当的地方调用task
模块当中的完成任务的函数,同时维护好正在挑战的人数和尝试挑战的总人数,当然,别忘了在挑战一个已经完成的任务时触发事件通知,并销毁玩家手中已经没有任何作用了的GameInfo
:
entry fun game_click_task(game_cap: &mut GameCap, mut r: u64, mut l: u64, mut game_info: GameInfo, task_list: &mut TaskList, ctx: &mut TxContext) {
// check the task
if (!task_list.contains(game_info.task_id)) {
destroy_game_info(game_info);
event::emit(PlayTooLate {loser: string(b"The bounty mission has been completed!!!")});
return
};
// get the task
let task = task_list.borrow_task_mut(game_info.task_id);
// check the r and l
assert!(r >= 1 && r <= max_row() && l >= 1 && l <= max_list(), ENotCorrectRowOrList);
// change the r and l to satisfy subscript
r = r - 1;
l = l - 1;
// check the hash code
if (game_info.hash_code.length() == 0) {
let seed = task.as_seed();
game_info.hash_code = game::generate_hash(seed, ctx);
};
// get checkerboard and hash
let mut checkerboard = game_info.checkerboard;
let hash = game_info.hash_code;
// check click safe
if (game::confirm_safe(r, l, &hash)) {
// update checkerboard
game::dfs(r, l, &mut checkerboard, &hash);
// check success
if (game::success_clear(&checkerboard, &hash)) {
// emit event, complete task and destroy game info
game::success_emit(task.value(), &checkerboard);
task::complete_task(game_cap, game_info.task_id, task_list, ctx);
destroy_game_info(game_info);
} else {
// emit event and transfer game info for next click
game::emit(&checkerboard);
game_info.checkerboard = checkerboard;
transfer::transfer(game_info, ctx.sender());
};
} else {
// update checkerboard
let square = &mut checkerboard[r][l];
*square = char(b"x"[0]);
// update attempt, emit and destroy game info
task.failed_attempt();
game::failure_emit(&checkerboard);
destroy_game_info(game_info);
};
}
一系列触发事件,核心是将用来存储扫雷区域变化的一个个Char
合在一起转为String
方便玩家查阅: 如果有前端这就不是问题了吧
public fun emit(vec: &vector<vector<Char>>) {
// char => string
// for ease of reading
let mut checkerboard = vector<String>[];
let mut i = 0;
while (i < MaxRow) {
let mut row = string(b"");
let mut j = 0;
while (j < MaxList) {
row.push_char(vec[i][j]);
j = j + 1;
};
checkerboard.push_back(row);
i = i + 1;
};
event::emit(GameEvent {checkerboard});
}
public fun success_emit(reward: u64, vec: &vector<vector<Char>>) {
event::emit(GameSuccessEvent {reward});
emit(vec);
}
public fun failure_emit(vec: &vector<vector<Char>>) {
event::emit(GameOverEvent {loser: string(b"Game Over")});
emit(vec);
}
生成空的游戏区域,通过循环进行填充vector
:
public fun generate_empty_checkerboard(): vector<vector<Char>> {
let c = char(b"-"[0]);
// fill in_v in a loop
let mut i = 0;
let mut in_v = vector<Char>[];
while (i < MaxList) {
in_v.push_back(c);
i = i + 1;
};
// fill out_v in a loop
i = 0;
let mut out_v = vector<vector<Char>>[];
while (i < MaxRow) {
out_v.push_back(in_v);
i = i + 1;
};
// emit empty checkerboard and return
emit(&out_v);
out_v
}
通过hmac_sha3_256
函数来生成 $\text {32}$ 个u8
类型的数字,生成的内容与传入的两个参数相关,这里其中一个与上下文ctx
有关,应该可以确保每个人都不一致吧~
public fun generate_hash(seed: u64, ctx: &mut TxContext): vector<u8> {
hmac_sha3_256(&bcs::to_bytes(&seed), &ctx.fresh_object_address().to_bytes())
}
判断某一个格子是否安全,由哈希码决定:
public fun confirm_safe(r: u64, l: u64, hash: &vector<u8>): bool {
let pos = r * MaxList + l;
// pos % 30 + 1 => between 1 ~ 30
let byte = hash[pos % 30 + 1] as u64;
// unused is hash[0] and hash[31]
let p1 = hash[0] as u64;
let p2 = hash[31] as u64;
// + 2 to avoid divisor < 2
// divisor can't be 0
// if divisor = 1 then (0, 0) must be safe
(byte * p1 * p2) % (pos + 2) % 2 == 0
}
如果所有未点开的格子当中全是雷,那么游戏结束,玩家获得胜利:
public fun success_clear(checkerboard: &vector<vector<Char>>, hash: &vector<u8>): bool {
let mut i = 0;
while (i < MaxRow) {
let mut j = 0;
while (j < MaxList) {
if (checkerboard[i][j] == char(b"-"[0]) && confirm_safe(i, j, hash)) {
return false
};
j = j + 1;
};
i = i + 1;
};
return true
}
深度优先遍历,由玩家点击的方格进行深搜,每一个被掀开的格子都将计算其周围的地雷数量,如果没被任何一个地雷包围,则向四周扩散掀开格子,否则就此停下并显示对应数目:
#[allow(implicit_const_copy)]
public fun dfs(r: u64, l: u64, checkerboard: &mut vector<vector<Char>>, hash: &vector<u8>) {
// have be clicked
if (checkerboard[r][l] != char(b"-"[0])) {
return
};
// find mines in around
let mut cur_byte = b"0"[0];
let mut i = 0;
while (i <= 2) {
let mut j = 0;
while (j <= 2) {
let x = r + i;
let y = l + j;
// out of range
if (x <= 0 || x > MaxRow || y <= 0 || y > MaxList) {
j = j + 1;
continue
};
// add the mine number
if (!confirm_safe(x - 1, y - 1, hash)) {
cur_byte = cur_byte + 1;
};
j = j + 1;
};
i = i + 1;
};
// set checkerboard
let square = &mut checkerboard[r][l];
*square = char(cur_byte);
// have mines in around
if (cur_byte != b"0"[0]) {
return
};
// expand around
i = 0;
while (i < 4) {
let x = r + XDirection[i];
let y = l + YDirection[i];
// out of range
if (x <= 0 || x > MaxRow || y <= 0 || y > MaxList) {
i = i + 1;
continue
};
dfs(x - 1, y - 1, checkerboard, hash);
i = i + 1;
};
}
开篇的#[allow(implicit_const_copy)]
是为了忽略一个警告,警告内容是copy
了const
定义的常量vector
中的数值,这是为了方便处理上下左右四个方向是设立的,此警告对代码逻辑并无影响,选择忽略。
sui client publish --gas-budget 100000000
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x5e8923e7d955754ecfd4f1735dc671a494a92b5fba2cf2269fd61b9d740c825f │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 839131 │
│ │ Digest: 4cfE9XhJg6yuNe1AkrMm5LXGkGH3PfSCoyYPEdbatehL │
│ └── │
│ ┌── │
│ │ ObjectID: 0xd8bdf81c0b94c8eab5ddeaa3d856297e25395360950ea777f5ae5cd76cbbc032 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Shared │
│ │ ObjectType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::TaskList │
│ │ Version: 839131 │
│ │ Digest: DKUgMGQmfj94HXAhr5s1NoXuvJ71aDQXcxMXxNNGCp3q │
│ └── │
│ ┌── │
│ │ ObjectID: 0xe75fb50542e1d1d495845cc082b0cbe99121bdb5ece7b9d340069c3b7087e43c │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Shared │
│ │ ObjectType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::admin::GameCap │
│ │ Version: 839131 │
│ │ Digest: 3ePkN293EeiSMx3h8WBpKUHGm5oFWSRwS8M68hnQEa8w │
│ └── │
│ ┌── │
│ │ ObjectID: 0xfcdbfe8e54ab870eb238901c5d5eb4494a1fcab8a7c72d6c3e347b72df488f31 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::package::Publisher │
│ │ Version: 839131 │
│ │ Digest: 5SBanYYmE64uxFw6fRyqtkim3JzJUwGELYJhcPKK8MQB │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 839131 │
│ │ Digest: GvBuHNrnparwsq3avXBoMEABJQY7k9D65aJEfAnTRyyP │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Version: 1 │
│ │ Digest: HMbbdGMZcXreav7Suz4aAZBjPSVMt2yo7gwwXnVfoEM5 │
│ │ Modules: admin, game, player, task │
│ └── │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
export PACKAGE=0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86
export PUBLISHER=0xfcdbfe8e54ab870eb238901c5d5eb4494a1fcab8a7c72d6c3e347b72df488f31
export GAMECAP=0xe75fb50542e1d1d495845cc082b0cbe99121bdb5ece7b9d340069c3b7087e43c
export TASKLIST=0xd8bdf81c0b94c8eab5ddeaa3d856297e25395360950ea777f5ae5cd76cbbc032
sui client gas
# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 930529320 │ 0.93 │
│ 0x03335f68ff3616af7e000b113c56a5ad53e8e8209784ca0a5623f70997c8d948 │ 3282792690 │ 3.28 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
export ADMINCOIN=0x03335f68ff3616af7e000b113c56a5ad53e8e8209784ca0a5623f70997c8d948
sui client call --package $PACKAGE --module task --function create_task --args $TASKLIST $ADMINCOIN 100000000 --gas-budget 100000000
TaskList
sui client object $TASKLIST
# output:
╭───────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ objectId │ 0xd8bdf81c0b94c8eab5ddeaa3d856297e25395360950ea777f5ae5cd76cbbc032 │
│ version │ 28131891 │
│ digest │ 3YfR5zdpUn2igrtqwP5x2bpsGH6pyHDzvmyqPhi4nTFJ │
│ objType │ 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::TaskList │
│ owner │ ╭────────┬───────────────────────────────────────╮ │
│ │ │ Shared │ ╭────────────────────────┬──────────╮ │ │
│ │ │ │ │ initial_shared_version │ 839131 │ │ │
│ │ │ │ ╰────────────────────────┴──────────╯ │ │
│ │ ╰────────┴───────────────────────────────────────╯ │
│ prevTx │ 6ptp6UT43swa26iZoSrDTyELYYbwt9q766UAGmwDnUJx │
│ storageRebate │ 1839200 │
│ content │ ╭───────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ │ dataType │ moveObject │ │
│ │ │ type │ 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::TaskList │ │
│ │ │ hasPublicTransfer │ false │ │
│ │ │ fields │ ╭──────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │
│ │ │ │ │ id │ ╭────┬──────────────────────────────────────────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ id │ 0xd8bdf81c0b94c8eab5ddeaa3d856297e25395360950ea777f5ae5cd76cbbc032 │ │ │ │
│ │ │ │ │ │ ╰────┴──────────────────────────────────────────────────────────────────────╯ │ │ │
│ │ │ │ │ task_ids │ ╭──────────────────────────────────────────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ 0xd5e6b228ac08c7de1f6d3aba2a46d97997426a0f02e67d01d29e6d36ec060ad0 │ │ │ │
│ │ │ │ │ │ ╰──────────────────────────────────────────────────────────────────────╯ │ │ │
│ │ │ │ │ tasks │ ╭────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ type │ 0x2::table::Table<0x2::object::ID, 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::Task> │ │ │ │
│ │ │ │ │ │ │ fields │ ╭──────┬───────────────────────────────────────────────────────────────────────────────╮ │ │ │ │
│ │ │ │ │ │ │ │ │ id │ ╭────┬──────────────────────────────────────────────────────────────────────╮ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │ id │ 0xc85fcd5de0d40deb7177583f89b2b6319d0c569826fe1e0833225096c8acea85 │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ ╰────┴──────────────────────────────────────────────────────────────────────╯ │ │ │ │ │
│ │ │ │ │ │ │ │ │ size │ 1 │ │ │ │ │
│ │ │ │ │ │ │ │ ╰──────┴───────────────────────────────────────────────────────────────────────────────╯ │ │ │ │
│ │ │ │ │ │ ╰────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │
│ │ │ │ ╰──────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │
│ │ ╰───────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
task_id
export TASKID=0xd5e6b228ac08c7de1f6d3aba2a46d97997426a0f02e67d01d29e6d36ec060ad0
sui client call --package $PACKAGE --module task --function query_task --args $TASKID $TASKLIST --gas-budget 100000000
# import output:
╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: APe9owSN7Jq6rcLq4ZsZU4wcjv8UhbMusFV2RALxMseC:0 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: task │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::QueryTaskEvent │
│ │ ParsedJSON: │
│ │ ┌────────────────┬────────────────────────────────────────────────────────────────────┐ │
│ │ │ cur_reward │ 100000000 │ │
│ │ ├────────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ in_task │ 0 │ │
│ │ ├────────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ task_id │ 0xd5e6b228ac08c7de1f6d3aba2a46d97997426a0f02e67d01d29e6d36ec060ad0 │ │
│ │ ├────────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ total_attempts │ 0 │ │
│ │ └────────────────┴────────────────────────────────────────────────────────────────────┘ │
│ └── │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯
sui client switch --address <Your Address Alias>
Coin
sui client gas
# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x516586df0c5e9c9567696840981f720d64335ac6e8ad409f4ba4843b8dc2274a │ 100 │ 0.00 │
│ 0x82ec01655d746b42dba5c5951841472e5d1715e74238a5ef8e39d0b0566dc3be │ 996215577 │ 0.99 │
│ 0x8ef6503cb330c4114bc7995a403adf4015190d8effc02504fd849377caa6499b │ 963358100 │ 0.96 │
│ 0xad3fa2545f5db01bd4d349871df5af4d6de913600e7e3e032d5229c006d35851 │ 100 │ 0.00 │
│ 0xcb24b30fe196f4f2ca6d5f8d87a273bf168f7f86f6b7ae3f1f20fc5cf447e557 │ 990920960 │ 0.99 │
│ 0xe4f2d7831241583d534271d8d777d7558290124779e98e03b059a2fe108d37b0 │ 989 │ 0.00 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
export PLAYERCOIN=0xcb24b30fe196f4f2ca6d5f8d87a273bf168f7f86f6b7ae3f1f20fc5cf447e557
sui client call --package $PACKAGE --module player --function start_task --args $TASKID $TASKLIST $PLAYERCOIN --gas-budget 100000000
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: H1gc93rXVNqqcBw9ixSvYycw2cGqEHiaJoDvKRJotRkE:0 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: player │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::game::GameEvent │
│ │ ParsedJSON: │
│ │ ┌──────────────┬────────────┐ │
│ │ │ checkerboard │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ └──────────────┴────────────┘ │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x2359ffba7bbad6a1297a689973ab12be92aea5f6bc56ceb6e820057c9bc312c9 │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ Owner: Account Address ( 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b ) │
│ │ ObjectType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::player::GameInfo │
│ │ Version: 28131892 │
│ │ Digest: FiJNKn7F4tHPLjXqZ5CLe2TimgYopgVYcd5KQrGwwBpD │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x069127c1917ba074790e6bafc5d396fedb9ea2b082adbb0aa23a6aef2b1a1d52 │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ Owner: Object ID: ( 0xc85fcd5de0d40deb7177583f89b2b6319d0c569826fe1e0833225096c8acea85 ) │
│ │ ObjectType: 0x2::dynamic_field::Field<0x2::object::ID, 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::Task> │
│ │ Version: 28131892 │
│ │ Digest: 8Y2wyvyFYbaQ5csxsPRS9CgYjUz4L3gVaQ9zMHjEagWH │
│ └── │
│ ┌── │
│ │ ObjectID: 0x82ec01655d746b42dba5c5951841472e5d1715e74238a5ef8e39d0b0566dc3be │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ Owner: Account Address ( 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 28131892 │
│ │ Digest: DQZQbuQ2TwmrTVGWh6ePBtk3A1DXGdMHZTLUSQvu1Uh6 │
│ └── │
│ ┌── │
│ │ ObjectID: 0xcb24b30fe196f4f2ca6d5f8d87a273bf168f7f86f6b7ae3f1f20fc5cf447e557 │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ Owner: Account Address ( 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 28131892 │
│ │ Digest: 8RfS2pfuFQdXVa1tdPMmnPWwnnRD2te67uGYc9Wsn4Q5 │
│ └── │
│ ┌── │
│ │ ObjectID: 0xd8bdf81c0b94c8eab5ddeaa3d856297e25395360950ea777f5ae5cd76cbbc032 │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ Owner: Shared │
│ │ ObjectType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::TaskList │
│ │ Version: 28131892 │
│ │ Digest: BtVRqM9uXYRYwCpPf2oYfXrWv7o2UCdaHdRqXU7oqpie │
│ └── │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
GameInfo
export GAMEINFO=0x2359ffba7bbad6a1297a689973ab12be92aea5f6bc56ceb6e820057c9bc312c9
sui client call --package $PACKAGE --module player --function game_click_task --args $GAMECAP 3 5 $GAMEINFO $TASKLIST --gas-budget 100000000
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: A3iF7tcE28cPzfhQFCBt1aBYXnkF9cEAcPdQAwoMkT1G:0 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: player │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::game::GameEvent │
│ │ ParsedJSON: │
│ │ ┌──────────────┬────────────┐ │
│ │ │ checkerboard │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ----3----- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ └──────────────┴────────────┘ │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
sui client call --package $PACKAGE --module player --function game_click_task --args $GAMECAP 2 9 $GAMEINFO $TASKLIST --gas-budget 100000000
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: BTgdBFY619JsUoq2EQvxjs3bMhmgzR5bpNkpg6QoXVNc:0 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: player │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::game::GameEvent │
│ │ ParsedJSON: │
│ │ ┌──────────────┬────────────┐ │
│ │ │ checkerboard │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ --------3- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ----3----- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ └──────────────┴────────────┘ │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├───────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: FecsgeihJicnn7n1A9CEmwCj97HDwtyS1zzgzbiWNjRS:0 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: player │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::game::GameOverEvent │
│ │ ParsedJSON: │
│ │ ┌───────┬───────────┐ │
│ │ │ loser │ Game Over │ │
│ │ └───────┴───────────┘ │
│ └── │
│ ┌── │
│ │ EventID: FecsgeihJicnn7n1A9CEmwCj97HDwtyS1zzgzbiWNjRS:1 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: player │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::game::GameEvent │
│ │ ParsedJSON: │
│ │ ┌──────────────┬────────────┐ │
│ │ │ checkerboard │ 00002----- │ │
│ │ │ ├────────────┤ │
│ │ │ │ 1121----3- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ----3----- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------- │ │
│ │ │ ├────────────┤ │
│ │ │ │ ---------x │ │
│ │ └──────────────┴────────────┘ │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯
sui client call --package $PACKAGE --module task --function query_task --args $TASKID $TASKLIST --gas-budget 100000000
# output:
╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: BbXxmWmZJjCgB5MfbwDYZCv2X66gRgV54h4L9HuKNB89:0 │
│ │ PackageID: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86 │
│ │ Transaction Module: task │
│ │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b │
│ │ EventType: 0x2b772f60f0794e23718d47ea32b9d61eb29b79dc45f026e31985575b8edd5a86::task::QueryTaskEvent │
│ │ ParsedJSON: │
│ │ ┌────────────────┬────────────────────────────────────────────────────────────────────┐ │
│ │ │ cur_reward │ 125000000 │ │
│ │ ├────────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ in_task │ 0 │ │
│ │ ├────────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ task_id │ 0xd5e6b228ac08c7de1f6d3aba2a46d97997426a0f02e67d01d29e6d36ec060ad0 │ │
│ │ ├────────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ total_attempts │ 1 │ │
│ │ └────────────────┴────────────────────────────────────────────────────────────────────┘ │
│ └── │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯
用开启普通游戏给GameCap
送 $\text {666}$( 绝对不是扫雷太难了才不做任务 ),通过命令提现并查看余额,当然,提现的时候要切换到发布者账户,否则会报错:
sui client call --package $PACKAGE --module admin --function withdraw --args $PUBLISHER $GAMECAP --gas-budget 100000000
sui client gas
# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 923479812 │ 0.92 │
│ 0x03335f68ff3616af7e000b113c56a5ad53e8e8209784ca0a5623f70997c8d948 │ 3182792690 │ 3.18 │
│ 0xf0d1ea4828fe7391b41b2b07cc8c4c5fd1831aee6b6a4e5195b236dea20fbde4 │ 666 │ 0.00 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
由于篇幅有限,且其它大部分逻辑都是类似的,这里就不再赘述了,大家可以自行体验。
上面的内容发布在测试网($\mathit {testnet}$),据说一般不会清理这上面的内容,所以大家可以尽情游玩,如果想要实际的资产收入,下面列举了在主网发布的相关信息。
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x013207a4563b3cd4f5571210c6137b88e6b49632c55e1f973273a89bd394189a │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Shared │
│ │ ObjectType: 0x61fae5877c2d1a8005850bdcc4f7af8e9db748bd8934fd267cb962b0a2682cea::task::TaskList │
│ │ Version: 93823811 │
│ │ Digest: bn9MjEfoPmQF5dzQ8x4hqYfDSXdzQhaFGEB4Bj9TVun │
│ └── │
│ ┌── │
│ │ ObjectID: 0x4149443de1b23dbe2d3ff3af3e4386d21b702fe0e9b98c6da328a779c8bc3b64 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::package::Publisher │
│ │ Version: 93823811 │
│ │ Digest: 4185sDwsbBUfqwH7UdNRNgeUV3UYcXxeacDbgRxMDPuG │
│ └── │
│ ┌── │
│ │ ObjectID: 0x4f4b954324e48fa3dfcce7fc9122b8b8f2529161d900d603d58dfbba697ad2b9 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Shared │
│ │ ObjectType: 0x61fae5877c2d1a8005850bdcc4f7af8e9db748bd8934fd267cb962b0a2682cea::admin::GameCap │
│ │ Version: 93823811 │
│ │ Digest: 89MaCQUw3fQi2Mk3XDmesieAiiAg6hheZBPVTT7qxzFf │
│ └── │
│ ┌── │
│ │ ObjectID: 0x7d138d46e14b53065ea2b81118a13a9d5328bc3e7fefbb21a61ba33bc85ef33c │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 93823811 │
│ │ Digest: 2mdqWWJ6rSEksAakRtrvqbjAXVRUKRDLuy4GWndpXyNY │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x5bd3822d01aa5aff68b8079b8a0f41563d423d8f5993daaddf338533a0735ab5 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 93823811 │
│ │ Digest: 3XrAe2vgxnVzhtm4QCErADLLgx5wyYXFtM3J9bxsEYT5 │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0x61fae5877c2d1a8005850bdcc4f7af8e9db748bd8934fd267cb962b0a2682cea │
│ │ Version: 1 │
│ │ Digest: Et5czEYSphmx1ZiBhhmYUASbuXvc3WWVDh7Md662q4Xq │
│ │ Modules: admin, game, player, task │
│ └── │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
export PACKAGE=0x61fae5877c2d1a8005850bdcc4f7af8e9db748bd8934fd267cb962b0a2682cea
export UPGRADECAP=0x7d138d46e14b53065ea2b81118a13a9d5328bc3e7fefbb21a61ba33bc85ef33c
export PUBLISHER=0x4149443de1b23dbe2d3ff3af3e4386d21b702fe0e9b98c6da328a779c8bc3b64
export GAMECAP=0x4f4b954324e48fa3dfcce7fc9122b8b8f2529161d900d603d58dfbba697ad2b9
export TASKLIST=0x013207a4563b3cd4f5571210c6137b88e6b49632c55e1f973273a89bd394189a
欢迎大家来主网玩,完整的代码也可以点击这里查看。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!