-
Notifications
You must be signed in to change notification settings - Fork 0
Content Loading #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Content Loading #12
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import type Activity from '../content-types/activity'; | ||
| import Article from '../content-types/article'; | ||
| import ContentLoader from './content-loader'; | ||
|
|
||
| class ContentLibrary { | ||
| loader: ContentLoader; | ||
| articles: Map<string, Article> = new Map<string, Article>(); | ||
| activities: Map<string, Activity> = new Map<string, Activity>(); | ||
|
|
||
| getArticle(id: string) { | ||
| return this.articles.get(id); | ||
| } | ||
|
|
||
| getActivity(id: string) { | ||
| return this.activities.get(id); | ||
| } | ||
|
|
||
| async initialize() { | ||
| const articles = await this.loader.loadArticles(); | ||
| articles.forEach((article) => { | ||
| this.articles.set(article.id, article); | ||
| }); | ||
| const activities = await this.loader.loadActivities(); | ||
| activities.forEach((activity) => { | ||
| this.activities.set(activity.id, activity); | ||
| }); | ||
| } | ||
|
|
||
| constructor() { | ||
| this.loader = new ContentLoader(); | ||
| } | ||
| } | ||
|
|
||
| export default ContentLibrary; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import Activity from '../content-types/activity'; | ||
| import Article from '../content-types/article'; | ||
| const loadedActivities = import.meta.glob('../content/activities/*', { eager: true }); | ||
| const loadedArticles = import.meta.glob('../content/articles/*', { eager: true }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since even a small game can have 100+ assets, I didn't want to specify each one individually. I also didn't want a single file per content type, since some content types might be large. This pattern is what I came up with to allow for dynamic discovery and loading of files, although as a result I had to cheat a bit on the types. |
||
| import.meta.glob('../scripts/*', { eager: true }); | ||
|
|
||
| class ContentLoader { | ||
| async loadArticles(): Promise<Article[]> { | ||
| const articles: Article[] = []; | ||
| Object.entries(loadedArticles).forEach(([, definition]) => { | ||
| const article = (definition as Record<string, Article>).default; | ||
| articles.push(article); | ||
| }); | ||
| return articles; | ||
| } | ||
|
|
||
| async loadActivities(): Promise<Activity[]> { | ||
| const activities: Activity[] = []; | ||
| for (let i = 0; i < Object.entries(loadedActivities).length; i++) { | ||
| const module: [string, unknown] = Object.entries(loadedActivities)[i]; | ||
| const rawActivity = (module[1] as Record<string, Activity>).default; | ||
| const importedScript = await import(rawActivity.scriptPath as string); | ||
| rawActivity.apply = importedScript.default; | ||
| activities.push(rawActivity); | ||
| } | ||
| return activities; | ||
| } | ||
|
|
||
| constructor() {} | ||
| } | ||
|
|
||
| export default ContentLoader; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,16 @@ | ||
| import BaseContentType from './base-content'; | ||
| import UIData from './ui-data'; | ||
|
|
||
| // An activity is a way for players to spend time in between each month of gameplay. | ||
| // e.g. leisure, studying, working | ||
| class Activity extends BaseContentType { | ||
| // Run any state changing effects of the activity. | ||
| apply: (/* player */) => void; | ||
| apply: (/* player */) => void = () => { | ||
| console.log('warning: apply not set on activity with id ' + this.id); | ||
| return; | ||
| }; | ||
|
|
||
| constructor(id: string, uiData: UIData, applyFunction: () => void) { | ||
| super(id, uiData); | ||
| this.apply = applyFunction; | ||
| } | ||
| // for deserialization purposes | ||
| scriptPath: string = ''; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I'm thinking of to attach scripts. There are some pros and cons to this approach, but it lets us take advantage of TypeScript. It's a fairly common approach in engines, although we'll have fewer bells and whistles than say, Godot. |
||
| } | ||
|
|
||
| export default Activity; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "id": "test-activity", | ||
| "scriptPath": "../scripts/test-activity", | ||
| "uiData": { | ||
| "description": "an activity for testing", | ||
| "name": "test activity" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "id": "test-article", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These files are under /src, which is probably not ideal. I tried /content with no success. I could also see /static/content, though I'm not sure what ramifications that has. This feels like an "I don't know which config to change, and haven't figured it out yet." |
||
| "uiData": { | ||
| "description": "an article for testing", | ||
| "name": "test article" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| const testFunction = function () { | ||
| console.log('test successful'); | ||
| }; | ||
|
|
||
| export default testFunction; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are for testing purposes (although they might also be useful in general.) I imagine this interface will grow a bit larger, e.g.
getAllActivities().