ecs.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. import { expect } from "chai";
  2. import {
  3. anchor,
  4. web3,
  5. FindComponentPda,
  6. FindComponentProgramDataPda,
  7. FindEntityPda,
  8. SerializeArgs,
  9. } from "../../clients/bolt-sdk/lib";
  10. import { Direction } from "../framework";
  11. export function ecs(framework) {
  12. describe("ECS", () => {
  13. it("Add entity 1", async () => {
  14. const world = await framework.worldProgram.account.world.fetch(
  15. framework.worldPda,
  16. );
  17. framework.entity1Pda = FindEntityPda({
  18. worldId: world.id,
  19. entityId: world.entities,
  20. });
  21. const instruction = await framework.worldProgram.methods
  22. .addEntity(null)
  23. .accounts({
  24. payer: framework.provider.wallet.publicKey,
  25. world: framework.worldPda,
  26. entity: framework.entity1Pda,
  27. })
  28. .instruction();
  29. const transaction = new anchor.web3.Transaction().add(instruction);
  30. await framework.provider.sendAndConfirm(transaction);
  31. });
  32. it("Add entity 2", async () => {
  33. const world = await framework.worldProgram.account.world.fetch(
  34. framework.worldPda,
  35. );
  36. framework.entity2Pda = FindEntityPda({
  37. worldId: world.id,
  38. entityId: world.entities,
  39. });
  40. const instruction = await framework.worldProgram.methods
  41. .addEntity(null)
  42. .accounts({
  43. payer: framework.provider.wallet.publicKey,
  44. world: framework.worldPda,
  45. entity: framework.entity2Pda,
  46. })
  47. .instruction();
  48. const transaction = new anchor.web3.Transaction().add(instruction);
  49. await framework.provider.sendAndConfirm(transaction);
  50. });
  51. it("Add entity 3", async () => {
  52. const world = await framework.worldProgram.account.world.fetch(
  53. framework.worldPda,
  54. );
  55. const entity3Pda = FindEntityPda({
  56. worldId: world.id,
  57. entityId: world.entities,
  58. });
  59. const instruction = await framework.worldProgram.methods
  60. .addEntity(null)
  61. .accounts({
  62. payer: framework.provider.wallet.publicKey,
  63. world: framework.worldPda,
  64. entity: entity3Pda,
  65. })
  66. .instruction();
  67. const transaction = new anchor.web3.Transaction().add(instruction);
  68. await framework.provider.sendAndConfirm(transaction);
  69. });
  70. it("Add entity 4 (with seed)", async () => {
  71. const world = await framework.worldProgram.account.world.fetch(
  72. framework.worldPda,
  73. );
  74. const seed = Buffer.from("custom-seed");
  75. framework.entity4Pda = FindEntityPda({ worldId: world.id, seed });
  76. const instruction = await framework.worldProgram.methods
  77. .addEntity(seed)
  78. .accounts({
  79. payer: framework.provider.wallet.publicKey,
  80. world: framework.worldPda,
  81. entity: framework.entity4Pda,
  82. })
  83. .instruction();
  84. const transaction = new anchor.web3.Transaction().add(instruction);
  85. await framework.provider.sendAndConfirm(transaction);
  86. });
  87. it("Initialize Velocity Component on Entity 1 (with seed)", async () => {
  88. const componentId = framework.exampleComponentVelocity.programId;
  89. framework.componentVelocityEntity1Pda = FindComponentPda({
  90. componentId,
  91. entity: framework.entity1Pda,
  92. seed: "component-velocity",
  93. });
  94. const instruction = await framework.worldProgram.methods
  95. .initializeComponent()
  96. .accounts({
  97. payer: framework.provider.wallet.publicKey,
  98. entity: framework.entity1Pda,
  99. data: framework.componentVelocityEntity1Pda,
  100. componentProgram: componentId,
  101. authority: framework.provider.wallet.publicKey,
  102. })
  103. .instruction();
  104. const transaction = new anchor.web3.Transaction().add(instruction);
  105. await framework.provider.sendAndConfirm(transaction);
  106. });
  107. it("Initialize Position Component on Entity 1", async () => {
  108. const componentId = framework.exampleComponentPosition.programId;
  109. framework.componentPositionEntity1Pda = FindComponentPda({
  110. componentId,
  111. entity: framework.entity1Pda,
  112. });
  113. const instruction = await framework.worldProgram.methods
  114. .initializeComponent()
  115. .accounts({
  116. payer: framework.provider.wallet.publicKey,
  117. entity: framework.entity1Pda,
  118. data: framework.componentPositionEntity1Pda,
  119. componentProgram: componentId,
  120. authority: framework.worldProgram.programId,
  121. })
  122. .instruction();
  123. const transaction = new anchor.web3.Transaction().add(instruction);
  124. await framework.provider.sendAndConfirm(transaction);
  125. });
  126. it("Initialize Position Component on Entity 2", async () => {
  127. const componentId = framework.exampleComponentPosition.programId;
  128. const componentPda = FindComponentPda({
  129. componentId,
  130. entity: framework.entity2Pda,
  131. });
  132. const instruction = await framework.worldProgram.methods
  133. .initializeComponent()
  134. .accounts({
  135. payer: framework.provider.wallet.publicKey,
  136. entity: framework.entity2Pda,
  137. data: componentPda,
  138. componentProgram: componentId,
  139. authority: framework.worldProgram.programId,
  140. })
  141. .instruction();
  142. const transaction = new anchor.web3.Transaction().add(instruction);
  143. await framework.provider.sendAndConfirm(transaction);
  144. });
  145. it("Initialize Position Component on Entity 4", async () => {
  146. const componentId = framework.exampleComponentPosition.programId;
  147. framework.componentPositionEntity4Pda = FindComponentPda({
  148. componentId,
  149. entity: framework.entity4Pda,
  150. });
  151. const instruction = await framework.worldProgram.methods
  152. .initializeComponent()
  153. .accounts({
  154. payer: framework.provider.wallet.publicKey,
  155. entity: framework.entity4Pda,
  156. data: framework.componentPositionEntity4Pda,
  157. componentProgram: componentId,
  158. authority: framework.worldProgram.programId,
  159. })
  160. .instruction();
  161. const transaction = new anchor.web3.Transaction().add(instruction);
  162. await framework.provider.sendAndConfirm(transaction);
  163. });
  164. it("Check Position on Entity 1 is default", async () => {
  165. const position =
  166. await framework.exampleComponentPosition.account.position.fetch(
  167. framework.componentPositionEntity1Pda,
  168. );
  169. expect(position.x.toNumber()).to.equal(0);
  170. expect(position.y.toNumber()).to.equal(0);
  171. expect(position.z.toNumber()).to.equal(0);
  172. });
  173. it("Apply Simple Movement System (Up) on Entity 1", async () => {
  174. const instruction = await framework.worldProgram.methods
  175. .apply(SerializeArgs({ direction: Direction.Up }))
  176. .accounts({
  177. authority: framework.provider.wallet.publicKey,
  178. boltSystem: framework.systemSimpleMovement.programId,
  179. world: framework.worldPda,
  180. })
  181. .remainingAccounts([
  182. {
  183. pubkey: framework.exampleComponentPosition.programId,
  184. isSigner: false,
  185. isWritable: false,
  186. },
  187. {
  188. pubkey: framework.componentPositionEntity1Pda,
  189. isSigner: false,
  190. isWritable: true,
  191. },
  192. ])
  193. .instruction();
  194. const transaction = new anchor.web3.Transaction().add(instruction);
  195. await framework.provider.sendAndConfirm(transaction);
  196. const position =
  197. await framework.exampleComponentPosition.account.position.fetch(
  198. framework.componentPositionEntity1Pda,
  199. );
  200. expect(position.x.toNumber()).to.equal(0);
  201. expect(position.y.toNumber()).to.equal(1);
  202. expect(position.z.toNumber()).to.equal(0);
  203. });
  204. it("Apply Simple Movement System (Right) on Entity 1", async () => {
  205. const instruction = await framework.worldProgram.methods
  206. .apply(SerializeArgs({ direction: Direction.Right }))
  207. .accounts({
  208. authority: framework.provider.wallet.publicKey,
  209. boltSystem: framework.systemSimpleMovement.programId,
  210. world: framework.worldPda,
  211. })
  212. .remainingAccounts([
  213. {
  214. pubkey: framework.exampleComponentPosition.programId,
  215. isSigner: false,
  216. isWritable: false,
  217. },
  218. {
  219. pubkey: framework.componentPositionEntity1Pda,
  220. isSigner: false,
  221. isWritable: true,
  222. },
  223. ])
  224. .instruction();
  225. const transaction = new anchor.web3.Transaction().add(instruction);
  226. await framework.provider.sendAndConfirm(transaction);
  227. const position =
  228. await framework.exampleComponentPosition.account.position.fetch(
  229. framework.componentPositionEntity1Pda,
  230. );
  231. expect(position.x.toNumber()).to.equal(1);
  232. expect(position.y.toNumber()).to.equal(1);
  233. expect(position.z.toNumber()).to.equal(0);
  234. });
  235. it("Apply Fly System on Entity 1", async () => {
  236. const instruction = await framework.worldProgram.methods
  237. .apply(SerializeArgs())
  238. .accounts({
  239. authority: framework.provider.wallet.publicKey,
  240. boltSystem: framework.systemFly.programId,
  241. world: framework.worldPda,
  242. })
  243. .remainingAccounts([
  244. {
  245. pubkey: framework.exampleComponentPosition.programId,
  246. isSigner: false,
  247. isWritable: false,
  248. },
  249. {
  250. pubkey: framework.componentPositionEntity1Pda,
  251. isSigner: false,
  252. isWritable: true,
  253. },
  254. ])
  255. .instruction();
  256. const transaction = new anchor.web3.Transaction().add(instruction);
  257. await framework.provider.sendAndConfirm(transaction);
  258. const position =
  259. await framework.exampleComponentPosition.account.position.fetch(
  260. framework.componentPositionEntity1Pda,
  261. );
  262. expect(position.x.toNumber()).to.equal(1);
  263. expect(position.y.toNumber()).to.equal(1);
  264. expect(position.z.toNumber()).to.equal(1);
  265. });
  266. it("Apply System Velocity on Entity 1", async () => {
  267. const instruction = await framework.worldProgram.methods
  268. .apply(SerializeArgs())
  269. .accounts({
  270. authority: framework.provider.wallet.publicKey,
  271. boltSystem: framework.systemApplyVelocity.programId,
  272. world: framework.worldPda,
  273. })
  274. .remainingAccounts([
  275. {
  276. pubkey: framework.exampleComponentVelocity.programId,
  277. isSigner: false,
  278. isWritable: false,
  279. },
  280. {
  281. pubkey: framework.componentVelocityEntity1Pda,
  282. isSigner: false,
  283. isWritable: true,
  284. },
  285. {
  286. pubkey: framework.exampleComponentPosition.programId,
  287. isSigner: false,
  288. isWritable: false,
  289. },
  290. {
  291. pubkey: framework.componentPositionEntity1Pda,
  292. isSigner: false,
  293. isWritable: true,
  294. },
  295. ])
  296. .instruction();
  297. const transaction = new anchor.web3.Transaction().add(instruction);
  298. await framework.provider.sendAndConfirm(transaction);
  299. const velocity =
  300. await framework.exampleComponentVelocity.account.velocity.fetch(
  301. framework.componentVelocityEntity1Pda,
  302. );
  303. expect(velocity.x.toNumber()).to.equal(10);
  304. expect(velocity.y.toNumber()).to.equal(0);
  305. expect(velocity.z.toNumber()).to.equal(0);
  306. expect(velocity.lastApplied.toNumber()).to.not.equal(0);
  307. const position =
  308. await framework.exampleComponentPosition.account.position.fetch(
  309. framework.componentPositionEntity1Pda,
  310. );
  311. expect(position.x.toNumber()).to.greaterThan(1);
  312. expect(position.y.toNumber()).to.equal(1);
  313. expect(position.z.toNumber()).to.equal(1);
  314. });
  315. it("Apply System Velocity on Entity 1, with Clock external account", async () => {
  316. const instruction = await framework.worldProgram.methods
  317. .apply(SerializeArgs())
  318. .accounts({
  319. authority: framework.provider.wallet.publicKey,
  320. boltSystem: framework.systemApplyVelocity.programId,
  321. world: framework.worldPda,
  322. })
  323. .remainingAccounts([
  324. {
  325. pubkey: framework.exampleComponentVelocity.programId,
  326. isSigner: false,
  327. isWritable: false,
  328. },
  329. {
  330. pubkey: framework.componentVelocityEntity1Pda,
  331. isSigner: false,
  332. isWritable: true,
  333. },
  334. {
  335. pubkey: framework.exampleComponentPosition.programId,
  336. isSigner: false,
  337. isWritable: false,
  338. },
  339. {
  340. pubkey: framework.componentPositionEntity1Pda,
  341. isSigner: false,
  342. isWritable: true,
  343. },
  344. {
  345. pubkey: framework.worldProgram.programId, // world program ID is the end of components delimiter
  346. isSigner: false,
  347. isWritable: false,
  348. },
  349. {
  350. pubkey: new web3.PublicKey(
  351. "SysvarC1ock11111111111111111111111111111111",
  352. ),
  353. isWritable: false,
  354. isSigner: false,
  355. },
  356. ])
  357. .instruction();
  358. const transaction = new anchor.web3.Transaction().add(instruction);
  359. await framework.provider.sendAndConfirm(transaction);
  360. const position =
  361. await framework.exampleComponentPosition.account.position.fetch(
  362. framework.componentPositionEntity1Pda,
  363. );
  364. expect(position.x.toNumber()).to.greaterThan(1);
  365. expect(position.y.toNumber()).to.equal(1);
  366. expect(position.z.toNumber()).to.equal(300);
  367. });
  368. it("Apply Fly System on Entity 4", async () => {
  369. const instruction = await framework.worldProgram.methods
  370. .apply(SerializeArgs())
  371. .accounts({
  372. authority: framework.provider.wallet.publicKey,
  373. boltSystem: framework.systemFly.programId,
  374. world: framework.worldPda,
  375. })
  376. .remainingAccounts([
  377. {
  378. pubkey: framework.exampleComponentPosition.programId,
  379. isSigner: false,
  380. isWritable: false,
  381. },
  382. {
  383. pubkey: framework.componentPositionEntity4Pda,
  384. isSigner: false,
  385. isWritable: true,
  386. },
  387. ])
  388. .instruction();
  389. const transaction = new anchor.web3.Transaction().add(instruction);
  390. await framework.provider.sendAndConfirm(transaction);
  391. const position =
  392. await framework.exampleComponentPosition.account.position.fetch(
  393. framework.componentPositionEntity4Pda,
  394. );
  395. expect(position.x.toNumber()).to.equal(0);
  396. expect(position.y.toNumber()).to.equal(0);
  397. expect(position.z.toNumber()).to.equal(1);
  398. });
  399. it("Destroy Velocity Component on Entity 1", async () => {
  400. const keypair = web3.Keypair.generate();
  401. let componentBalance = await framework.provider.connection.getBalance(
  402. framework.componentVelocityEntity1Pda,
  403. );
  404. const componentProgramData = FindComponentProgramDataPda({
  405. programId: framework.exampleComponentVelocity.programId,
  406. });
  407. const instruction = await framework.worldProgram.methods
  408. .destroyComponent()
  409. .accounts({
  410. authority: framework.provider.wallet.publicKey,
  411. componentProgram: framework.exampleComponentVelocity.programId,
  412. entity: framework.entity1Pda,
  413. component: framework.componentVelocityEntity1Pda,
  414. componentProgramData: componentProgramData,
  415. receiver: keypair.publicKey,
  416. })
  417. .instruction();
  418. const transaction = new anchor.web3.Transaction().add(instruction);
  419. await framework.provider.sendAndConfirm(transaction);
  420. const balance = await framework.provider.connection.getBalance(
  421. keypair.publicKey,
  422. );
  423. expect(balance).to.equal(componentBalance);
  424. });
  425. });
  426. }