Aspect用例: 全链游戏的链上自动化NPC

Artela中文博客
9 min readJan 17, 2024

--

我们通过Aspect,给Artela上的全链游戏添加了一个全链NPC!在这个全链游戏世界里,玩家可以把账号注册为一个会自动化的NPC玩家,根据算法自动参与到与其他真实玩家的对战里!

下图展示的这个游戏里,玩家控制209号角色,而24号玩家则是全链NPC,没有off-chain组件控制,在Royale世界里与真实玩家一起对战。

本文我们会介绍下Artela的Aspect如何与全链游戏擦出不一样的火花!会详细介绍Aspect哪些特性适合全链游戏,可以实现什么样的有趣全链功能,以及上面这个游戏是如何通过Aspect完成开发!

Features for fully on-chain game

我们与许多全链游戏开发者做了交流,总结了Asepct一些可以让全链游戏变得更好的特性,这里介绍其中两个最受关注的特性:just-in-time call与高性能wasm计算。

Just-in-time call

JIT(Just-in-time) Call指在Aspect运行过程中,它可以动态发起对evm里智能合约的调用(call),实现在链上transaction执行过程中插入即时交易的效果。

JIT Call使得智能合约拥有在链上自动化执行的能力,使合约可以实时地动态决策是否要执行额外的流程。

原理如下图,transaction会cal智能合约执行,合约执行的前后都有join point会触发Aspect执行。图里展示了有一个Aspect在合约的call执行之后,它动态签署了一笔transaction,这笔transaction会在下一个call执行前立即执行。由于链上没有私钥可以签署transaction,因此JIT Call通过底层的AA Wallet模块发起交易。

在全链游戏中,它使得游戏合约拥有自动化能力,因此游戏合约可以去自动执行系统任务!比如每隔50个区块,游戏世界里的地图、天气、怪物、buff等可以自动刷新;比如当player击杀了boss后,身边的小怪会自动消亡、宝箱会开启;比如NPC玩家会随着player的事件自动进行移动等!

以上这些场景的实现它不需要修改游戏合约,只需要添加Aspect,在游戏合约的执行前后动态判断玩家的操作,游戏其他实体的变动,然后发起JIT Call去操控这些自动化实体!Aspect甚至和AI-agent结合,让玩家不在线时,角色依然可以自动成长。

高性能wasm虚拟机

全链游戏如果设计自主生命,最大的调整就是链上的计算量!比如游戏世界里有一千个玩家,每个玩家在每个区块里面都自动更新成长数据的话,evm中需要执行1000遍玩家成长数据计算,这是不太现实的做法。

在Artela上,Aspect运行wasm虚拟机中,而智能合约运行在evm中,wasm虚拟机的执行效率是evm的1~2个数量级,如果设计得当,充分利用Aspect wasm runtime特性,它可以很好得完成批量计算和更新的操作,使得链上自主世界的生命可以周期性在链上自动更新!

Real Case: support NPC for Royale

想法有了,那我们就来实现它实操一遍吧!

我们与BladeDAO进行了合作,针对Royale这款在线PvP游戏集成Aspect并利用JIT Call,使得Royale里具有自动化的NPC角色与玩家互动。

这个想法来自于我想去玩Royale时,由于时间点不对,苦等不到与我对战的玩家!Royale目前的实现里,需要玩家创建房间,每个房间要等待其他玩家加入后才能开始。而我在线操作了许久还进不去游戏。

于是我的想法是,给Royale添加一批NPC角色,即时没有玩家进入房间,当我点击开始的时候,会有NPC自动进来房间与我对战。这个NPC和我一样都是Royale的player角色,都由wallet控制,角色属性都相同,唯一不同的是它有Aspect管理,而我是由我的EoA控制。

经过改造后,这个JIT Royale游戏出来了!在JIT Royale里,玩家会自动进入一个房间,这个房间里如果没有其他玩家或者其他玩家不移动,则Aspect则会操控它的角色进来与我对战!因此我可以随时随地战斗了!

Aspect Design

我设计了这么一个Aspect,它有两个主要流程

  • Register palyer

在Aspect上,把wallet注册为由Aspect控制的玩家,Aspect会根据算法自动提这些wallet发起JIT Call。

  • join point at pre-contract call

每笔调用Royale合约的transaction都会在合约执行前触发Aspect,Aspect判断如果这笔tx调用的是玩家的move方法,那么它将会使用register player发起move调用,控制NPC移动。


<tx:call move>
|
| _ _ _ _ _ _ _ _ _ _ _
| | |
|--pre_contract_call--> | JIT Aspect | <------- <tx:register player>
| | |
| _ _ _ _ _ _ _ _ _ _ _
| |
v |
----------------- | <tx:call move>
| | |
| Royale |<-------------
| contract |
| |
-----------------

Implements

这个Aspect的核心方法如下,这段代码展示了join point的执行逻辑。

它会判断本次contract call的calldata,解析出当前call的method。如果method的值 move(uint8) 的哈希值,那么它就会去获取 sysPlayers ,并去发起move调用 this.doMove(sysPlayers[i], input);

preContractCall(input: PreContractCallInput): void {

let calldata = uint8ArrayToHex(input.call!.data);
let method = this.parseCallMethod(calldata);

// if method is 'move(uint8)'
if (method == "0x70e87aaf") {
let currentCaller = uint8ArrayToHex(input.call!.from);
let sysPlayers = this.getSysPlayersList();
let isSysPlayer = sysPlayers.includes(this.rmPrefix(currentCaller).toLowerCase());

// if player moves, sys players also move just-in-time
if (!isSysPlayer) {
// do jit-call
for (let i = 0; i < sysPlayers.length; ++i) {
this.doMove(sysPlayers[i], input);
}
} else {
// if sys player moves, do nothing in Aspect and pass the join point
return;
}
}
}

doMove 这个方法里,会发起JIT Call,它首先会随机选择一个移动方向,然后构造calldata。

使用JitCallBuilder 构建一个JIT Call请求,通过 sys.hostApi.evmCall.jitCall(request) 发起JIT Call,这是个同步请求,它会在这个call结束后才返回,也就是角色在Royale游戏合约移动后返回。


doMove(sysPlayer: string, input: PreContractCallInput): void {
// init jit call
let direction = this.getRandomDirection(input);

let moveCalldata = ethereum.abiEncode('move', [
ethereum.Number.fromU8(direction, 8)
]);

// Construct a JIT request (similar to the user operation defined in EIP-4337)
let request = JitCallBuilder.simple(hexToUint8Array(sysPlayer),
input.call!.to,
hexToUint8Array(moveCalldata)
).build();

// Submit the JIT call
let response = sys.hostApi.evmCall.jitCall(request);

// Verify successful submission of the call
sys.require(response.success, `Failed to submit the JIT call: ${sysPlayer}, err: ${response.errorMsg}, ret: ${uint8ArrayToString(response.ret)}`);
}

More than NPC

以上就是一个支持链上NPC的全链游戏从想法,到设计,到实现的全过程。

Aspect不仅能带来自动化、高性能计算,同时它还可以给AW带来可组合性!以上Royale的例子里,加入NPC的过程我们没有修改Royale游戏合约,也就是说对于Royale游戏合约而言,无论是玩家控制的,还是Aspect控制的,都是同一类玩家,Aspect是动态添加上去。

换句话说,autonomous world游戏还可以通过社区治理,一步步地动态添加模块,完善这个世界的玩法、规则,这会是一个可组合的世界!

End

欢迎来体验这个JIT Royale:地址。同时也欢迎对Artela和Aspect编程感兴趣的全链游戏开发者关注与联系我们,一起打造更丰富的autonomous world!

--

--