Skip to content

Commit

Permalink
Resource Pack Exporter
Browse files Browse the repository at this point in the history
- Improved dev debugging by adding `sourceRoot: true` to esbuild `buildDev()` options.
- Removed unused `CustomModelData` class.
- Fixed some weird incorrect `.png` extensions.
- Fixed `rigRenderer.ts` failing to export any textures on variant models.
- Completed the first mostly-functional build of the resource pack compiling systems.
- Made `exportRig()` crash-safe.
- Made `exportRig()` actually respect the "export data pack" and "export resource pack" blueprint settings.
- Removed left-over `scoreboards.ts` file.
- Made some small fixes to the data pack compiler.
- Removed redundant try catch statement from data pack compiler.
- Added `saveBlueprint()` function to `blueprintFormat.ts`
- Renamed internal variables for `root_entity_summon_commands` to `custom_summon_commands` to match the user-facing naming.
- Added some proper default values to some blueprint settings.
- Added `Project.last_used_export_namespace` to keep track of previous exports, and clean up old files a little better.
-
  • Loading branch information
SnaveSutit committed Apr 21, 2024
1 parent 9aec632 commit 3500327
Show file tree
Hide file tree
Showing 16 changed files with 400 additions and 175 deletions.
3 changes: 2 additions & 1 deletion src/blockbenchTypeMods.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ declare global {
enable_data_pack: boolean
enable_advanced_data_pack_settings: boolean
data_pack: string
root_entity_summon_commands: string
custom_summon_commands: string
}
last_used_export_namespace: string

variants: Variant[]
}
Expand Down
12 changes: 12 additions & 0 deletions src/blueprintFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export interface IBlueprintFormatJSON {
box_uv: boolean
backup: boolean
save_location: string
last_used_export_namespace: string
}
/**
* The project settings of the Blueprint
Expand Down Expand Up @@ -174,6 +175,9 @@ export const BLUEPRINT_CODEC = new Blockbench.Codec('animated_java_blueprint', {
Project.animated_java = { ...Project.animated_java, ...model.project_settings }
}

Project.last_used_export_namespace =
model.meta.last_used_export_namespace || Project.animated_java.export_namespace

if (model.textures) {
for (const texture of model.textures) {
const newTexture = new Texture(texture, texture.uuid).add(false)
Expand Down Expand Up @@ -301,6 +305,7 @@ export const BLUEPRINT_CODEC = new Blockbench.Codec('animated_java_blueprint', {
format_version: PACKAGE.version,
uuid: Project.uuid,
save_location: Project.save_path,
last_used_export_namespace: Project.last_used_export_namespace,
},
project_settings: Project.animated_java,
resolution: {
Expand Down Expand Up @@ -446,6 +451,7 @@ export const BLUEPRINT_FORMAT = new Blockbench.ModelFormat({
}

Project.variants ??= []
Project.last_used_export_namespace = Project.animated_java.export_namespace
if (newModel) {
new Variant('Default', true)
}
Expand Down Expand Up @@ -508,3 +514,9 @@ BLUEPRINT_CODEC.format = BLUEPRINT_FORMAT
export function isCurrentFormat() {
return Format.id === BLUEPRINT_FORMAT.id
}

export function saveBlueprint() {
if (!Project || !Format) return
if (Format !== BLUEPRINT_FORMAT) return
BLUEPRINT_CODEC.write(BLUEPRINT_CODEC.compile(), Project.save_path)
}
6 changes: 3 additions & 3 deletions src/blueprintSettings.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export const defaultValues: ModelProject['animated_java'] = {
export_namespace: '',
export_namespace: 'blueprint',
// Plugin Settings
enable_plugin_mode: false,
// Resource Pack Settings
enable_resource_pack: true,
display_item: '',
display_item: 'minecraft:white_dye',
customModelDataOffset: 0,
enable_advanced_resource_pack_settings: false,
resource_pack: '',
Expand All @@ -15,5 +15,5 @@ export const defaultValues: ModelProject['animated_java'] = {
enable_data_pack: true,
enable_advanced_data_pack_settings: false,
data_pack: '',
root_entity_summon_commands: '',
custom_summon_commands: '',
}
6 changes: 2 additions & 4 deletions src/components/blueprintSettingsDialog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,8 @@
/>
{/if}
<CodeInput
label={translate('dialog.blueprint_settings.root_entity_summon_commands.title')}
tooltip={translate(
'dialog.blueprint_settings.root_entity_summon_commands.description',
)}
label={translate('dialog.blueprint_settings.custom_summon_commands.title')}
tooltip={translate('dialog.blueprint_settings.custom_summon_commands.description')}
bind:value={rootEntitySummonCommands}
/>
{/if}
Expand Down
4 changes: 2 additions & 2 deletions src/interface/blueprintSettingsDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function getSettings(): Record<string, Valuable<any>> {
Project!.animated_java.enable_advanced_data_pack_settings
),
dataPack: new Valuable(Project!.animated_java.data_pack),
rootEntitySummonCommands: new Valuable(Project!.animated_java.root_entity_summon_commands),
rootEntitySummonCommands: new Valuable(Project!.animated_java.custom_summon_commands),
}
}

Expand All @@ -94,7 +94,7 @@ function setSettings(settings: any) {
Project.animated_java.enable_advanced_data_pack_settings =
settings.enableAdvancedDataPackSettings.get()
Project.animated_java.data_pack = settings.dataPack.get()
Project.animated_java.root_entity_summon_commands = settings.rootEntitySummonCommands.get()
Project.animated_java.custom_summon_commands = settings.rootEntitySummonCommands.get()
console.log('Successfully saved project settings', Project)
}

Expand Down
4 changes: 2 additions & 2 deletions src/lang/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ animated_java.dialog.blueprint_settings.data_pack.error.not_a_folder: The select
animated_java.dialog.blueprint_settings.data_pack.error.missing_pack_mcmeta: The selected folder is missing a pack.mcmeta file!
animated_java.dialog.blueprint_settings.data_pack.error.missing_data_folder: The selected Data Pack is missing a data folder!

animated_java.dialog.blueprint_settings.root_entity_summon_commands.title: Custom On-Summon Commands
animated_java.dialog.blueprint_settings.root_entity_summon_commands.description: Commands to run as the root entity when summoned. Treat this text input as a normal mcfunction.
animated_java.dialog.blueprint_settings.custom_summon_commands.title: Custom On-Summon Commands
animated_java.dialog.blueprint_settings.custom_summon_commands.description: Commands to run as the root entity when summoned. Treat this text input as a normal mcfunction.

## Bone Config Dialog
animated_java.dialog.bone_config.title: Bone Config
Expand Down
4 changes: 2 additions & 2 deletions src/mods/saveProjectActionMod.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BLUEPRINT_CODEC, BLUEPRINT_FORMAT } from '../blueprintFormat'
import { BLUEPRINT_FORMAT, saveBlueprint } from '../blueprintFormat'
import { PACKAGE } from '../constants'
import { createBlockbenchMod } from '../util/moddingTools'

Expand All @@ -12,7 +12,7 @@ createBlockbenchMod(
context.action.click = (event: Event) => {
if (!Project || !Format) return
if (Format === BLUEPRINT_FORMAT) {
BLUEPRINT_CODEC.write(BLUEPRINT_CODEC.compile(), Project.save_path)
saveBlueprint()
} else {
context.originalClick.call(context.action, event)
}
Expand Down
70 changes: 34 additions & 36 deletions src/systems/datapackCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Compiler, Parser, Tokenizer, SyncIo } from 'mc-build'
import { VariableMap } from 'mc-build/dist/mcl/Compiler'
import { isFunctionTagPath } from '../util/fileUtil'
import datapackTemplate from './datapackCompiler/animated_java.mcb'
import { openUnexpectedErrorDialog } from '../interface/unexpectedErrorDialog'
import { IRenderedNodes, IRenderedRig } from './rigRenderer'
import { IRenderedAnimation } from './animationRenderer'
import { Variant } from '../variants'
Expand Down Expand Up @@ -183,41 +182,40 @@ function createCustomSyncIO(): SyncIo {
return io
}

export function compileDataPack(rig: IRenderedRig, animations: IRenderedAnimation[]) {
try {
console.log('Compiling Data Pack...')
const compiler = new Compiler('src/', {
libDir: null,
generatedDirName: 'zzz',
internalScoreboardName: 'aj.i',
eqVarScoreboardName: null,
eqConstScoreboardName: null,
header: '# This file was generated by Animated Java via MC-Build. It is not recommended to edit this file directly.',
ioThreadCount: null,
setup: null,
})
compiler.io = createCustomSyncIO()
compiler.disableRequire = true

const variables = {
export_namespace: Project!.animated_java.export_namespace,
rig,
animations,
variants: Variant.all,
export_version: Math.random().toString().substring(2, 12),
root_entity_passengers: generateRootEntityPassengers(rig),
TAGS,
}
export function compileDataPack(options: { rig: IRenderedRig; animations: IRenderedAnimation[] }) {
const { rig, animations } = options
console.log('Compiling Data Pack...')
const compiler = new Compiler('src/', {
libDir: null,
generatedDirName: 'zzz',
internalScoreboardName: 'aj.i',
eqVarScoreboardName: null,
eqConstScoreboardName: null,
header: '# This file was generated by Animated Java via MC-Build. It is not recommended to edit this file directly.',
ioThreadCount: null,
setup: null,
})
compiler.io = createCustomSyncIO()
compiler.disableRequire = true

console.time('Data Pack Compilation')
compiler.addFile(
'src/animated_java.mcb',
Parser.parseMcbFile(Tokenizer.tokenize(datapackTemplate, 'src/animated_java.mcb'))
)
compiler.compile(VariableMap.fromObject(variables))
console.timeEnd('Data Pack Compilation')
} catch (e: any) {
openUnexpectedErrorDialog(e as Error)
console.error(e)
const aj = Project!.animated_java

const variables = {
export_namespace: aj.export_namespace,
rig,
animations,
variants: Variant.all,
export_version: Math.random().toString().substring(2, 10),
root_entity_passengers: generateRootEntityPassengers(rig),
TAGS,
custom_summon_commands: aj.custom_summon_commands,
}

console.time('Data Pack Compilation')
compiler.addFile(
'src/animated_java.mcb',
Parser.parseMcbFile(Tokenizer.tokenize(datapackTemplate, 'src/animated_java.mcb'))
)
compiler.compile(VariableMap.fromObject(variables))
console.timeEnd('Data Pack Compilation')
}
63 changes: 35 additions & 28 deletions src/systems/datapackCompiler/animated_java.mcb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ dir global {
scoreboard objectives add aj.frame dummy
scoreboard objectives add aj.rig_is_loaded dummy

scoreboard players set aj.true aj.i 1
scoreboard players set aj.false aj.i 0
scoreboard players set aj.1b aj.i 1
scoreboard players set aj.0b aj.i 0
scoreboard players add aj.last_id aj.id 0

scoreboard players reset * aj.rig_is_loaded
Expand Down Expand Up @@ -54,7 +54,19 @@ dir global {
dir errors {
function function_not_executed_as_root_entity {
# Make this text fancier in the actual implementation.
$tellraw @a 'The function $(function_path) must be executed as the root entity of the rig.'
$tellraw @a "The function $(function_path) must be executed as the root entity of the rig."
}
}

dir remove {
# Removes all instances of all rigs from the world.
function everything {
# Args: {confirm: boolean}
$execute if score aj.$(confirm) aj.i matches 0 run tellraw @a "Are you sure you want to remove all Animated Java rigs from the world? Run this command again with {confirm:true} to confirm."
$execute if score aj.$(confirm) aj.i matches 1 run {
kill @e[type=item_display,tag=aj.rig_entity]
tellraw @a "All Animated Java rigs have been removed from the world."
}
}
}
}
Expand Down Expand Up @@ -143,54 +155,54 @@ dir <%export_namespace%> {
function play {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/play'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/play'}
tag @s add aj.<%export_namespace%>.animation.<%animation.name%>.playing
}
function stop {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/stop'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/stop'}
tag @s remove aj.<%export_namespace%>.animation.<%animation.name%>.playing
}
function pause {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/pause'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/pause'}
tag @s remove aj.<%export_namespace%>.animation.<%animation.name%>.playing
}
function resume {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/resume'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/resume'}
tag @s add aj.<%export_namespace%>.animation.<%animation.name%>.playing
}
function reset {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/reset'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/reset'}
tag @s remove aj.<%export_namespace%>.animation.<%animation.name%>.playing
}
function next_frame {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/next_frame'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/next_frame'}
}
function apply_frame {
# ARGS: {frame: int}
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/apply_frame'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/apply_frame'}
}
function tween_play {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/tween_play'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/tween_play'}
tag @s add aj.<%export_namespace%>.animation.<%animation.name%>.tween_playing
}
function tween_resume {
execute unless entity @s[type=item_display,tag=aj.root_entity] run return run \
function *global/errors/function_not_executed_as_root_entity \
with {'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/tween_resume'}
{'function_path': 'animated_java:<%export_namespace%>/animations/<%animation.name%>/tween_resume'}
tag @s add aj.<%export_namespace%>.animation.<%animation.name%>.tween_playing
}
dir zzz {
Expand All @@ -215,38 +227,42 @@ dir <%export_namespace%> {
execute store result score @s aj.id run scoreboard players add aj.last_id aj.id 1
tag @s remove aj.new

data set value aj:temp args set value {variant:'', animation:'', frame: 0}
data modify storage aj:temp args set value {variant:'', animation:'', frame: 0}
$execute store success score #success aj.i run data modify storage aj:temp args set value $(args)

# Variant Arguement
execute if data storage aj:temp args.variant run {
execute if data storage aj:temp {args:{variant:''}} run return run tellraw @a 'The variant argument cannot be an empty string.'
execute if data storage aj:temp {args:{variant:''}} run return run tellraw @a "The variant argument cannot be an empty string."
# Attempt to apply the variant, if it fails, print an error.
execute store success score #success aj.i run { with storage aj:temp args
$execute store success score #success aj.i run function *<%export_namespace%>/variants/$(variant)/apply
execute if score #success aj.i matches 1 run return 1
return fail
}
$execute unless score #success aj.i matches 1 run return run tellraw @a 'The variant $(variant) does not exist.'
$execute unless score #success aj.i matches 1 run return run tellraw @a "The variant $(variant) does not exist."
}

# Animation, Frame, and Start Animation Arguments
execute if data storage aj:temp args.animation run {
execute if data storage aj:temp {args:{animation:''}} run return run tellraw @a 'The animation argument cannot be an empty string.'
execute if data storage aj:temp {args:{animation:''}} run return run tellraw @a "The animation argument cannot be an empty string."
execute store result score #frame aj.i run data get storage aj:temp args.frame
execute if score #frame aj.i matches ..-1 run return run tellraw @a 'The frame argument must be a non-negative integer.'
execute if score #frame aj.i matches ..-1 run return run tellraw @a "The frame argument must be a non-negative integer."
execute store result storage aj:temp args.frame int 1 run scoreboard players get #frame aj.i
# Attempt to apply the animation frame, if it fails, print an error.
execute store success score #success aj.i run { with storage aj:temp args
$execute store success score #success aj.i run function *<%export_namespace%>/animations/$(animation)/apply_frame {frame: $(frame)}
execute if score #success aj.i matches 1 run return 1
return fail
}
$execute unless score #success aj.i matches 1 run return run tellraw @a 'The animation $(animation) does not exist.'
$execute unless score #success aj.i matches 1 run return run tellraw @a "The animation $(animation) does not exist."
execute if data storage aj:temp {args:{start_animation: true}} run { with storage aj:temp args
$function *<%export_namespace%>/animations/$(animation)/resume
}
}
# Custom Summon Commands
<%custom_summon_commands%>
# Custom Summon Commands

# Run the on_summon function for the root entity.
function #*<%export_namespace%>/as_root/on_summon
}
Expand Down Expand Up @@ -274,15 +290,6 @@ dir <%export_namespace%> {
execute on passengers run kill @s
kill @s
}
# Removes all instances of all rigs from the world.
function everything {
# Args: {confirm: boolean}
$execute if score aj.$(confirm) aj.i matches 0 run tellraw @a 'Are you sure you want to remove all Animated Java rigs from the world? Run this command again with {confirm:true} to confirm.'
$execute if score aj.$(confirm) aj.i matches 1 run {
kill @e[type=item_display,tag=aj.rig_entity]
tellraw @a 'All Animated Java rigs have been removed from the world.'
}
}
}

dir variants {
Expand Down Expand Up @@ -312,7 +319,7 @@ dir <%export_namespace%> {

dir zzz {
function check_if_rig_outdated {
execute unless score @s aj.<%export_version%> matches <%export_version%> run function #animated_java:<%export_namespace%>/zzz/update_outdated_rig
execute unless score @s aj.export_version matches <%export_version%> run function #animated_java:<%export_namespace%>/zzz/update_outdated_rig
}

function update_outdated_rig {
Expand Down
Loading

0 comments on commit 3500327

Please sign in to comment.