@occultus/article-api 0.23.0-alpha.1 → 0.24.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@occultus/article-api",
3
- "version": "0.23.0-alpha.1",
3
+ "version": "0.24.0-beta.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://codeberg.org/TeamOccultus/StarTenonAPI"
@@ -24,10 +24,10 @@
24
24
  "license": "MIT",
25
25
  "author": "CTN Studios",
26
26
  "dependencies": {
27
- "@occultus/text-api": "0.23.0"
27
+ "@occultus/text-api": "0.24.0"
28
28
  },
29
29
  "peerDependencies": {
30
- "@occultus/core": "1.1.0-rc.1",
30
+ "@occultus/core": "^1.1.0",
31
31
  "@minecraft/server": "^2.4.0",
32
32
  "@minecraft/server-ui": "^2.0.0"
33
33
  },
@@ -4,7 +4,7 @@ import { ArticleRegistries } from "./Base/ArticleRegistries";
4
4
  import { Article } from "./Article";
5
5
  import { generateContentForm } from "../lib/utils";
6
6
  import { TextProvider } from "@occultus/text-api";
7
- import { FormLike } from "@occultus/core";
7
+ import { FormLike, OccultusCore, OccultusSDKError } from "@occultus/core";
8
8
  import { ReadableArticle } from "../types/ReadableArticle";
9
9
 
10
10
  /**
@@ -38,8 +38,8 @@ export class ArticleCenter extends FormLike {
38
38
  public readonly id: string,
39
39
  public title: TextProvider,
40
40
  public body: TextProvider,
41
- public articles: Article[] | boolean,
42
- public readonly bindTo: ArticleRegistries,
41
+ public articles: ReadableArticle[] | boolean,
42
+ public readonly bindTo?: ArticleRegistries,
43
43
  public iconPath?: string
44
44
  ) {
45
45
  super();
@@ -79,6 +79,11 @@ export class ArticleCenter extends FormLike {
79
79
  private getAvailableArticles(): ReadableArticle[] {
80
80
  if (typeof this.articles === "boolean") {
81
81
  if (!this.articles) return [];
82
+ if (!this.bindTo) {
83
+ throw new OccultusSDKError(
84
+ "You must bind article registries to the center when using the boolean parameter!"
85
+ );
86
+ }
82
87
  return this.bindTo.getAll();
83
88
  }
84
89
  return this.articles;
@@ -0,0 +1,182 @@
1
+ import { ItemStack, RawMessage, StartupEvent, system } from "@minecraft/server";
2
+ import { ArticleBindingConfig } from "./BindingConfig";
3
+ import { OccultusSDKError } from "@occultus/core";
4
+ import { parseText, TextProvider } from "@occultus/text-api";
5
+ import { ChapterData } from "../../interface/ChapterData";
6
+ import { ReadableArticle } from "../../types/ReadableArticle";
7
+ import { Article } from "../Article";
8
+ import {
9
+ ArticleCenterComponentParams,
10
+ ArticleComponentParams,
11
+ ArticleContentParams
12
+ } from "./ComponentParams";
13
+ import { ArticleCenter } from "../ArticleCenter";
14
+
15
+ /**
16
+ * 文章内容类型别名
17
+ */
18
+ type ArticleContent =
19
+ | TextProvider
20
+ | { chapter: ChapterData[]; description: TextProvider };
21
+
22
+ export class ArticleServerBindings {
23
+ private static instance: ArticleServerBindings | undefined;
24
+ private static center: ArticleCenter | undefined;
25
+ private preloadedContent: Map<string, ArticleContent> = new Map();
26
+ private articles: Map<string, ReadableArticle> = new Map();
27
+ /**
28
+ * 获取文章的内容
29
+ * @param item
30
+ * @param config
31
+ * @returns
32
+ */
33
+ private getArticleContent(item: ItemStack, config: ArticleBindingConfig) {
34
+ const params = item.getComponent(config.contentComponentName)
35
+ ?.customComponentParameters.params as ArticleContentParams;
36
+ if (!params) return;
37
+ if (typeof params === "string") {
38
+ return this.preloadedContent.get(params);
39
+ }
40
+ return params;
41
+ }
42
+ private parseDescription(text: ArticleContent | RawMessage[]): TextProvider {
43
+ if (typeof text === "string") return text;
44
+ if (Array.isArray(text)) {
45
+ return {
46
+ rawtext: text
47
+ };
48
+ }
49
+ if ("description" in text) {
50
+ return text.description;
51
+ }
52
+ return text;
53
+ }
54
+ private registryArticleComponent(
55
+ event: StartupEvent,
56
+ config: ArticleBindingConfig
57
+ ) {
58
+ const self = this;
59
+ event.itemComponentRegistry.registerCustomComponent(config.componentName, {
60
+ onUse(event, componentParams) {
61
+ const { itemStack, source } = event;
62
+ const params = componentParams.params as ArticleComponentParams;
63
+ if (!itemStack) return;
64
+ // 该文章已经被注册
65
+ if (self.articles.has(itemStack.typeId)) {
66
+ self.articles.get(itemStack.typeId)?.display(source, []);
67
+ return;
68
+ }
69
+ // 该文章没有被注册,先注册一下
70
+ const content = self.getArticleContent(itemStack, config);
71
+ let article: ReadableArticle;
72
+ if (!content) return;
73
+ if (typeof content !== "string" && "chapter" in content) {
74
+ article = new Article(
75
+ itemStack.typeId,
76
+ params.title,
77
+ content.description,
78
+ content.chapter,
79
+ params.icon_path
80
+ );
81
+ self.articles.set(itemStack.typeId, article);
82
+ article.display(source, []);
83
+ return;
84
+ }
85
+ article = new Article(
86
+ itemStack.typeId,
87
+ params.title,
88
+ self.parseDescription(content),
89
+ undefined,
90
+ params.icon_path
91
+ );
92
+ self.articles.set(itemStack.typeId, article);
93
+ article.display(source, []);
94
+ }
95
+ });
96
+ }
97
+ private registryArticleContentComponent(
98
+ event: StartupEvent,
99
+ config: ArticleBindingConfig
100
+ ) {
101
+ event.itemComponentRegistry.registerCustomComponent(
102
+ config.contentComponentName,
103
+ {}
104
+ );
105
+ }
106
+ private registryArticleCenterContent(
107
+ event: StartupEvent,
108
+ config: ArticleBindingConfig
109
+ ) {
110
+ const self = this;
111
+ event.itemComponentRegistry.registerCustomComponent(
112
+ config.centerComponentName,
113
+ {
114
+ onUse(event, componentParams) {
115
+ const { itemStack, source } = event;
116
+ const params = componentParams.params as ArticleCenterComponentParams;
117
+ if (!itemStack) return;
118
+ const center = ArticleServerBindings.center;
119
+ if (!center) {
120
+ const newCenter = new ArticleCenter(
121
+ itemStack.typeId,
122
+ params.title,
123
+ params.description,
124
+ Array.from(self.articles.values()),
125
+ undefined,
126
+ params.icon_path
127
+ );
128
+ ArticleServerBindings.center = newCenter;
129
+ newCenter.display(source, []);
130
+ return;
131
+ }
132
+ center.display(source, []);
133
+ }
134
+ }
135
+ );
136
+ }
137
+ private constructor(public config: ArticleBindingConfig) {
138
+ if (!config) {
139
+ throw new OccultusSDKError("ArticleBindingConfig is required!");
140
+ }
141
+ system.beforeEvents.startup.subscribe((event) => {
142
+ this.registryArticleComponent(event, config);
143
+ this.registryArticleContentComponent(event, config);
144
+ this.registryArticleCenterContent(event, config);
145
+ });
146
+ }
147
+ static create(config: ArticleBindingConfig): void {
148
+ if (ArticleServerBindings.instance) {
149
+ throw new OccultusSDKError("ArticleServerBindings already created!");
150
+ }
151
+ ArticleServerBindings.instance = new ArticleServerBindings(config);
152
+ }
153
+ static getInstance(): ArticleServerBindings {
154
+ if (!ArticleServerBindings.instance) {
155
+ throw new OccultusSDKError("ArticleServerBindings not created!");
156
+ }
157
+ return ArticleServerBindings.instance;
158
+ }
159
+ static getCenter(): ArticleCenter {
160
+ if (!ArticleServerBindings.center) {
161
+ throw new OccultusSDKError("ArticleCenter not found!");
162
+ }
163
+ return ArticleServerBindings.center;
164
+ }
165
+ /**
166
+ * 预载文章内容
167
+ * @param id
168
+ * @param content
169
+ */
170
+ preloadContent(
171
+ id: string,
172
+ content:
173
+ | TextProvider
174
+ | { chapter: ChapterData[]; description: TextProvider }
175
+ ) {
176
+ if (!id || !content) {
177
+ console.warn(`Preload data failed with id: ${id}`);
178
+ return;
179
+ }
180
+ this.preloadedContent.set(id, content);
181
+ }
182
+ }
@@ -0,0 +1,5 @@
1
+ export type ArticleBindingConfig = {
2
+ componentName: string;
3
+ centerComponentName: string;
4
+ contentComponentName: string;
5
+ };
@@ -0,0 +1,14 @@
1
+ import { RawMessage } from "@minecraft/server";
2
+
3
+ export type ArticleComponentParams = {
4
+ title: RawMessage | string;
5
+ icon_path?: string;
6
+ };
7
+
8
+ export type ArticleContentParams = RawMessage[] | string;
9
+
10
+ export type ArticleCenterComponentParams = {
11
+ title: RawMessage | string;
12
+ description: RawMessage | string;
13
+ icon_path?: string;
14
+ };
package/src/index.ts CHANGED
@@ -6,3 +6,6 @@ export * from "./api/Article";
6
6
  export * from "./api/ArticleCenter";
7
7
  export * from "./api/Base/ArticleRegistries";
8
8
  export * from "./interface/ChapterData";
9
+ export * from "./api/Bindings/ArticleServerBindings";
10
+ export * from "./api/Bindings/BindingConfig";
11
+ export * from "./api/Bindings/ComponentParams";