Merge branch 'gamma-delta:main' into main

This commit is contained in:
Uriadov Aleksey 2022-05-09 01:02:34 +00:00 committed by GitHub
commit e83a25f03d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
224 changed files with 3667 additions and 1668 deletions

View file

@ -4,4 +4,5 @@ A minecraft mod about casting Hexes, powerful and programmable magical effects,
[Curseforge Link](https://www.curseforge.com/minecraft/mc-mods/hexcasting)
This mod requires Patchouli and Kotlin for Forge!
This mod requires PAUCAL, Patchouli and Kotlin for Forge!

View file

@ -1,4 +1,5 @@
buildscript {
ext.kotlin_version = '1.6.21'
repositories {
// These repositories are only for Gradle plugins, put any other repositories in the repository block further below
maven { url = 'https://maven.minecraftforge.net' }
@ -15,6 +16,7 @@ buildscript {
}
}
import com.diluv.schoomp.Webhook
import com.diluv.schoomp.message.Message
@ -26,9 +28,10 @@ apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.parchmentmc.librarian.forgegradle'
apply plugin: 'org.spongepowered.mixin'
version = '0.8.0'
group = 'at.petra-k.hexcasting' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'hexcasting-1.18.2'
version = modVersion
group = "at.petra-k.$modID" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "$modID-$minecraftVersion"
def isRelease = { ->
try {
@ -82,25 +85,12 @@ apply plugin: 'kotlinx-serialization'
// If you already know how to add the Kotlin plugin to Gradle, this is the only line you need for KFF
apply from: 'https://raw.githubusercontent.com/thedarkcolour/KotlinForForge/site/thedarkcolour/kotlinforforge/gradle/kff-3.0.0.gradle'
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
minecraft {
// The mappings can be changed at any time and must be in the following format.
// Channel: Version:
// snapshot YYYYMMDD Snapshot are built nightly.
// stable # Stables are built at the discretion of the MCP team.
// official MCVersion Official field/method names from Mojang mapping files
//
// You must be aware of the Mojang license when using the 'official' mappings.
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
//
// Use non-default mappings at your own risk. They may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: 'parchment', version: '2022.03.13-1.18.2'
// After running this the first time, switch which is commented and rerun genIntellijRuns
mappings channel: 'official', version: '1.18.2'
// mappings channel: 'parchment', version: '2022.03.13-1.18.2'
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default.
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
client {
workingDirectory project.file('run')
@ -117,12 +107,11 @@ minecraft {
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
// unbreak patchi??
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', modID
mods {
hexcasting {
create(modID) {
source sourceSets.main
}
}
@ -131,29 +120,24 @@ minecraft {
server {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', modID
mods {
hexcasting {
create(modID) {
source sourceSets.main
}
}
}
data {
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
@ -168,14 +152,28 @@ minecraft {
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'hexcasting', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', modID
mods {
hexcasting {
create(modID) {
source sourceSets.main
}
}
}
data {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', modID, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
mods {
create(modID) {
source sourceSets.main
}
}
@ -186,6 +184,13 @@ minecraft {
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
mixin {
add sourceSets.main, "${modID}.mixins.refmap.json"
config "${modID}.mixins.json"
dumpTargetOnFailure true
}
repositories {
mavenCentral()
// Put repositories for dependencies here
@ -215,42 +220,30 @@ dependencies {
// Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed
// that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.18.2-40.0.19'
minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}"
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
compileOnly fg.deobf("vazkii.patchouli:Patchouli:1.18.2-66:api")
runtimeOnly fg.deobf("vazkii.patchouli:Patchouli:1.18.2-66")
compileOnly fg.deobf("at.petra-k.paucal:paucal-$minecraftVersion:$paucalVersion")
runtimeOnly fg.deobf("at.petra-k.paucal:paucal-$minecraftVersion:$paucalVersion")
compileOnly fg.deobf("vazkii.patchouli:Patchouli:$minecraftVersion-$patchouliVersion:api")
runtimeOnly fg.deobf("vazkii.patchouli:Patchouli:$minecraftVersion-$patchouliVersion")
// compile against the JEI API but do not include it at runtime
compileOnly fg.deobf("mezz.jei:jei-1.18.2:9.5.3.143:api")
// at runtime, use the full JEI jar
runtimeOnly fg.deobf("mezz.jei:jei-1.18.2:9.5.3.143")
compileOnly fg.deobf("at.petra-k.paucal:paucal-1.18.2:0.3.2")
runtimeOnly fg.deobf("at.petra-k.paucal:paucal-1.18.2:0.3.2")
}
mixin {
add sourceSets.main, 'hexcasting.mixins.refmap.json'
config 'hexcasting.mixins.json'
dumpTargetOnFailure true
}
java {
withJavadocJar()
withSourcesJar()
compileOnly fg.deobf("mezz.jei:jei-$minecraftVersion:$jeiVersion:api")
runtimeOnly fg.deobf("mezz.jei:jei-$minecraftVersion:$jeiVersion")
}
// Example for how to get properties into the manifest for reading at runtime.
jar {
manifest {
attributes([
"Specification-Title" : "hexcasting",
"Specification-Vendor" : "petrak-at",
"Specification-Title" : modID,
"Specification-Vendor" : "petra-kat",
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.jar.archiveVersion,
"Implementation-Vendor" : "petrak-at",
"Implementation-Vendor" : "petra-kat",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
@ -262,12 +255,10 @@ jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
// publish.dependsOn('reobfJar')
// Disables Gradle's custom module metadata from being published to maven. The
// metadata includes mapped dependencies which are not reasonably consumable by
// other mod developers.
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
@ -280,9 +271,7 @@ publishing {
from components.java
pom.withXml {
asNode().dependencies.dependency.each { dep ->
assert dep.parent().remove(dep)
}
}
@ -294,14 +283,6 @@ publishing {
}
}
}
compileKotlin {
kotlinOptions {
}
}
compileTestKotlin {
kotlinOptions {
}
}
def getGitChangelog = { ->
try {
@ -311,13 +292,13 @@ def getGitChangelog = { ->
def travisRange = System.getenv('TRAVIS_COMMIT_RANGE')
if (gitHash && gitPrevHash) {
exec {
commandLine 'git', 'log', '--pretty=tformat:> %s', '' + gitPrevHash + '...' + gitHash
commandLine 'git', 'log', '--pretty=tformat:> - %s', '' + gitPrevHash + '...' + gitHash
standardOutput = stdout
}
return stdout.toString().trim()
} else if (travisRange) {
exec {
commandLine 'git', 'log', '--pretty=tformat:> %s', '' + travisRange
commandLine 'git', 'log', '--pretty=tformat:> - %s', '' + travisRange
standardOutput = stdout
}
return stdout.toString().trim()
@ -340,7 +321,7 @@ task sendWebhook {
def message = new Message()
message.setUsername("Patreon Early Access")
message.setContent("New Hexcasting release! Download it here: ${System.getenv("BUILD_URL")}\nChangelog:\n${getGitChangelog()}")
message.setContent("New **$modName** release! Download it here: ${System.getenv("BUILD_URL")}\nChangelog:\n${getGitChangelog()}")
webhook.sendMessage(message)
} catch (ignored) {
@ -349,3 +330,14 @@ task sendWebhook {
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
compileKotlin {
kotlinOptions {
}
}
compileTestKotlin {
kotlinOptions {
}
}

View file

@ -2,3 +2,11 @@
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
modID=hexcasting
modName=Hex Casting
minecraftVersion=1.18.2
modVersion=0.8.4
forgeVersion=40.1.0
paucalVersion=0.3.4
patchouliVersion=66
jeiVersion=9.5.3.143

View file

@ -321,19 +321,19 @@ f043370d6762b976e33dd6e9562d5e1659d32bbf assets/hexcasting/models/item/wand_old.
05e86742a71afd740f47639be62f93bc9898fcde data/forge/tags/items/gems.json
b6593ea802a692c29b5032292df31beb84878ad8 data/hexcasting/advancements/aaa_wasteful_cast.json
4f4c94021adfb296e3ef3dce1acc46f724f38f92 data/hexcasting/advancements/aab_big_cast.json
a165e3959b7d0c37bea586d0e94609b483255569 data/hexcasting/advancements/enlightenment.json
2fe3543a209fca031b1eace7ea217c76142609cc data/hexcasting/advancements/enlightenment.json
eb6393ffc79966e4b5983a68157742b78cd12414 data/hexcasting/advancements/opened_eyes.json
d0b09e984b9270fe20b6c8d6f17e7690caaea409 data/hexcasting/advancements/recipes/brainsweep/brainsweep/akashic_record.json
7e93886be31c3762a5b70e56a7214d19f64d58a8 data/hexcasting/advancements/recipes/brainsweep/brainsweep/budding_amethyst.json
12d9101d43c907f08b0f94747240678d53e4c1fb data/hexcasting/advancements/recipes/brainsweep/brainsweep/directrix_redstone.json
ed6ce219b2ee65d69ea45a43fb9a71b1f5da88bb data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_look.json
d225f90cc1e3b8200014106cd2d3bede9c783817 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_rightclick.json
c966b7ab46808f86bdb7bbd07049146f0dfb24ec data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_storedplayer.json
cf0ad981bebbb79414d955fb40fbf537fe88b89d data/hexcasting/advancements/recipes/brainsweep/brainsweep/akashic_record.json
c2a362b8c19cb288187d8ff340f82198edc54378 data/hexcasting/advancements/recipes/brainsweep/brainsweep/budding_amethyst.json
c11dc4388c18dadff5d93126eb0f7ae848d627b9 data/hexcasting/advancements/recipes/brainsweep/brainsweep/directrix_redstone.json
86424d21e1bf91c128d3b0d528b813629ad962e9 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_look.json
5f9f0962f407062e7b6dd0e8c5f8c55ce13962a5 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_rightclick.json
5d4811f78feefbef0a305555143f488b3dac7ac6 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_storedplayer.json
3fe1fcf17e1e25aebede47c537f92888330ccf9f data/hexcasting/advancements/recipes/hexcasting/abacus.json
5a17fa9a1496f5fbedd0362f94a5231e0e5ebbfc data/hexcasting/advancements/recipes/hexcasting/ageing_scroll_paper_lantern.json
c498998fcffe3d1a0b6dfd6459db64e9389f5c15 data/hexcasting/advancements/recipes/hexcasting/akashic_bookshelf.json
66e51300dc72c27ed8024ddf852ac9a6208a66b1 data/hexcasting/advancements/recipes/hexcasting/akashic_bookshelf.json
31f9b7d8141f67981deedf7a46894e454006bb28 data/hexcasting/advancements/recipes/hexcasting/akashic_button.json
d9f9fc153bf8e8861f79f982b185d2e4c7048067 data/hexcasting/advancements/recipes/hexcasting/akashic_connector.json
168749d413b20bb9c05a8e7191758e0e596a319b data/hexcasting/advancements/recipes/hexcasting/akashic_connector.json
1266b263056dd15c862bff27b05a119c4bbc89ee data/hexcasting/advancements/recipes/hexcasting/akashic_door.json
149179e18b1b8db5dc3fb96e6faa6cb6ffaecb75 data/hexcasting/advancements/recipes/hexcasting/akashic_panel.json
4f852507d843f82dce1512f55abfb205b9829ed4 data/hexcasting/advancements/recipes/hexcasting/akashic_planks.json
@ -368,8 +368,8 @@ d6dfd0c6e995270868cb90de818d24b8a667fd01 data/hexcasting/advancements/recipes/he
b0b1c5fff194b92ff8c5d6468e177271fd910abd data/hexcasting/advancements/recipes/hexcasting/dye_colorizer_red.json
ccc33b4f1a43c8ecd3352ad36ae2dd2191317b5b data/hexcasting/advancements/recipes/hexcasting/dye_colorizer_white.json
9c857c4aeda8a1b3d7a1b5d341871a9434b5816f data/hexcasting/advancements/recipes/hexcasting/dye_colorizer_yellow.json
d978ce120b6af69899ff556f06997fcea522948b data/hexcasting/advancements/recipes/hexcasting/empty_directrix.json
e40a09b7fdf5125be645a323ea5e1922a7e963f0 data/hexcasting/advancements/recipes/hexcasting/empty_impetus.json
7351200c8e3eb24772852c578286384c8aab61bd data/hexcasting/advancements/recipes/hexcasting/empty_directrix.json
023c32e8834eb313c4fa94a84a8f6390ee951ef0 data/hexcasting/advancements/recipes/hexcasting/empty_impetus.json
f089ab17470c5fa0065438c5533d5fafb3ee8eaf data/hexcasting/advancements/recipes/hexcasting/focus.json
fc57d15e9f9f11347a2170dd06053954345368d2 data/hexcasting/advancements/recipes/hexcasting/lens.json
82be04125e60a28701de5bb6bc7855bb46fa9d0f data/hexcasting/advancements/recipes/hexcasting/pride_colorizer_0.json
@ -406,7 +406,7 @@ f32ccb2d36d773215d91dee46bec70a20af501c3 data/hexcasting/advancements/recipes/he
30950c6dd31102cf145f8f7d2979df0736a7ba1e data/hexcasting/advancements/recipes/hexcasting/wand_oak.json
f8d2872c4e692153049b6ae4879755a079954763 data/hexcasting/advancements/recipes/hexcasting/wand_spruce.json
3b2bcffe70bb1f732f06c2560cef66de6c273d62 data/hexcasting/advancements/recipes/hexcasting/wand_warped.json
d31956749bebbcb3f0d3c37f89b569642ac8c2fb data/hexcasting/advancements/root.json
ed0e62cb81783d8eb6323dd70609067219f163ec data/hexcasting/advancements/root.json
739cbdf7f204132f2acfab4df8d21c6197aa1456 data/hexcasting/advancements/y_u_no_cast_angy.json
70a8f77d38affa642afbfceebe129358737b09ac data/hexcasting/loot_modifiers/amethyst_cluster_charged.json
f746acc6b3e798d3b95f4ceb463c648b1f3ae8c3 data/hexcasting/loot_modifiers/amethyst_cluster_dust.json
@ -418,6 +418,7 @@ afecba3144e00505977a4ab4de7940f949ab7818 data/hexcasting/loot_modifiers/scroll_d
50e7ad657a0ab43f3bd632120e09f109791aaf34 data/hexcasting/loot_modifiers/scroll_shipwreck.json
7ffa361bd8a108b504fe450749b42997dc898e5e data/hexcasting/loot_modifiers/scroll_stronghold_library.json
cfd72df535fe95cd2b0d800696e7b4b3429a0459 data/hexcasting/loot_tables/blocks/akashic_bookshelf.json
fc787ec13389b66afda79083f22c7b72f02d5966 data/hexcasting/loot_tables/blocks/akashic_button.json
2e5958279471fa57ae2929d9f9da46e59495f50e data/hexcasting/loot_tables/blocks/akashic_connector.json
3794453f5412af9c7307c9cd91fe2d01ffb763af data/hexcasting/loot_tables/blocks/akashic_door.json
e05da321f00ce09c6f4ad3f6da95ae3dc93e7748 data/hexcasting/loot_tables/blocks/akashic_leaves1.json
@ -427,7 +428,10 @@ e05da321f00ce09c6f4ad3f6da95ae3dc93e7748 data/hexcasting/loot_tables/blocks/akas
ff25315e494e3b79667a1fa90d22a80d0eb6d208 data/hexcasting/loot_tables/blocks/akashic_log_stripped.json
7400ffa5214a5d7ed34be2ac2ffcc2b50cdf299c data/hexcasting/loot_tables/blocks/akashic_panel.json
f59f016a4fa4edaad0b2731f8f1bb2c7b9299ede data/hexcasting/loot_tables/blocks/akashic_planks.json
a8f202947467960dcc634ca7cc65b8911a5c2399 data/hexcasting/loot_tables/blocks/akashic_pressure_plate.json
22517cb8c8063a6a2752cd80f63f224c88bc2ede data/hexcasting/loot_tables/blocks/akashic_record.json
abb4c70d044fed6af763b75bdc50fe2624e83625 data/hexcasting/loot_tables/blocks/akashic_slab.json
5128da5769f0a1a9045488e32ac453069d6431f5 data/hexcasting/loot_tables/blocks/akashic_stairs.json
0ddb27503a7266d126661bad496047a069a07670 data/hexcasting/loot_tables/blocks/akashic_tile.json
659b7e6d539474357532c1207b21354e19cbd4b1 data/hexcasting/loot_tables/blocks/akashic_trapdoor.json
1590fee356080d4dd3f4e0718d87269bdd7f3519 data/hexcasting/loot_tables/blocks/akashic_wood.json
@ -544,7 +548,7 @@ d1b8725bbfc01e2d9a02ef84c911fef89b3636a9 data/hexcasting/tags/items/wands.json
c25784941d6416744fb2ca2d43a3203e5c3e7c8a data/minecraft/tags/blocks/leaves.json
f3c6b6917e504e1c3d5d8875f7cce6f311e791d2 data/minecraft/tags/blocks/logs.json
f3c6b6917e504e1c3d5d8875f7cce6f311e791d2 data/minecraft/tags/blocks/logs_that_burn.json
7c08784f2de139be380b5299f8ea8b8c78126ed8 data/minecraft/tags/blocks/mineable/axe.json
cb5721fcb4a8f7bf14adf6ab560378a250128aba data/minecraft/tags/blocks/mineable/axe.json
c25784941d6416744fb2ca2d43a3203e5c3e7c8a data/minecraft/tags/blocks/mineable/hoe.json
eb4bfbd7fc7632a5c16aa1d50d6090a1f466069b data/minecraft/tags/blocks/mineable/pickaxe.json
f55afc2c05d93b5a44bc9fd73c5e81e71b183965 data/minecraft/tags/blocks/mineable/shovel.json

View file

@ -20,7 +20,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -10,7 +10,7 @@
"trigger": "hexcasting:overcast",
"conditions": {
"health_used": {
"min": 17.95
"min": 0.8
},
"mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion": {
"min": 0.1,

View file

@ -16,37 +16,22 @@
"background": "minecraft:textures/block/calcite.png"
},
"criteria": {
"on_thingy": {
"trigger": "minecraft:tick",
"has_charged_amethyst": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"player": [
"items": [
{
"condition": "minecraft:entity_properties",
"predicate": {
"stepping_on": {
"position": {
"y": {
"min": -64.0,
"max": 30.0
}
},
"block": {
"blocks": [
"minecraft:amethyst_block",
"minecraft:calcite"
"items": [
"hexcasting:charged_amethyst"
]
}
}
},
"entity": "this"
}
]
}
}
},
"requirements": [
[
"on_thingy"
"has_charged_amethyst"
]
]
}

View file

@ -24,7 +24,7 @@
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 1.0,
"min": 2.0,
"max": 4.0
},
"add": false

View file

@ -18,6 +18,6 @@
}
}
],
"modifier": -2.0,
"modifier": -0.5,
"type": "hexcasting:amethyst_shard_reducer"
}

View file

@ -0,0 +1,16 @@
{
"type": "minecraft:block",
"pools": [
{
"name": "akashic_button",
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:akashic_button"
}
]
}
]
}

View file

@ -0,0 +1,16 @@
{
"type": "minecraft:block",
"pools": [
{
"name": "akashic_pressure_plate",
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:akashic_pressure_plate"
}
]
}
]
}

View file

@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"name": "akashic_slab",
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:akashic_slab"
}
],
"functions": [
{
"function": "minecraft:set_count",
"conditions": [
{
"condition": "minecraft:block_state_property",
"block": "hexcasting:akashic_slab",
"properties": {
"type": "double"
}
}
],
"count": 2.0,
"add": false
},
{
"function": "minecraft:explosion_decay"
}
]
}
]
}

View file

@ -0,0 +1,16 @@
{
"type": "minecraft:block",
"pools": [
{
"name": "akashic_stairs",
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:akashic_stairs"
}
]
}
]
}

View file

@ -14,6 +14,7 @@
"hexcasting:akashic_door",
"hexcasting:akashic_trapdoor",
"hexcasting:akashic_slab",
"hexcasting:akashic_stairs",
"hexcasting:akashic_button"
]
}

View file

@ -11,18 +11,23 @@ import at.petrak.hexcasting.common.blocks.HexBlocks
import at.petrak.hexcasting.common.casting.RegisterPatterns
import at.petrak.hexcasting.common.casting.operators.spells.great.OpFlight
import at.petrak.hexcasting.common.command.HexCommands
import at.petrak.hexcasting.common.command.PatternResLocArgument
import at.petrak.hexcasting.common.entities.HexEntities
import at.petrak.hexcasting.common.items.HexItems
import at.petrak.hexcasting.common.lib.HexCapabilityHandler
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.common.misc.Brainsweeping
import at.petrak.hexcasting.common.misc.PlayerPositionRecorder
import at.petrak.hexcasting.common.network.HexMessages
import at.petrak.hexcasting.common.particles.HexParticles
import at.petrak.hexcasting.common.recipe.HexComposting
import at.petrak.hexcasting.common.recipe.HexCustomRecipes
import at.petrak.hexcasting.common.recipe.HexRecipeSerializers
import at.petrak.hexcasting.datagen.HexDataGenerators
import at.petrak.hexcasting.datagen.lootmods.HexLootModifiers
import at.petrak.hexcasting.server.TickScheduler
import net.minecraft.commands.synchronization.ArgumentTypes
import net.minecraft.commands.synchronization.EmptyArgumentSerializer
import net.minecraftforge.api.distmarker.Dist
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.eventbus.api.SubscribeEvent
@ -55,6 +60,8 @@ object HexMod {
CLIENT_CONFIG_SPEC = ForgeConfigSpec.Builder()
.configure { builder: ForgeConfigSpec.Builder? -> HexConfig.Client(builder) }.right
ArgumentTypes.register("hexcasting:pattern", PatternResLocArgument::class.java, EmptyArgumentSerializer(PatternResLocArgument::id))
// mod lifecycle
val modBus = thedarkcolour.kotlinforforge.forge.MOD_BUS
// game events
@ -77,6 +84,9 @@ object HexMod {
modBus.register(HexStatistics::class.java)
modBus.register(HexRecipeSerializers::class.java)
modBus.register(HexComposting::class.java)
evBus.register(PlayerPositionRecorder::class.java)
evBus.register(HexCommands::class.java)
evBus.register(TickScheduler)
evBus.register(HexCapabilityHandler::class.java)

View file

@ -35,7 +35,7 @@ public class OvercastTrigger extends SimpleCriterionTrigger<OvercastTrigger.Inst
super.trigger(player, inst -> {
var manaToHealth = HexConfig.manaToHealthRate.get();
var healthUsed = manaGenerated / manaToHealth;
return inst.test(manaGenerated, healthUsed, player.getHealth() - (float) healthUsed);
return inst.test(manaGenerated, healthUsed / player.getMaxHealth(), player.getHealth() - (float) healthUsed);
});
}

View file

@ -1,9 +1,12 @@
package at.petrak.hexcasting.api.cap;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken;
import java.util.Optional;
public final class HexCapabilities {
public static final Capability<ManaHolder> MANA = CapabilityManager.get(new CapabilityToken<>() {
@ -14,4 +17,10 @@ public final class HexCapabilities {
});
public static final Capability<Colorizer> COLOR = CapabilityManager.get(new CapabilityToken<>() {
});
public static <T> Optional<T> getCapability(ItemStack stack, Capability<T> cap) {
if (stack.isEmpty())
return Optional.empty();
return stack.getCapability(cap).resolve();
}
}

View file

@ -1,6 +1,7 @@
package at.petrak.hexcasting.api.circle;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.misc.ManaConstants;
import at.petrak.hexcasting.api.mod.HexApiItems;
import at.petrak.hexcasting.api.mod.HexApiSounds;
import at.petrak.hexcasting.api.mod.HexConfig;
@ -37,6 +38,8 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
@ -115,21 +118,22 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
this.stepCircle();
}
public List<Pair<ItemStack, Component>> getScryingLensOverlay(BlockState state, BlockPos pos,
LocalPlayer observer, ClientLevel world, InteractionHand lensHand) {
var out = new ArrayList<Pair<ItemStack, Component>>();
@OnlyIn(Dist.CLIENT)
public void applyScryingLensOverlay(List<Pair<ItemStack, Component>> lines,
BlockState state, BlockPos pos,
LocalPlayer observer, ClientLevel world,
Direction hitFace, InteractionHand lensHand) {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
var dustCount = (float) beai.getMana() / (float) HexConfig.dustManaAmount.get();
var dustCount = (float) beai.getMana() / (float) ManaConstants.DUST_UNIT;
var dustCmp = new TranslatableComponent("hexcasting.tooltip.lens.impetus.mana",
String.format("%.2f", dustCount));
out.add(new Pair<>(new ItemStack(HexApiItems.AMETHYST_DUST), dustCmp));
lines.add(new Pair<>(new ItemStack(HexApiItems.AMETHYST_DUST), dustCmp));
var mishap = this.getLastMishap();
if (mishap != null) {
out.add(new Pair<>(new ItemStack(Items.MUSIC_DISC_11), mishap));
lines.add(new Pair<>(new ItemStack(Items.MUSIC_DISC_11), mishap));
}
}
return out;
}
@NotNull
@ -173,7 +177,7 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
if (tag.contains(TAG_ACTIVATOR, Tag.TAG_INT_ARRAY) &&
tag.contains(TAG_COLORIZER, Tag.TAG_COMPOUND) &&
tag.contains(TAG_NEXT_BLOCK, Tag.TAG_COMPOUND) &&
tag.contains(TAG_TRACKED_BLOCKS, Tag.TAG_COMPOUND)) {
tag.contains(TAG_TRACKED_BLOCKS, Tag.TAG_LIST)) {
this.activator = tag.getUUID(TAG_ACTIVATOR);
this.colorizer = FrozenColorizer.deserialize(tag.getCompound(TAG_COLORIZER));
this.nextBlock = NbtUtils.readBlockPos(tag.getCompound(TAG_NEXT_BLOCK));

View file

@ -1,21 +1,30 @@
package at.petrak.hexcasting.api.client;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -26,16 +35,53 @@ import java.util.concurrent.ConcurrentMap;
*/
@OnlyIn(Dist.CLIENT)
public final class ScryingLensOverlayRegistry {
private static final ConcurrentMap<ResourceLocation, Displayer> ID_LOOKUP = new ConcurrentHashMap<>();
private static final ConcurrentMap<ResourceLocation, OverlayBuilder> ID_LOOKUP = new ConcurrentHashMap<>();
// vectors are thread-safe!
private static final List<Pair<Predicate, Displayer>> PREDICATE_LOOKUP = new Vector<>();
private static final List<Pair<OverlayPredicate, OverlayBuilder>> PREDICATE_LOOKUP = new Vector<>();
// implemented as a map to allow for weak dereferencing
private static final Map<LocalPlayer, Pair<BlockPos, Integer>> comparatorData = new WeakHashMap<>();
public static void receiveComparatorValue(BlockPos pos, int value) {
LocalPlayer player = Minecraft.getInstance().player;
if (player != null) {
if (pos == null || value == -1)
comparatorData.remove(player);
else
comparatorData.put(player, new Pair<>(pos, value));
}
}
public static int getComparatorValue(boolean onlyRealComparators) {
var mc = Minecraft.getInstance();
var player = mc.player;
var level = mc.level;
var result = mc.hitResult;
if (player == null || level == null || result == null || result.getType() != HitResult.Type.BLOCK)
return -1;
var comparatorValue = comparatorData.get(player);
if (comparatorValue == null)
return -1;
var pos = ((BlockHitResult)result).getBlockPos();
if (!pos.equals(comparatorValue.getFirst()))
return -1;
var state = mc.level.getBlockState(pos);
if ((onlyRealComparators && !state.is(Blocks.COMPARATOR)) || (!onlyRealComparators && !state.hasAnalogOutputSignal()))
return -1;
return comparatorValue.getSecond();
}
/**
* Add the block to display things when the player is holding a lens and looking at it.
*
* @throws IllegalArgumentException if the block is already registered.
*/
public static void addDisplayer(Block block, Displayer displayer) {
public static void addDisplayer(Block block, OverlayBuilder displayer) {
addDisplayer(block.getRegistryName(), displayer);
}
@ -44,7 +90,7 @@ public final class ScryingLensOverlayRegistry {
*
* @throws IllegalArgumentException if the block ID is already registered.
*/
public static void addDisplayer(ResourceLocation blockID, Displayer displayer) {
public static void addDisplayer(ResourceLocation blockID, OverlayBuilder displayer) {
if (ID_LOOKUP.containsKey(blockID)) {
throw new IllegalArgumentException("Already have a displayer for " + blockID);
}
@ -57,47 +103,51 @@ public final class ScryingLensOverlayRegistry {
* These have a lower priority than the standard ID-based displays, so if an ID and predicate both match,
* this won't be displayed.
*/
public static void addPredicateDisplayer(Predicate predicate, Displayer displayer) {
public static void addPredicateDisplayer(OverlayPredicate predicate, OverlayBuilder displayer) {
PREDICATE_LOOKUP.add(new Pair<>(predicate, displayer));
}
/**
* Internal use only.
*/
public static @Nullable List<Pair<ItemStack, Component>> getLines(BlockState state, BlockPos pos,
public static @NotNull List<Pair<ItemStack, Component>> getLines(BlockState state, BlockPos pos,
LocalPlayer observer, ClientLevel world,
@Nullable InteractionHand lensHand) {
Direction hitFace, @Nullable InteractionHand lensHand) {
List<Pair<ItemStack, Component>> lines = Lists.newArrayList();
var idLookedup = ID_LOOKUP.get(state.getBlock().getRegistryName());
if (idLookedup != null) {
return idLookedup.getLines(state, pos, observer, world, lensHand);
idLookedup.addLines(lines, state, pos, observer, world, hitFace, lensHand);
}
for (var pair : PREDICATE_LOOKUP) {
if (pair.getFirst().test(state, pos, observer, world, lensHand)) {
return pair.getSecond().getLines(state, pos, observer, world, lensHand);
if (pair.getFirst().test(state, pos, observer, world, hitFace, lensHand)) {
pair.getSecond().addLines(lines, state, pos, observer, world, hitFace, lensHand);
}
}
return null;
return lines;
}
/**
* Return the lines displayed by the cursor: an item and some text.
* <p>
* The ItemStack can be null; if it is, the text isn't shifted over for it.
* The ItemStack can be empty; if it is, the text isn't shifted over for it.
*/
@FunctionalInterface
public interface Displayer {
List<Pair<ItemStack, Component>> getLines(BlockState state, BlockPos pos, LocalPlayer observer,
public interface OverlayBuilder {
void addLines(List<Pair<ItemStack, Component>> lines,
BlockState state, BlockPos pos, LocalPlayer observer,
ClientLevel world,
@Nullable InteractionHand lensHand);
Direction hitFace, @Nullable InteractionHand lensHand);
}
/**
* Predicate for matching on a block state.
*/
@FunctionalInterface
public interface Predicate {
boolean test(BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, @Nullable InteractionHand lensHand);
public interface OverlayPredicate {
boolean test(BlockState state, BlockPos pos, LocalPlayer observer,
ClientLevel world,
Direction hitFace, @Nullable InteractionHand lensHand);
}
}

View file

@ -1,6 +1,8 @@
package at.petrak.hexcasting.api.item;
import at.petrak.hexcasting.api.spell.SpellDatum;
import at.petrak.hexcasting.api.utils.NBTHelper;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.Component;
@ -13,6 +15,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface DataHolderItem {
String TAG_OVERRIDE_VISUALLY = "VisualOverride";
@Nullable CompoundTag readDatumTag(ItemStack stack);
@Nullable
@ -49,6 +53,10 @@ public interface DataHolderItem {
if (pIsAdvanced.isAdvanced()) {
pTooltipComponents.add(NbtUtils.toPrettyComponent(datumTag));
}
} else if (NBTHelper.hasString(pStack, DataHolderItem.TAG_OVERRIDE_VISUALLY)) {
pTooltipComponents.add(new TranslatableComponent("hexcasting.spelldata.onitem",
new TranslatableComponent("hexcasting.spelldata.anything").withStyle(ChatFormatting.LIGHT_PURPLE)));
}
}
}

View file

@ -55,7 +55,7 @@ public record FrozenColorizer(ItemStack item, UUID owner) {
}
public static boolean isColorizer(ItemStack stack) {
return stack.getCapability(HexCapabilities.COLOR).isPresent();
return HexCapabilities.getCapability(stack, HexCapabilities.COLOR).isPresent();
}
/**
@ -89,7 +89,7 @@ public record FrozenColorizer(ItemStack item, UUID owner) {
* @return an AARRGGBB color.
*/
public int getRawColor(float time, Vec3 position) {
var maybeColorizer = item.getCapability(HexCapabilities.COLOR).resolve();
var maybeColorizer = HexCapabilities.getCapability(this.item, HexCapabilities.COLOR);
if (maybeColorizer.isPresent()) {
Colorizer colorizer = maybeColorizer.get();
return colorizer.color(owner, time, position);

View file

@ -0,0 +1,7 @@
package at.petrak.hexcasting.api.misc;
public final class ManaConstants {
public static final int DUST_UNIT = 10000;
public static final int SHARD_UNIT = 5 * DUST_UNIT;
public static final int CRYSTAL_UNIT = 10 * DUST_UNIT;
}

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.api.mod;
import at.petrak.hexcasting.api.misc.ManaConstants;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Tier;
import net.minecraft.world.item.Tiers;
@ -16,13 +17,13 @@ public class HexConfig {
public HexConfig(ForgeConfigSpec.Builder builder) {
builder.push("Mana Amounts");
dustManaAmount = builder.comment("How much mana a single Amethyst Dust item is worth")
.defineInRange("dustManaAmount", 10_000, 0, Integer.MAX_VALUE);
.defineInRange("dustManaAmount", ManaConstants.DUST_UNIT, 0, Integer.MAX_VALUE);
shardManaAmount = builder.comment("How much mana a single Amethyst Shard item is worth")
.defineInRange("shardManaAmount", 50_000, 0, Integer.MAX_VALUE);
.defineInRange("shardManaAmount", ManaConstants.SHARD_UNIT, 0, Integer.MAX_VALUE);
chargedCrystalManaAmount = builder.comment("How much mana a single Charged Amethyst Crystal item is worth")
.defineInRange("chargedCrystalManaAmount", 100_000, 0, Integer.MAX_VALUE);
.defineInRange("chargedCrystalManaAmount", ManaConstants.CRYSTAL_UNIT, 0, Integer.MAX_VALUE);
manaToHealthRate = builder.comment("How many points of mana a half-heart is worth when casting from HP")
.defineInRange("manaToHealthRate", 200_000.0 / 20.0, 0.0, Double.POSITIVE_INFINITY);
.defineInRange("manaToHealthRate", 2 * ManaConstants.CRYSTAL_UNIT / 20.0, 0.0, Double.POSITIVE_INFINITY);
builder.pop();
}
@ -33,7 +34,7 @@ public class HexConfig {
public Client(ForgeConfigSpec.Builder builder) {
patternPointSpeedMultiplier = builder.comment(
"How fast the point showing you the stroke order on patterns moves")
.defineInRange("manaToHealthRate", 1.0, 0.0, Double.POSITIVE_INFINITY);
.defineInRange("patternPointSpeed", 1.0, 0.0, Double.POSITIVE_INFINITY);
ctrlTogglesOffStrokeOrder = builder.comment(
"Whether the ctrl key will instead turn *off* the color gradient on patterns")
.define("ctrlTogglesOffStrokeOrder", false);

View file

@ -1,6 +1,7 @@
package at.petrak.hexcasting.api.mod;
import at.petrak.hexcasting.HexMod;
import at.petrak.hexcasting.api.misc.ManaConstants;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.stats.StatFormatter;
@ -19,10 +20,10 @@ public class HexStatistics {
@SubscribeEvent
public static void register(RegistryEvent.Register<Block> evt) {
MANA_USED = makeCustomStat("mana_used",
manamount -> StatFormatter.DEFAULT.format(manamount / HexConfig.dustManaAmount.get())
manamount -> StatFormatter.DEFAULT.format(manamount / ManaConstants.DUST_UNIT)
);
MANA_OVERCASTED = makeCustomStat("mana_overcasted",
manamount -> StatFormatter.DEFAULT.format(manamount / HexConfig.dustManaAmount.get())
manamount -> StatFormatter.DEFAULT.format(manamount / ManaConstants.DUST_UNIT)
);
PATTERNS_DRAWN = makeCustomStat("patterns_drawn", StatFormatter.DEFAULT);
SPELLS_CAST = makeCustomStat("spells_cast", StatFormatter.DEFAULT);

View file

@ -33,7 +33,7 @@ public class HexPlayerDataHelper {
public static final String TAG_FLIGHT_ALLOWED = "hexcasting:flight_allowed";
public static final String TAG_FLIGHT_TIME = "hexcasting:flight_time";
public static final String TAG_FLIGHT_ORIGIN = "hexcasting:flight_origin";
public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_origin";
public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_dimension";
public static final String TAG_FLIGHT_RADIUS = "hexcasting:flight_radius";
public static final String TAG_HARNESS = "hexcasting:spell_harness";
@ -100,6 +100,7 @@ public class HexPlayerDataHelper {
} else {
tag.remove(TAG_FLIGHT_TIME);
tag.remove(TAG_FLIGHT_ORIGIN);
tag.remove(TAG_FLIGHT_DIMENSION);
tag.remove(TAG_FLIGHT_RADIUS);
}
}
@ -148,7 +149,7 @@ public class HexPlayerDataHelper {
var timeLeft = tag.getInt(TAG_FLIGHT_TIME);
var origin = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_FLIGHT_ORIGIN));
var radius = tag.getDouble(TAG_FLIGHT_RADIUS);
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_FLIGHT_DIMENSION)));
return new FlightAbility(true, timeLeft, dimension, origin, radius);
}
return FlightAbility.deny();

View file

@ -14,7 +14,7 @@ interface ConstManaOperator : Operator {
fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>>
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
override fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
if (this.argc > stack.size)
throw MishapNotEnoughArgs(this.argc, stack.size)
val args = stack.takeLast(this.argc)
@ -24,6 +24,6 @@ interface ConstManaOperator : Operator {
val sideEffects = mutableListOf<OperatorSideEffect>(OperatorSideEffect.ConsumeMana(this.manaCost))
return OperationResult(stack, sideEffects)
return OperationResult(stack, local, sideEffects)
}
}

View file

@ -5,4 +5,4 @@ import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
/**
* What happens when an operator is through?
*/
data class OperationResult(val newStack: List<SpellDatum<*>>, val sideEffects: List<OperatorSideEffect>)
data class OperationResult(val newStack: List<SpellDatum<*>>, val newLocalIota: SpellDatum<*>, val sideEffects: List<OperatorSideEffect>)

View file

@ -23,7 +23,7 @@ interface Operator {
*
* A particle effect at the cast site and various messages and advancements are done automagically.
*/
fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult
fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult
/**
* Do you need to be enlightened to use this operator?

View file

@ -1,10 +1,11 @@
package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidSpellDatumType
import at.petrak.hexcasting.api.utils.HexUtils
import at.petrak.hexcasting.api.utils.HexUtils.serializeToNBT
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidSpellDatumType
import at.petrak.hexcasting.api.utils.getList
import net.minecraft.ChatFormatting
import net.minecraft.nbt.*
import net.minecraft.network.chat.Component
@ -144,7 +145,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
TAG_DOUBLE -> SpellDatum(nbt.getDouble(key))
TAG_VEC3 -> SpellDatum(HexUtils.DeserializeVec3FromNBT(nbt.getLongArray(key)))
TAG_LIST -> {
val arr = nbt.getList(key, Tag.TAG_COMPOUND.toInt())
val arr = nbt.getList(key, Tag.TAG_COMPOUND)
val out = ArrayList<SpellDatum<*>>(arr.size)
for (subtag in arr) {
// this is safe because otherwise we wouldn't have been able to get the list before
@ -188,7 +189,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
TAG_LIST -> {
val out = TextComponent("[").withStyle(ChatFormatting.WHITE)
val arr = nbt.getList(key, Tag.TAG_COMPOUND.toInt())
val arr = nbt.getList(key, Tag.TAG_COMPOUND)
for ((i, subtag) in arr.withIndex()) {
// this is safe because otherwise we wouldn't have been able to get the list before
out.append(DisplayFromTag(subtag as CompoundTag))
@ -259,6 +260,19 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
ValidTypes.any { clazz -> clazz.isAssignableFrom(checkee.javaClass) }
}
@JvmStatic
fun GetTagName(datumType: DatumType): String {
return when (datumType) {
DatumType.ENTITY -> TAG_ENTITY
DatumType.WIDGET -> TAG_WIDGET
DatumType.LIST -> TAG_LIST
DatumType.PATTERN -> TAG_PATTERN
DatumType.DOUBLE -> TAG_DOUBLE
DatumType.VEC -> TAG_VEC3
DatumType.OTHER, DatumType.EMPTY -> ""
}
}
}
}

View file

@ -7,30 +7,32 @@ import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
interface SpellOperator : Operator {
val argc: Int
val hasCastingSound: Boolean get() = true
fun hasCastingSound(ctx: CastingContext): Boolean = true
fun awardsCastingStat(ctx: CastingContext): Boolean = true
fun execute(
args: List<SpellDatum<*>>,
ctx: CastingContext
): Triple<RenderedSpell, Int, List<ParticleSpray>>?
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
override fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
if (this.argc > stack.size)
throw MishapNotEnoughArgs(this.argc, stack.size)
val args = stack.takeLast(this.argc)
for (_i in 0 until this.argc) stack.removeLast()
val executeResult = this.execute(args, ctx) ?: return OperationResult(stack, listOf())
val executeResult = this.execute(args, ctx) ?: return OperationResult(stack, local, listOf())
val (spell, mana, particles) = executeResult
val sideEffects = mutableListOf(
OperatorSideEffect.ConsumeMana(mana),
OperatorSideEffect.AttemptSpell(spell, this.isGreat, this.hasCastingSound)
OperatorSideEffect.AttemptSpell(spell, this.isGreat, this.hasCastingSound(ctx), this.awardsCastingStat(ctx))
)
for (spray in particles) {
sideEffects.add(OperatorSideEffect.Particles(spray))
}
return OperationResult(stack, sideEffects)
return OperationResult(stack, local, sideEffects)
}
}

View file

@ -16,9 +16,12 @@ import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.Mishap
import at.petrak.hexcasting.api.spell.mishaps.MishapDisallowedSpell
import at.petrak.hexcasting.api.spell.mishaps.MishapError
import at.petrak.hexcasting.api.spell.mishaps.MishapTooManyCloseParens
import at.petrak.hexcasting.api.utils.HexDamageSources
import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.api.utils.asCompound
import at.petrak.hexcasting.api.utils.getList
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
@ -34,6 +37,7 @@ import kotlin.math.min
*/
class CastingHarness private constructor(
var stack: MutableList<SpellDatum<*>>,
var localIota: SpellDatum<*>,
var parenCount: Int,
var parenthesized: List<HexPattern>,
var escapeNext: Boolean,
@ -45,7 +49,7 @@ class CastingHarness private constructor(
constructor(
ctx: CastingContext,
prepackagedColorizer: FrozenColorizer? = null
) : this(mutableListOf(), 0, mutableListOf(), false, ctx, prepackagedColorizer)
) : this(mutableListOf(), SpellDatum.make(Widget.NULL), 0, mutableListOf(), false, ctx, prepackagedColorizer)
/**
* Given a pattern, do all the updating/side effects/etc required.
@ -81,7 +85,8 @@ class CastingHarness private constructor(
if (HexConfig.Server.actionDenyList.get().contains(operatorIdPair.second.toString())) {
throw MishapDisallowedSpell()
}
val (stack2, sideEffectsUnmut) = operatorIdPair.first.operate(this.stack.toMutableList(), this.ctx)
val (stack2, local2, sideEffectsUnmut) = operatorIdPair.first.operate(this.stack.toMutableList(), this.localIota, this.ctx)
this.localIota = local2
// Stick a poofy particle effect at the caster position
val sideEffects = sideEffectsUnmut.toMutableList()
if (this.ctx.spellCircle == null)
@ -108,6 +113,12 @@ class CastingHarness private constructor(
this.getFunctionalData(),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, operatorIdPair?.second))),
)
} catch (exception: Exception) {
exception.printStackTrace()
return CastResult(
this.getFunctionalData(),
listOf(OperatorSideEffect.DoMishap(MishapError(exception), Mishap.Context(newPat, operatorIdPair?.second)))
)
}
}
@ -274,8 +285,8 @@ class CastingHarness private constructor(
}
} else {
val casterStack = this.ctx.caster.getItemInHand(this.ctx.castingHand)
val casterManaHolder = casterStack.getCapability(HexCapabilities.MANA).resolve()
val casterSpellHolder = casterStack.getCapability(HexCapabilities.SPELL).resolve()
val casterManaHolder = HexCapabilities.getCapability(casterStack, HexCapabilities.MANA)
val casterSpellHolder = HexCapabilities.getCapability(casterStack, HexCapabilities.SPELL)
val ipsCanDrawFromInv = if (casterSpellHolder.isPresent) {
if (casterManaHolder.isPresent) {
val manaAvailable = casterManaHolder.get().mana
@ -340,6 +351,8 @@ class CastingHarness private constructor(
stackTag.add(datum.serializeToNBT())
out.put(TAG_STACK, stackTag)
out.put(TAG_LOCAL, localIota.serializeToNBT())
out.putInt(TAG_PAREN_COUNT, this.parenCount)
out.putBoolean(TAG_ESCAPE_NEXT, this.escapeNext)
@ -358,25 +371,29 @@ class CastingHarness private constructor(
companion object {
const val TAG_STACK = "stack"
const val TAG_LOCAL = "local"
const val TAG_PAREN_COUNT = "open_parens"
const val TAG_PARENTHESIZED = "parenthesized"
const val TAG_ESCAPE_NEXT = "escape_next"
const val TAG_PREPACKAGED_COLORIZER = "prepackaged_colorizer"
@JvmStatic
fun DeserializeFromNBT(nbt: Tag, ctx: CastingContext): CastingHarness {
fun DeserializeFromNBT(nbt: CompoundTag, ctx: CastingContext): CastingHarness {
return try {
val stack = mutableListOf<SpellDatum<*>>()
val stackTag = (nbt as CompoundTag).getList(TAG_STACK, Tag.TAG_COMPOUND.toInt())
val stackTag = nbt.getList(TAG_STACK, Tag.TAG_COMPOUND)
for (subtag in stackTag) {
val datum = SpellDatum.DeserializeFromNBT(subtag as CompoundTag, ctx.world)
val datum = SpellDatum.DeserializeFromNBT(subtag.asCompound, ctx.world)
stack.add(datum)
}
val localTag = nbt.getCompound(TAG_LOCAL)
val localIota = SpellDatum.DeserializeFromNBT(localTag, ctx.world)
val parenthesized = mutableListOf<HexPattern>()
val parenTag = nbt.getList(TAG_PARENTHESIZED, Tag.TAG_COMPOUND.toInt())
val parenTag = nbt.getList(TAG_PARENTHESIZED, Tag.TAG_COMPOUND)
for (subtag in parenTag) {
parenthesized.add(HexPattern.DeserializeFromNBT(subtag as CompoundTag))
parenthesized.add(HexPattern.DeserializeFromNBT(subtag.asCompound))
}
val parenCount = nbt.getInt(TAG_PAREN_COUNT)
@ -388,7 +405,7 @@ class CastingHarness private constructor(
null
}
CastingHarness(stack, parenCount, parenthesized, escapeNext, ctx, colorizer)
CastingHarness(stack, localIota, parenCount, parenthesized, escapeNext, ctx, colorizer)
} catch (exn: Exception) {
CastingHarness(ctx)
}

View file

@ -22,7 +22,7 @@ sealed class OperatorSideEffect {
abstract fun performEffect(harness: CastingHarness): Boolean
/** Try to cast a spell */
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean, val hasCastingSound: Boolean = true) : OperatorSideEffect() {
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean, val hasCastingSound: Boolean = true, val awardStat: Boolean = true) : OperatorSideEffect() {
override fun performEffect(harness: CastingHarness): Boolean {
return if (this.isGreat && !harness.ctx.isCasterEnlightened) {
harness.ctx.caster.sendMessage(
@ -33,6 +33,7 @@ sealed class OperatorSideEffect {
true
} else {
this.spell.cast(harness.ctx)
if (awardStat)
harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST)
false
}
@ -53,8 +54,7 @@ sealed class OperatorSideEffect {
}
}
data class Particles(val spray: ParticleSpray) :
OperatorSideEffect() {
data class Particles(val spray: ParticleSpray) : OperatorSideEffect() {
override fun performEffect(harness: CastingHarness): Boolean {
this.spray.sprayParticles(harness.ctx.world, harness.getColorizer())

View file

@ -14,7 +14,7 @@ class MishapAlreadyBrainswept(val villager: Villager) : Mishap() {
dyeColor(DyeColor.GREEN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
villager.hurt(HexDamageSources.OVERCAST, villager.health)
villager.hurt(HexDamageSources.overcastDamageFrom(ctx.caster), villager.health)
}
override fun particleSpray(ctx: CastingContext): ParticleSpray {

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
@ -16,7 +16,7 @@ class MishapBadBlock(val pos: BlockPos, val expected: Component) : Mishap() {
dyeColor(DyeColor.LIME)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
ctx.world.explode(null, pos.x + 0.5, pos.y + 0.5, pos.z + 0.5, 2f, Explosion.BlockInteraction.NONE)
ctx.world.explode(null, pos.x + 0.5, pos.y + 0.5, pos.z + 0.5, 0.25f, Explosion.BlockInteraction.NONE)
}
override fun particleSpray(ctx: CastingContext): ParticleSpray {

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.utils.HexDamageSources
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
@ -16,7 +16,7 @@ class MishapBadBrainsweep(val villager: Villager, val pos: BlockPos) : Mishap()
dyeColor(DyeColor.GREEN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
villager.hurt(HexDamageSources.OVERCAST, villager.health)
villager.hurt(HexDamageSources.overcastDamageFrom(ctx.caster), villager.health)
}
override fun particleSpray(ctx: CastingContext): ParticleSpray {

View file

@ -13,14 +13,14 @@ class MishapBadItem(val item: ItemEntity, val wanted: Component) : Mishap() {
dyeColor(DyeColor.BROWN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
item.deltaMovement = item.deltaMovement.add((Math.random() - 0.5) * 0.05, 1.0, (Math.random() - 0.5) * 0.05)
item.deltaMovement = item.deltaMovement.add((Math.random() - 0.5) * 0.05, 0.75, (Math.random() - 0.5) * 0.05)
}
override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component {
return if (item.item.isEmpty)
error("no_item", actionName(errorCtx.action), wanted)
else
error("bad_item", actionName(errorCtx.action), wanted, item.item)
error("bad_item", actionName(errorCtx.action), wanted, item.item.count, item.item.displayName)
}
companion object {

View file

@ -0,0 +1,18 @@
package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.network.chat.Component
import net.minecraft.world.item.DyeColor
class MishapError(val exception: Exception) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.BLACK)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
}
override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component =
error("unknown", actionName(errorCtx.action), exception)
}

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.math.HexPattern
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
@ -53,7 +53,7 @@ class MishapInvalidIota(
ItemEntity::class.java.isAssignableFrom(cls) -> "entity.item"
Player::class.java.isAssignableFrom(cls) -> "entity.player"
Villager::class.java.isAssignableFrom(cls) -> "entity.player"
Villager::class.java.isAssignableFrom(cls) -> "entity.villager"
LivingEntity::class.java.isAssignableFrom(cls) -> "entity.living"
Entity::class.java.isAssignableFrom(cls) -> "entity"

View file

@ -1,10 +1,19 @@
package at.petrak.hexcasting.api.utils;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.EntityDamageSource;
import net.minecraft.world.entity.Entity;
public final class HexDamageSources {
public static final DamageSource OVERCAST = new DamageSource("hexcasting.overcast")
.bypassArmor()
.bypassMagic()
.setMagic();
public static DamageSource overcastDamageFrom(Entity cause) {
return new EntityDamageSource("hexcasting.overcast", cause)
.bypassArmor()
.bypassMagic()
.setMagic();
}
}

View file

@ -18,7 +18,7 @@ object HexUtils {
LongArrayTag(longArrayOf(this.x.toRawBits(), this.y.toRawBits(), this.z.toRawBits()))
@JvmStatic
fun DeserializeVec3FromNBT(tag: LongArray): Vec3 =
fun DeserializeVec3FromNBT(tag: LongArray): Vec3 = if (tag.size != 3) Vec3.ZERO else
Vec3(
Double.fromBits(tag[0]),
Double.fromBits(tag[1]),
@ -30,7 +30,7 @@ object HexUtils {
LongArrayTag(longArrayOf(this.x.toDouble().toRawBits(), this.y.toDouble().toRawBits()))
@JvmStatic
fun DeserializeVec2FromNBT(tag: LongArray): Vec2 =
fun DeserializeVec2FromNBT(tag: LongArray): Vec2 = if (tag.size != 2) Vec2.ZERO else
Vec2(
Double.fromBits(tag[0]).toFloat(),
Double.fromBits(tag[1]).toFloat(),

View file

@ -1,6 +1,7 @@
package at.petrak.hexcasting.api.utils
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.cap.ManaHolder
import net.minecraft.util.Mth
import net.minecraft.world.item.ItemStack
import kotlin.math.roundToInt
@ -8,7 +9,7 @@ import kotlin.math.roundToInt
object ManaHelper {
@JvmStatic
fun isManaItem(stack: ItemStack): Boolean {
return stack.getCapability(HexCapabilities.MANA).map { it.canProvide() }.orElse(false) && extractMana(stack, simulate = true) > 0
return HexCapabilities.getCapability(stack, HexCapabilities.MANA).map(ManaHolder::canProvide).orElse(false) && extractMana(stack, simulate = true) > 0
}
/**
@ -22,7 +23,7 @@ object ManaHelper {
@JvmStatic
@JvmOverloads
fun extractMana(stack: ItemStack, cost: Int = -1, drainForBatteries: Boolean = false, simulate: Boolean = false): Int {
val manaCapability = stack.getCapability(HexCapabilities.MANA).resolve()
val manaCapability = HexCapabilities.getCapability(stack, HexCapabilities.MANA)
if (!manaCapability.isPresent)
return 0
@ -39,8 +40,8 @@ object ManaHelper {
* Sorted from least important to most important
*/
fun compare(astack: ItemStack, bstack: ItemStack): Int {
val aMana = astack.getCapability(HexCapabilities.MANA).resolve()
val bMana = bstack.getCapability(HexCapabilities.MANA).resolve()
val aMana = HexCapabilities.getCapability(astack, HexCapabilities.MANA)
val bMana = HexCapabilities.getCapability(bstack, HexCapabilities.MANA)
return if (astack.item != bstack.item) {
aMana.map { it.consumptionPriority }.orElse(0) - bMana.map { it.consumptionPriority }.orElse(0)

View file

@ -0,0 +1,237 @@
@file:JvmName("NBTHelper")
package at.petrak.hexcasting.api.utils
import net.minecraft.nbt.*
import net.minecraft.world.item.ItemStack
import java.util.*
private inline fun <T: Any, K, E> T?.getIf(key: K, predicate: T?.(K) -> Boolean, get: T.(K) -> E): E? =
getIf(key, predicate, get, null)
private inline fun <T: Any, K, E> T?.getIf(key: K, predicate: T?.(K) -> Boolean, get: T.(K) -> E, default: E): E {
if (this != null && predicate(key))
return get(key)
return default
}
// ======================================================================================================== CompoundTag
// Checks for containment
fun CompoundTag?.hasNumber(key: String) = contains(key, Tag.TAG_ANY_NUMERIC)
fun CompoundTag?.hasByte(key: String) = contains(key, Tag.TAG_BYTE)
fun CompoundTag?.hasShort(key: String) = contains(key, Tag.TAG_SHORT)
fun CompoundTag?.hasInt(key: String) = contains(key, Tag.TAG_INT)
fun CompoundTag?.hasLong(key: String) = contains(key, Tag.TAG_LONG)
fun CompoundTag?.hasFloat(key: String) = contains(key, Tag.TAG_FLOAT)
fun CompoundTag?.hasDouble(key: String) = contains(key, Tag.TAG_DOUBLE)
fun CompoundTag?.hasLongArray(key: String) = contains(key, Tag.TAG_LONG_ARRAY)
fun CompoundTag?.hasIntArray(key: String) = contains(key, Tag.TAG_INT_ARRAY)
fun CompoundTag?.hasByteArray(key: String) = contains(key, Tag.TAG_BYTE_ARRAY)
fun CompoundTag?.hasCompound(key: String) = contains(key, Tag.TAG_COMPOUND)
fun CompoundTag?.hasString(key: String) = contains(key, Tag.TAG_STRING)
fun CompoundTag?.hasList(key: String) = contains(key, Tag.TAG_LIST)
fun CompoundTag?.hasList(key: String, objType: Int) = hasList(key, objType.toByte())
fun CompoundTag?.hasList(key: String, objType: Byte) = hasList(key) && (get(key) as ListTag).elementType == objType
fun CompoundTag?.hasUUID(key: String) = this != null && hasUUID(key)
fun CompoundTag?.contains(key: String, id: Byte) = contains(key, id.toInt())
fun CompoundTag?.contains(key: String, id: Int) = this != null && contains(key, id)
fun CompoundTag?.contains(key: String) = this != null && contains(key)
// Puts
fun CompoundTag?.putBoolean(key: String, value: Boolean) = this?.putBoolean(key, value)
fun CompoundTag?.putByte(key: String, value: Byte) = this?.putByte(key, value)
fun CompoundTag?.putShort(key: String, value: Short) = this?.putShort(key, value)
fun CompoundTag?.putInt(key: String, value: Int) = this?.putInt(key, value)
fun CompoundTag?.putLong(key: String, value: Long) = this?.putLong(key, value)
fun CompoundTag?.putFloat(key: String, value: Float) = this?.putFloat(key, value)
fun CompoundTag?.putDouble(key: String, value: Double) = this?.putDouble(key, value)
fun CompoundTag?.putLongArray(key: String, value: LongArray) = this?.putLongArray(key, value)
fun CompoundTag?.putIntArray(key: String, value: IntArray) = this?.putIntArray(key, value)
fun CompoundTag?.putByteArray(key: String, value: ByteArray) = this?.putByteArray(key, value)
fun CompoundTag?.putCompound(key: String, value: CompoundTag) = put(key, value)
fun CompoundTag?.putString(key: String, value: String) = this?.putString(key, value)
fun CompoundTag?.putList(key: String, value: ListTag) = put(key, value)
fun CompoundTag?.putUUID(key: String, value: UUID) = this?.putUUID(key, value)
fun CompoundTag?.put(key: String, value: Tag) = this?.put(key, value)
// Remove
fun CompoundTag?.remove(key: String) = this?.remove(key)
// Gets
@JvmOverloads
fun CompoundTag?.getBoolean(key: String, defaultExpected: Boolean = false) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getBoolean, defaultExpected)
@JvmOverloads
fun CompoundTag?.getByte(key: String, defaultExpected: Byte = 0) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getByte, defaultExpected)
@JvmOverloads
fun CompoundTag?.getShort(key: String, defaultExpected: Short = 0) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getShort, defaultExpected)
@JvmOverloads
fun CompoundTag?.getInt(key: String, defaultExpected: Int = 0) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getInt, defaultExpected)
@JvmOverloads
fun CompoundTag?.getLong(key: String, defaultExpected: Long = 0) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getLong, defaultExpected)
@JvmOverloads
fun CompoundTag?.getFloat(key: String, defaultExpected: Float = 0f) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getFloat, defaultExpected)
@JvmOverloads
fun CompoundTag?.getDouble(key: String, defaultExpected: Double = 0.0) = getIf(key, CompoundTag?::hasNumber, CompoundTag::getDouble, defaultExpected)
fun CompoundTag?.getLongArray(key: String) = getIf(key, CompoundTag?::hasLongArray, CompoundTag::getLongArray)
fun CompoundTag?.getIntArray(key: String) = getIf(key, CompoundTag?::hasIntArray, CompoundTag::getIntArray)
fun CompoundTag?.getByteArray(key: String) = getIf(key, CompoundTag?::hasByteArray, CompoundTag::getByteArray)
fun CompoundTag?.getCompound(key: String): CompoundTag? = getIf(key, CompoundTag?::hasCompound, CompoundTag::getCompound)
fun CompoundTag?.getString(key: String) = getIf(key, CompoundTag?::hasString, CompoundTag::getString)
fun CompoundTag?.getList(key: String, objType: Byte) = getList(key, objType.toInt())
fun CompoundTag?.getList(key: String, objType: Int) = getIf(key, { hasList(key, objType) }) { getList(it, objType) }
fun CompoundTag?.getUUID(key: String) = getIf(key, CompoundTag?::hasUUID, CompoundTag::getUUID)
fun CompoundTag?.get(key: String) = getIf(key, CompoundTag?::contains, CompoundTag::get)
@JvmSynthetic
@JvmName("getListByByte")
fun CompoundTag.getList(key: String, objType: Byte): ListTag = getList(key, objType.toInt())
// Get-or-create
fun CompoundTag.getOrCreateCompound(key: String) = getCompound(key) ?: CompoundTag().also { putCompound(key, this) }
// ================================================================================================================ Tag
val Tag.asBoolean get() = asByte == 0.toByte()
val Tag.asByte get() = (this as? NumericTag)?.asByte ?: 0.toByte()
val Tag.asShort get() = (this as? NumericTag)?.asShort ?: 0.toShort()
val Tag.asInt get() = (this as? NumericTag)?.asInt ?: 0
val Tag.asLong get() = (this as? NumericTag)?.asLong ?: 0L
val Tag.asFloat get() = (this as? NumericTag)?.asFloat ?: 0F
val Tag.asDouble get() = (this as? NumericTag)?.asDouble ?: 0.0
val Tag.asLongArray: LongArray
get() = when (this) {
is LongArrayTag -> this.asLongArray
is IntArrayTag -> {
val array = this.asIntArray
LongArray(array.size) { array[it].toLong() }
}
is ByteArrayTag -> {
val array = this.asByteArray
LongArray(array.size) { array[it].toLong() }
}
else -> LongArray(0)
}
val Tag.asIntArray: IntArray
get() = when (this) {
is IntArrayTag -> this.asIntArray
is LongArrayTag -> {
val array = this.asLongArray
IntArray(array.size) { array[it].toInt() }
}
is ByteArrayTag -> {
val array = this.asByteArray
IntArray(array.size) { array[it].toInt() }
}
else -> IntArray(0)
}
val Tag.asByteArray: ByteArray
get() = when (this) {
is ByteArrayTag -> this.asByteArray
is LongArrayTag -> {
val array = this.asLongArray
ByteArray(array.size) { array[it].toByte() }
}
is IntArrayTag -> {
val array = this.asIntArray
ByteArray(array.size) { array[it].toByte() }
}
else -> ByteArray(0)
}
val Tag.asCompound get() = this as? CompoundTag ?: CompoundTag()
// asString is defined in Tag
val Tag.asList get() = this as? ListTag ?: ListTag()
val Tag.asUUID: UUID get() = if (this is IntArrayTag && this.size == 4) NbtUtils.loadUUID(this) else UUID(0, 0)
// ========================================================================================================== ItemStack
// Checks for containment
fun ItemStack.hasNumber(key: String) = tag.hasNumber(key)
fun ItemStack.hasByte(key: String) = tag.hasByte(key)
fun ItemStack.hasShort(key: String) = tag.hasShort(key)
fun ItemStack.hasInt(key: String) = tag.hasInt(key)
fun ItemStack.hasLong(key: String) = tag.hasLong(key)
fun ItemStack.hasFloat(key: String) = tag.hasFloat(key)
fun ItemStack.hasDouble(key: String) = tag.hasDouble(key)
fun ItemStack.hasLongArray(key: String) = tag.hasLongArray(key)
fun ItemStack.hasIntArray(key: String) = tag.hasIntArray(key)
fun ItemStack.hasByteArray(key: String) = tag.hasByteArray(key)
fun ItemStack.hasCompound(key: String) = tag.hasCompound(key)
fun ItemStack.hasString(key: String) = tag.hasString(key)
fun ItemStack.hasList(key: String) = tag.hasList(key)
fun ItemStack.hasList(key: String, objType: Int) = tag.hasList(key, objType)
fun ItemStack.hasList(key: String, objType: Byte) = tag.hasList(key, objType)
fun ItemStack.hasUUID(key: String) = tag.hasUUID(key)
@JvmName("contains")
fun ItemStack.containsTag(key: String) = tag.contains(key)
@JvmName("contains")
fun ItemStack.containsTag(key: String, id: Byte) = tag.contains(key, id)
@JvmName("contains")
fun ItemStack.containsTag(key: String, id: Int) = tag.contains(key, id)
// Puts
fun ItemStack.putBoolean(key: String, value: Boolean) = orCreateTag.putBoolean(key, value)
fun ItemStack.putByte(key: String, value: Byte) = orCreateTag.putByte(key, value)
fun ItemStack.putShort(key: String, value: Short) = orCreateTag.putShort(key, value)
fun ItemStack.putInt(key: String, value: Int) = orCreateTag.putInt(key, value)
fun ItemStack.putLong(key: String, value: Long) = orCreateTag.putLong(key, value)
fun ItemStack.putFloat(key: String, value: Float) = orCreateTag.putFloat(key, value)
fun ItemStack.putDouble(key: String, value: Double) = orCreateTag.putDouble(key, value)
fun ItemStack.putLongArray(key: String, value: LongArray) = orCreateTag.putLongArray(key, value)
fun ItemStack.putIntArray(key: String, value: IntArray) = orCreateTag.putIntArray(key, value)
fun ItemStack.putByteArray(key: String, value: ByteArray) = orCreateTag.putByteArray(key, value)
fun ItemStack.putCompound(key: String, value: CompoundTag) = putTag(key, value)
fun ItemStack.putString(key: String, value: String) = orCreateTag.putString(key, value)
fun ItemStack.putList(key: String, value: ListTag) = putTag(key, value)
fun ItemStack.putUUID(key: String, value: UUID) = orCreateTag.putUUID(key, value)
@JvmName("put")
fun ItemStack.putTag(key: String, value: Tag) = orCreateTag.put(key, value)
// Remove
fun ItemStack.remove(key: String) = removeTagKey(key)
// Gets
@JvmOverloads
fun ItemStack.getBoolean(key: String, defaultExpected: Boolean = false) = tag.getBoolean(key, defaultExpected)
@JvmOverloads
fun ItemStack.getByte(key: String, defaultExpected: Byte = 0) = tag.getByte(key, defaultExpected)
@JvmOverloads
fun ItemStack.getShort(key: String, defaultExpected: Short = 0) = tag.getShort(key, defaultExpected)
@JvmOverloads
fun ItemStack.getInt(key: String, defaultExpected: Int = 0) = tag.getInt(key, defaultExpected)
@JvmOverloads
fun ItemStack.getLong(key: String, defaultExpected: Long = 0) = tag.getLong(key, defaultExpected)
@JvmOverloads
fun ItemStack.getFloat(key: String, defaultExpected: Float = 0f) = tag.getFloat(key, defaultExpected)
@JvmOverloads
fun ItemStack.getDouble(key: String, defaultExpected: Double = 0.0) = tag.getDouble(key, defaultExpected)
fun ItemStack.getLongArray(key: String) = tag.getLongArray(key)
fun ItemStack.getIntArray(key: String) = tag.getIntArray(key)
fun ItemStack.getByteArray(key: String) = tag.getByteArray(key)
fun ItemStack.getCompound(key: String) = tag.getCompound(key)
fun ItemStack.getString(key: String) = tag.getString(key)
fun ItemStack.getList(key: String, objType: Int) = tag.getList(key, objType)
fun ItemStack.getUUID(key: String) = tag.getUUID(key)
@JvmName("get")
fun ItemStack.getTag(key: String) = tag.get(key)
// Get-or-create
fun ItemStack.getOrCreateCompound(key: String): CompoundTag = getOrCreateTagElement(key)

View file

@ -3,16 +3,32 @@ package at.petrak.hexcasting.client;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
// I can't find a better way to do this :(
public class ClientTickCounter {
private static long tickCount = 0;
public static long ticksInGame = 0L;
public static float partialTicks = 0.0F;
public static float delta = 0.0F;
public static float total = 0.0F;
@SubscribeEvent
public static void onTick(TickEvent.ClientTickEvent evt) {
tickCount++;
public static void onRenderTick(TickEvent.RenderTickEvent evt) {
if (evt.phase == TickEvent.Phase.START) {
partialTicks = evt.renderTickTime;
} else {
calcDelta();
}
}
@SubscribeEvent
public static void onTickEnd(TickEvent.ClientTickEvent evt) {
if (evt.phase == TickEvent.Phase.END) {
++ticksInGame;
partialTicks = 0.0F;
calcDelta();
}
}
public static long getTickCount() {
return tickCount;
private static void calcDelta() {
float oldTotal = total;
total = (float)ticksInGame + partialTicks;
delta = total - oldTotal;
}
}

View file

@ -1,30 +1,37 @@
package at.petrak.hexcasting.client;
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
import at.petrak.hexcasting.api.player.HexPlayerDataHelper;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.common.items.HexItems;
import at.petrak.hexcasting.api.player.HexPlayerDataHelper;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.Style;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderLevelLastEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import java.util.List;
import java.util.function.BiConsumer;
public class HexAdditionalRenderers {
@ -42,7 +49,7 @@ public class HexAdditionalRenderers {
@SubscribeEvent
public static void overlayGui(RenderGameOverlayEvent.Post evt) {
if (evt.getType() == RenderGameOverlayEvent.ElementType.ALL) {
tryRenderScryingLensOverlay(evt.getMatrixStack(), evt.getPartialTicks());
tryRenderScryingLensOverlay(evt.getMatrixStack());
}
}
@ -59,7 +66,7 @@ public class HexAdditionalRenderers {
sentinel.position().y - playerPos.y,
sentinel.position().z - playerPos.z);
var time = mc.level.getLevelData().getGameTime() + partialTicks;
var time = ClientTickCounter.total / 2;
var bobSpeed = 1f / 20;
var magnitude = 0.1f;
ps.translate(0, Mth.sin(bobSpeed * time) * magnitude, 0);
@ -148,19 +155,24 @@ public class HexAdditionalRenderers {
// My internet is really shaky right now but thank god Patchi already does this exact thing
// cause it's a dependency so i have the .class files downloaded
private static void tryRenderScryingLensOverlay(PoseStack ps, float partialTicks) {
private static void tryRenderScryingLensOverlay(PoseStack ps) {
var mc = Minecraft.getInstance();
LocalPlayer player = mc.player;
ClientLevel level = mc.level;
if (player == null || level == null)
return;
boolean foundLens = false;
InteractionHand lensHand = null;
for (var hand : InteractionHand.values()) {
if (mc.player.getItemInHand(hand).is(HexItems.SCRYING_LENS.get())) {
if (player.getItemInHand(hand).is(HexItems.SCRYING_LENS.get())) {
lensHand = hand;
foundLens = true;
break;
}
}
if (!foundLens && mc.player.getItemBySlot(EquipmentSlot.HEAD).is(HexItems.SCRYING_LENS.get())) {
if (!foundLens && player.getItemBySlot(EquipmentSlot.HEAD).is(HexItems.SCRYING_LENS.get())) {
foundLens = true;
}
@ -169,38 +181,55 @@ public class HexAdditionalRenderers {
}
var hitRes = mc.hitResult;
if (hitRes instanceof BlockHitResult bhr) {
if (hitRes != null && hitRes.getType() == HitResult.Type.BLOCK) {
var bhr = (BlockHitResult) hitRes;
var pos = bhr.getBlockPos();
var bs = mc.level.getBlockState(pos);
var bs = level.getBlockState(pos);
var lines = ScryingLensOverlayRegistry.getLines(bs, pos, player, level, bhr.getDirection(), lensHand);
int totalHeight = 8;
List<Pair<ItemStack, List<FormattedText>>> actualLines = Lists.newArrayList();
var lines = ScryingLensOverlayRegistry.getLines(bs, pos, mc.player, mc.level, lensHand);
if (lines != null) {
var window = mc.getWindow();
var x = window.getGuiScaledWidth() / 2f + 8f;
var y = window.getGuiScaledHeight() / 2f;
ps.pushPose();
ps.translate(x, y, 0);
var maxWidth = (int) (window.getGuiScaledWidth() / 2f * 0.8f);
for (var pair : lines) {
var stack = pair.getFirst();
if (stack != null) {
// this draws centered in the Y ...
RenderLib.renderItemStackInGui(ps, pair.getFirst(), 0, 0);
}
float tx = stack == null ? 0 : 18;
float ty = 5;
// but this draws where y=0 is the baseline
totalHeight += mc.font.lineHeight + 6;
var text = pair.getSecond();
var textLines = mc.font.getSplitter().splitLines(text, maxWidth, Style.EMPTY);
for (var line : textLines) {
actualLines.add(Pair.of(pair.getFirst(), textLines));
if (textLines.size() > 1) {
totalHeight += mc.font.lineHeight * (textLines.size() - 1);
}
}
if (!lines.isEmpty()) {
var x = window.getGuiScaledWidth() / 2f + 8f;
var y = window.getGuiScaledHeight() / 2f - totalHeight;
ps.pushPose();
ps.translate(x, y, 0);
for (var pair : actualLines) {
var stack = pair.getFirst();
if (!stack.isEmpty()) {
// this draws centered in the Y ...
RenderLib.renderItemStackInGui(ps, pair.getFirst(), 0, 0);
}
float tx = stack.isEmpty() ? 0 : 18;
float ty = 5;
// but this draws where y=0 is the baseline
var text = pair.getSecond();
for (var line : text) {
var actualLine = Language.getInstance().getVisualOrder(line);
mc.font.drawShadow(ps, actualLine, tx, ty, 0xffffffff);
ps.translate(0, 9, 0);
ps.translate(0, mc.font.lineHeight, 0);
}
if (text.isEmpty())
ps.translate(0, mc.font.lineHeight, 0);
ps.translate(0, 6, 0);
}

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.client;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.gui.PatternTooltipGreeble;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.items.HexItems;
@ -8,6 +9,7 @@ import at.petrak.hexcasting.common.items.ItemSlate;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import com.mojang.datafixers.util.Either;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.ItemStack;
@ -35,23 +37,22 @@ public class HexTooltips {
ItemStack stack = evt.getItemStack();
if (!stack.isEmpty()) {
if (stack.is(HexItems.SCROLL.get())) {
var tag = stack.getOrCreateTag();
if (tag.contains(ItemScroll.TAG_PATTERN, Tag.TAG_COMPOUND)) {
var pattern = HexPattern.DeserializeFromNBT(tag.getCompound(ItemScroll.TAG_PATTERN));
CompoundTag patternTag = NBTHelper.getCompound(stack, ItemScroll.TAG_PATTERN);
if (patternTag != null) {
var pattern = HexPattern.DeserializeFromNBT(patternTag);
evt.getTooltipElements().add(Either.right(new PatternTooltipGreeble(
pattern,
tag.contains(ItemScroll.TAG_OP_ID, Tag.TAG_STRING)
NBTHelper.contains(stack, ItemScroll.TAG_OP_ID, Tag.TAG_STRING)
? PatternTooltipGreeble.ANCIENT_BG : PatternTooltipGreeble.PRISTINE_BG)));
}
} else if (stack.is(HexItems.SLATE.get()) && ItemSlate.hasPattern(stack)) {
var tag = stack.getOrCreateTag()
.getCompound("BlockEntityTag")
.getCompound(BlockEntitySlate.TAG_PATTERN);
var tag = NBTHelper.getCompound(NBTHelper.getOrCreateCompound(stack, "BlockEntityTag"), BlockEntitySlate.TAG_PATTERN);
if (tag != null) {
var pattern = HexPattern.DeserializeFromNBT(tag);
evt.getTooltipElements().add(Either.right(new PatternTooltipGreeble(
pattern,
PatternTooltipGreeble.SLATE_BG)));
}
}
}
}

View file

@ -5,9 +5,10 @@ import at.petrak.hexcasting.api.circle.BlockEntityAbstractImpetus;
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
import at.petrak.hexcasting.api.item.DataHolderItem;
import at.petrak.hexcasting.api.item.ManaHolderItem;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.misc.ManaConstants;
import at.petrak.hexcasting.api.spell.SpellDatum;
import at.petrak.hexcasting.api.spell.Widget;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.be.BlockEntityAkashicBookshelfRenderer;
import at.petrak.hexcasting.client.be.BlockEntitySlateRenderer;
import at.petrak.hexcasting.client.entity.WallScrollRenderer;
@ -28,64 +29,39 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.network.chat.Component;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.util.Mth;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ComparatorBlock;
import net.minecraft.world.level.block.RepeaterBlock;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.properties.ComparatorMode;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.ParticleFactoryRegisterEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.UnaryOperator;
public class RegisterClientStuff {
@SubscribeEvent
public static void init(FMLClientSetupEvent evt) {
evt.enqueueWork(() -> {
for (DataHolderItem dataHolder : new DataHolderItem[]{ HexItems.FOCUS.get(), HexItems.SPELLBOOK.get() }) {
ItemProperties.register((Item) dataHolder, ItemFocus.DATATYPE_PRED,
(stack, level, holder, holderID) -> {
var datum = dataHolder.readDatumTag(stack);
if (datum != null) {
var typename = datum.getAllKeys().iterator().next();
return switch (typename) {
case SpellDatum.TAG_ENTITY -> 1f;
case SpellDatum.TAG_DOUBLE -> 2f;
case SpellDatum.TAG_VEC3 -> 3f;
case SpellDatum.TAG_WIDGET -> 4f;
case SpellDatum.TAG_LIST -> 5f;
case SpellDatum.TAG_PATTERN -> 6f;
default -> 0f; // uh oh
};
}
return 0f;
});
ItemProperties.register((Item) dataHolder, ItemFocus.SEALED_PRED,
(stack, level, holder, holderID) -> dataHolder.canWrite(stack, SpellDatum.make(Widget.NULL)) ? 0f : 1f);
}
for (ItemPackagedSpell packager : new ItemPackagedSpell[]{
HexItems.CYPHER.get(),
HexItems.TRINKET.get(),
HexItems.ARTIFACT.get(),
}) {
ItemProperties.register(packager, ItemPackagedSpell.HAS_PATTERNS_PRED,
(stack, level, holder, holderID) ->
packager.getPatterns(stack) != null ? 1f : 0f
);
}
registerDataHolderOverrides(HexItems.FOCUS.get());
registerDataHolderOverrides(HexItems.SPELLBOOK.get());
registerPackagedSpellOverrides(HexItems.CYPHER.get());
registerPackagedSpellOverrides(HexItems.TRINKET.get());
registerPackagedSpellOverrides(HexItems.ARTIFACT.get());
ItemProperties.register(HexItems.BATTERY.get(), ItemManaBattery.MANA_PREDICATE,
(stack, level, holder, holderID) -> {
@ -96,58 +72,35 @@ public class RegisterClientStuff {
(stack, level, holder, holderID) -> {
var item = (ItemManaBattery) stack.getItem();
var max = item.getMaxMana(stack);
return (float) Math.sqrt((float) max / HexConfig.chargedCrystalManaAmount.get() / 10);
return (float) Math.sqrt((float) max / ManaConstants.CRYSTAL_UNIT / 10);
});
ItemProperties.register(HexItems.SCROLL.get(), ItemScroll.ANCIENT_PREDICATE,
(stack, level, holder, holderID) -> stack.getOrCreateTag().contains(ItemScroll.TAG_OP_ID) ? 1f : 0f);
(stack, level, holder, holderID) -> NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) ? 1f : 0f);
ItemProperties.register(HexItems.SLATE.get(), ItemSlate.WRITTEN_PRED,
(stack, level, holder, holderID) -> ItemSlate.hasPattern(stack) ? 1f : 0f);
var wands = new Item[]{
HexItems.WAND_OAK.get(),
HexItems.WAND_BIRCH.get(),
HexItems.WAND_SPRUCE.get(),
HexItems.WAND_JUNGLE.get(),
HexItems.WAND_DARK_OAK.get(),
HexItems.WAND_ACACIA.get(),
HexItems.WAND_AKASHIC.get(),
};
for (var wand : wands) {
ItemProperties.register(wand, ItemWand.FUNNY_LEVEL_PREDICATE,
(stack, level, holder, holderID) -> {
var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT);
if (name.contains("old")) {
return 1f;
} else if (name.contains("wand of the forest")) {
return 2f;
} else {
return 0f;
}
});
}
registerWandOverrides(HexItems.WAND_OAK.get());
registerWandOverrides(HexItems.WAND_BIRCH.get());
registerWandOverrides(HexItems.WAND_SPRUCE.get());
registerWandOverrides(HexItems.WAND_JUNGLE.get());
registerWandOverrides(HexItems.WAND_DARK_OAK.get());
registerWandOverrides(HexItems.WAND_ACACIA.get());
registerWandOverrides(HexItems.WAND_AKASHIC.get());
HexTooltips.init();
});
for (var cutout : new Block[]{
HexBlocks.CONJURED_LIGHT.get(),
HexBlocks.CONJURED_BLOCK.get(),
HexBlocks.AKASHIC_DOOR.get(),
HexBlocks.AKASHIC_TRAPDOOR.get(),
HexBlocks.SCONCE.get(),
}) {
ItemBlockRenderTypes.setRenderLayer(cutout, RenderType.cutout());
}
ItemBlockRenderTypes.setRenderLayer(HexBlocks.CONJURED_LIGHT.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.CONJURED_BLOCK.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.AKASHIC_DOOR.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.AKASHIC_TRAPDOOR.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.SCONCE.get(), RenderType.cutout());
for (var mipped : new Block[]{
HexBlocks.AKASHIC_LEAVES1.get(),
HexBlocks.AKASHIC_LEAVES2.get(),
HexBlocks.AKASHIC_LEAVES3.get(),
}) {
ItemBlockRenderTypes.setRenderLayer(mipped, RenderType.cutoutMipped());
}
ItemBlockRenderTypes.setRenderLayer(HexBlocks.AKASHIC_LEAVES1.get(), RenderType.cutoutMipped());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.AKASHIC_LEAVES2.get(), RenderType.cutoutMipped());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.AKASHIC_LEAVES3.get(), RenderType.cutoutMipped());
ItemBlockRenderTypes.setRenderLayer(HexBlocks.AKASHIC_RECORD.get(), RenderType.translucent());
@ -158,81 +111,188 @@ public class RegisterClientStuff {
private static void addScryingLensStuff() {
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, lensHand) -> state.getBlock() instanceof BlockAbstractImpetus,
(state, pos, observer, world, lensHand) -> {
(state, pos, observer, world, direction, lensHand) -> state.getBlock() instanceof BlockAbstractImpetus,
(lines, state, pos, observer, world, direction, lensHand) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
return beai.getScryingLensOverlay(state, pos, observer, world, lensHand);
} else {
return List.of();
beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction, lensHand);
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.NOTE_BLOCK,
(lines, state, pos, observer, world, direction, lensHand) -> {
int note = state.getValue(NoteBlock.NOTE);
float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F);
float gCol = Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F);
float bCol = Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F);
int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol);
var instrument = state.getValue(NoteBlock.INSTRUMENT);
lines.add(new Pair<>(
new ItemStack(Items.MUSIC_DISC_CHIRP),
new TextComponent(String.valueOf(instrument.ordinal()))
.withStyle(color(instrumentColor(instrument)))));
lines.add(new Pair<>(
new ItemStack(Items.NOTE_BLOCK),
new TextComponent(String.valueOf(note))
.withStyle(color(noteColor))));
});
ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_BOOKSHELF.get(),
(state, pos, observer, world, lensHand) -> {
if (!(world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile)) {
return List.of();
}
var out = new ArrayList<Pair<ItemStack, Component>>();
(lines, state, pos, observer, world, direction, lensHand) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var recordPos = tile.getRecordPos();
var pattern = tile.getPattern();
if (recordPos != null && pattern != null) {
out.add(new Pair<>(new ItemStack(HexBlocks.AKASHIC_RECORD.get()), new TranslatableComponent(
lines.add(new Pair<>(new ItemStack(HexBlocks.AKASHIC_RECORD.get()), new TranslatableComponent(
"hexcasting.tooltip.lens.akashic.bookshelf.location",
recordPos.toShortString()
)));
if (world.getBlockEntity(recordPos) instanceof BlockEntityAkashicRecord record) {
out.add(new Pair<>(new ItemStack(Items.BOOK), record.getDisplayAt(pattern)));
lines.add(new Pair<>(new ItemStack(Items.BOOK), record.getDisplayAt(pattern)));
}
}
}
return out;
});
ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_RECORD.get(),
((state, pos, observer, world, lensHand) -> {
if (!(world.getBlockEntity(pos) instanceof BlockEntityAkashicRecord tile)) {
return List.of();
}
ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_RECORD.get(),
(lines, state, pos, observer, world, direction, lensHand) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicRecord tile) {
int count = tile.getCount();
return List.of(new Pair<>(new ItemStack(HexBlocks.AKASHIC_BOOKSHELF.get()), new TranslatableComponent(
lines.add(new Pair<>(new ItemStack(HexBlocks.AKASHIC_BOOKSHELF.get()), new TranslatableComponent(
"hexcasting.tooltip.lens.akashic.record.count" + (count == 1 ? ".single" : ""),
count
)));
}));
ScryingLensOverlayRegistry.addDisplayer(Blocks.REDSTONE_WIRE,
(state, pos, observer, world, lensHand) -> List.of(
new Pair<>(
new ItemStack(Items.REDSTONE),
new TextComponent(String.valueOf(state.getValue(BlockStateProperties.POWER)))
.withStyle(ChatFormatting.RED))
));
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR,
(state, pos, observer, world, lensHand) -> List.of(
new Pair<>(
(lines, state, pos, observer, world, direction, lensHand) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(true);
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE),
new TextComponent(String.valueOf(state.getDirectSignal(world, pos, state.getValue(BlockStateProperties.HORIZONTAL_FACING))))
.withStyle(ChatFormatting.RED)),
new Pair<>(
new TextComponent(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE;
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE_TORCH),
new TextComponent(
state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE ? ">" : "-")
.withStyle(ChatFormatting.RED))));
compare ? ">=" : "-")
.withStyle(redstoneColor(compare ? 0 : 15))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER,
(state, pos, observer, world, lensHand) -> List.of(
new Pair<>(
new ItemStack(Items.REDSTONE),
new TextComponent(String.valueOf(state.getValue(RepeaterBlock.POWERED) ? 15 : 0))
.withStyle(ChatFormatting.RED)),
new Pair<>(
(lines, state, pos, observer, world, direction, lensHand) -> lines.add(new Pair<>(
new ItemStack(Items.CLOCK),
new TextComponent(String.valueOf(state.getValue(RepeaterBlock.DELAY)))
.withStyle(ChatFormatting.YELLOW))));
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction, lensHand) -> state.isSignalSource() && !state.is(Blocks.COMPARATOR),
(lines, state, pos, observer, world, direction, lensHand) -> {
int signalStrength = 0;
if (state.getBlock() instanceof RedStoneWireBlock)
signalStrength = state.getValue(RedStoneWireBlock.POWER);
else {
for (Direction dir : Direction.values())
signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir));
}
lines.add(0, new Pair<>(
new ItemStack(Items.REDSTONE),
new TextComponent(String.valueOf(signalStrength))
.withStyle(redstoneColor(signalStrength))));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction, lensHand) -> state.hasAnalogOutputSignal(),
(lines, state, pos, observer, world, direction, lensHand) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(false);
lines.add(
new Pair<>(
new ItemStack(Items.COMPARATOR),
new TextComponent(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
});
}
private static UnaryOperator<Style> color(int color) {
return (style) -> style.withColor(TextColor.fromRgb(color));
}
private static UnaryOperator<Style> redstoneColor(int power) {
return color(RedStoneWireBlock.getColorForPower(Mth.clamp(power, 0, 15)));
}
private static int instrumentColor(NoteBlockInstrument instrument) {
return switch(instrument) {
case BASEDRUM -> MaterialColor.STONE.col;
case SNARE, XYLOPHONE, PLING -> MaterialColor.SAND.col;
case HAT -> MaterialColor.QUARTZ.col;
case BASS -> MaterialColor.WOOD.col;
case FLUTE -> MaterialColor.CLAY.col;
case BELL -> MaterialColor.GOLD.col;
case GUITAR -> MaterialColor.WOOL.col;
case CHIME -> MaterialColor.ICE.col;
case IRON_XYLOPHONE -> MaterialColor.METAL.col;
case COW_BELL -> MaterialColor.COLOR_BROWN.col;
case DIDGERIDOO -> MaterialColor.COLOR_ORANGE.col;
case BIT -> MaterialColor.EMERALD.col;
case BANJO -> MaterialColor.COLOR_YELLOW.col;
default -> -1;
};
}
private static void registerDataHolderOverrides(DataHolderItem item) {
ItemProperties.register((Item) item, ItemFocus.DATATYPE_PRED,
(stack, level, holder, holderID) -> {
var datum = item.readDatumTag(stack);
String override = NBTHelper.getString(stack, DataHolderItem.TAG_OVERRIDE_VISUALLY);
String typename = null;
if (override != null) {
typename = override;
} else if (datum != null) {
typename = datum.getAllKeys().iterator().next();
}
return typename == null ? 0f : switch (typename) {
case SpellDatum.TAG_ENTITY -> 1f;
case SpellDatum.TAG_DOUBLE -> 2f;
case SpellDatum.TAG_VEC3 -> 3f;
case SpellDatum.TAG_WIDGET -> 4f;
case SpellDatum.TAG_LIST -> 5f;
case SpellDatum.TAG_PATTERN -> 6f;
default -> 0f; // uh oh
};
});
ItemProperties.register((Item) item, ItemFocus.SEALED_PRED,
(stack, level, holder, holderID) -> item.canWrite(stack, SpellDatum.make(Widget.NULL)) ? 0f : 1f);
}
private static void registerPackagedSpellOverrides(ItemPackagedSpell item) {
ItemProperties.register(item, ItemPackagedSpell.HAS_PATTERNS_PRED,
(stack, level, holder, holderID) ->
item.getPatterns(stack) != null ? 1f : 0f
);
}
private static void registerWandOverrides(ItemWand item) {
ItemProperties.register(item, ItemWand.FUNNY_LEVEL_PREDICATE,
(stack, level, holder, holderID) -> {
var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT);
if (name.contains("old")) {
return 1f;
} else if (name.contains("wand of the forest")) {
return 2f;
} else {
return 0f;
}
});
}
@SubscribeEvent(priority = EventPriority.LOWEST)

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.client
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.utils.HexUtils
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.utils.HexUtils
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack
@ -169,8 +169,7 @@ object RenderLib {
if (points.isEmpty()) {
return emptyList()
}
val mc = Minecraft.getInstance()
val zSeed = (mc.frameTime.toDouble() + (mc.level?.levelData?.gameTime ?: 0)) * speed
val zSeed = (ClientTickCounter.total.toDouble()) * speed
// Create our output list of zap points
val zappyPts = mutableListOf(points[0])
// For each segment in the original...

View file

@ -1,23 +1,22 @@
package at.petrak.hexcasting.client.gui
import at.petrak.hexcasting.api.utils.HexUtils
import at.petrak.hexcasting.api.utils.HexUtils.TAU
import at.petrak.hexcasting.client.RenderLib
import at.petrak.hexcasting.client.sound.GridSoundInstance
import at.petrak.hexcasting.api.mod.HexItemTags
import at.petrak.hexcasting.api.spell.casting.ControllerInfo
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternValidity
import at.petrak.hexcasting.api.spell.math.HexAngle
import at.petrak.hexcasting.api.spell.math.HexCoord
import at.petrak.hexcasting.api.spell.math.HexDir
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.utils.HexUtils
import at.petrak.hexcasting.client.RenderLib
import at.petrak.hexcasting.client.sound.GridSoundInstance
import at.petrak.hexcasting.common.items.HexItems
import at.petrak.hexcasting.common.items.ItemSpellbook
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.common.network.HexMessages
import at.petrak.hexcasting.common.network.MsgNewSpellPatternSyn
import at.petrak.hexcasting.common.network.MsgShiftScrollSyn
import at.petrak.hexcasting.api.spell.math.HexAngle
import at.petrak.hexcasting.api.spell.math.HexCoord
import at.petrak.hexcasting.api.spell.math.HexDir
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.mod.HexItemTags
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Minecraft
@ -32,10 +31,13 @@ import net.minecraft.world.InteractionHand
import net.minecraft.world.phys.Vec2
import kotlin.math.atan2
import kotlin.math.roundToInt
import kotlin.math.sqrt
class GuiSpellcasting(private val handOpenedWith: InteractionHand,
class GuiSpellcasting(
private val handOpenedWith: InteractionHand,
private var patterns: MutableList<ResolvedPattern>,
private var stackDescs: List<Component>) : Screen(TextComponent("")) {
private var stackDescs: List<Component>
) : Screen(TextComponent("")) {
private var drawState: PatternDrawState = PatternDrawState.BetweenPatterns
private val usedSpots: MutableSet<HexCoord> = HashSet()
@ -140,7 +142,7 @@ class GuiSpellcasting(private val handOpenedWith: InteractionHand,
val delta = mouse.add(anchor.negated())
val angle = atan2(delta.y, delta.x)
// 0 is right, increases clockwise(?)
val snappedAngle = angle.div(TAU.toFloat()).mod(6.0f)
val snappedAngle = angle.div(Mth.TWO_PI).mod(6.0f)
val newdir = HexDir.values()[(snappedAngle.times(6).roundToInt() + 1).mod(6)]
// The player might have a lousy aim, so set the new anchor point to the "ideal"
// location as if they had hit it exactly on the nose.
@ -344,7 +346,10 @@ class GuiSpellcasting(private val handOpenedWith: InteractionHand,
fun hexSize(): Float {
val hasLens = Minecraft.getInstance().player!!
.getItemInHand(HexUtils.OtherHand(this.handOpenedWith)).`is`(HexItems.SCRYING_LENS.get())
return this.width.toFloat() / if (hasLens) 48.0f else 32.0f
// Originally, we allowed 32 dots across. Assuming a 1920x1080 screen this allowed like 500-odd area.
// Let's be generous and give them 512.
val baseScale = sqrt(this.width.toDouble() * this.height / 512.0)
return baseScale.toFloat() * if (hasLens) 0.75f else 1f
}
fun coordsOffset(): Vec2 = Vec2(this.width.toFloat() * 0.5f, this.height.toFloat() * 0.5f)

View file

@ -77,7 +77,7 @@ public class PatternTooltipGreeble implements ClientTooltipComponent, TooltipCom
outer, outer, null);
RenderLib.drawLineSeq(mat, this.zappyPoints, 2f, 0,
innerDark, innerLight,
ClientTickCounter.getTickCount() / 40f);
ClientTickCounter.total / 40f);
RenderLib.drawSpot(mat, this.zappyPoints.get(0), 2.5f, 1f, 0.1f, 0.15f, 0.6f);
for (var dot : this.pathfinderDots) {

View file

@ -102,8 +102,8 @@ public class ConjureParticle extends TextureSheetParticle {
@Override
public void begin(BufferBuilder buf, TextureManager texMan) {
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
RenderSystem.depthMask(false);
RenderSystem.enableDepthTest();
RenderSystem.depthMask(false);
RenderSystem.enableBlend();
RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);

View file

@ -49,8 +49,8 @@ class GridSoundInstance(val player: Player) : AbstractTickableSoundInstance(HexS
}
private fun calculateVectorFromPitchAndYaw(pitch: Float, yaw: Float): Vec3 {
val radiansPitch = pitch * (Math.PI.toFloat() / 180f)
val radiansYaw = -yaw * (Math.PI.toFloat() / 180f)
val radiansPitch = pitch * Mth.DEG_TO_RAD
val radiansYaw = -yaw * Mth.DEG_TO_RAD
val xComponent = Mth.cos(radiansYaw).toDouble()
val zComponent = Mth.sin(radiansYaw).toDouble()
val azimuthHorizontal = Mth.cos(radiansPitch).toDouble()

View file

@ -0,0 +1,33 @@
package at.petrak.hexcasting.common.blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
public class BlockBurns extends Block {
private final int flammability;
private final int spreadSpeed;
public BlockBurns(Properties props, int flammability, int spreadSpeed) {
super(props);
this.flammability = flammability;
this.spreadSpeed = spreadSpeed;
}
@Override
public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return true;
}
@Override
public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return flammability;
}
@Override
public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return spreadSpeed;
}
}

View file

@ -3,9 +3,7 @@ package at.petrak.hexcasting.common.blocks;
import at.petrak.hexcasting.HexMod;
import at.petrak.hexcasting.api.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.spell.DatumType;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicFloodfiller;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord;
import at.petrak.hexcasting.common.blocks.akashic.*;
import at.petrak.hexcasting.common.blocks.circles.BlockEmptyImpetus;
import at.petrak.hexcasting.common.blocks.circles.BlockSlate;
import at.petrak.hexcasting.common.blocks.circles.directrix.BlockEmptyDirectrix;
@ -144,51 +142,51 @@ public class HexBlocks {
public static final RegistryObject<AmethystBlock> AMETHYST_TILES = blockItem("amethyst_tiles",
() -> new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK)));
public static final RegistryObject<Block> SCROLL_PAPER = blockItem("scroll_paper",
() -> new Block(papery(MaterialColor.TERRACOTTA_WHITE)));
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_WHITE), 100, 60));
public static final RegistryObject<Block> ANCIENT_SCROLL_PAPER = blockItem("ancient_scroll_paper",
() -> new Block(papery(MaterialColor.TERRACOTTA_ORANGE)));
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_ORANGE), 100, 60));
public static final RegistryObject<Block> SCROLL_PAPER_LANTERN = blockItem("scroll_paper_lantern",
() -> new Block(papery(MaterialColor.TERRACOTTA_WHITE).lightLevel($ -> 15)));
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_WHITE).lightLevel($ -> 15), 100, 60));
public static final RegistryObject<Block> ANCIENT_SCROLL_PAPER_LANTERN = blockItem(
"ancient_scroll_paper_lantern",
() -> new Block(papery(MaterialColor.TERRACOTTA_ORANGE).lightLevel($ -> 12)));
() -> new BlockBurns(papery(MaterialColor.TERRACOTTA_ORANGE).lightLevel($ -> 12), 100, 60));
public static final RegistryObject<BlockSconce> SCONCE = blockItem("amethyst_sconce",
() -> new BlockSconce(BlockBehaviour.Properties.of(Material.AMETHYST, MaterialColor.COLOR_PURPLE)
.sound(SoundType.AMETHYST)
.strength(1f)
.lightLevel($ -> 15)));
public static final RegistryObject<BlockAxis> AKASHIC_LOG_STRIPPED = blockItem("akashic_log_stripped",
() -> new BlockAxis(akashicWoody()));
() -> new BlockAkashicLog(akashicWoody()));
public static final RegistryObject<BlockStrippable> AKASHIC_LOG = blockItem("akashic_log",
() -> new BlockStrippable(akashicWoody(), AKASHIC_LOG_STRIPPED));
() -> new BlockAkashicWood(akashicWoody(), AKASHIC_LOG_STRIPPED));
public static final RegistryObject<Block> AKASHIC_WOOD_STRIPPED = blockItem("akashic_wood_stripped",
() -> new Block(akashicWoody()));
() -> new BlockBurns(akashicWoody(), 5, 5));
public static final RegistryObject<BlockStrippable> AKASHIC_WOOD = blockItem("akashic_wood",
() -> new BlockStrippable(akashicWoody(), AKASHIC_WOOD_STRIPPED));
() -> new BlockAkashicWood(akashicWoody(), AKASHIC_WOOD_STRIPPED));
public static final RegistryObject<Block> AKASHIC_PLANKS = blockItem("akashic_planks",
() -> new Block(akashicWoody()));
() -> new BlockBurns(akashicWoody(), 20, 5));
public static final RegistryObject<Block> AKASHIC_PANEL = blockItem("akashic_panel",
() -> new Block(akashicWoody()));
() -> new BlockBurns(akashicWoody(), 20, 5));
public static final RegistryObject<Block> AKASHIC_TILE = blockItem("akashic_tile",
() -> new Block(akashicWoody()));
() -> new BlockBurns(akashicWoody(), 20, 5));
public static final RegistryObject<DoorBlock> AKASHIC_DOOR = blockItem("akashic_door",
() -> new DoorBlock(akashicWoody().noOcclusion()));
public static final RegistryObject<TrapDoorBlock> AKASHIC_TRAPDOOR = blockItem("akashic_trapdoor",
() -> new TrapDoorBlock(akashicWoody().noOcclusion()));
public static final RegistryObject<StairBlock> AKASHIC_STAIRS = blockItem("akashic_stairs",
() -> new StairBlock(() -> AKASHIC_PLANKS.get().defaultBlockState(), akashicWoody().noOcclusion()));
() -> new BlockAkashicStairs(() -> AKASHIC_PLANKS.get().defaultBlockState(), akashicWoody().noOcclusion()));
public static final RegistryObject<SlabBlock> AKASHIC_SLAB = blockItem("akashic_slab",
() -> new SlabBlock(akashicWoody().noOcclusion()));
() -> new BlockAkashicSlab(akashicWoody().noOcclusion()));
public static final RegistryObject<WoodButtonBlock> AKASHIC_BUTTON = blockItem("akashic_button",
() -> new WoodButtonBlock(akashicWoody().noOcclusion()));
() -> new WoodButtonBlock(akashicWoody().noCollission()));
public static final RegistryObject<PressurePlateBlock> AKASHIC_PRESSURE_PLATE = blockItem("akashic_pressure_plate",
() -> new PressurePlateBlock(PressurePlateBlock.Sensitivity.EVERYTHING, akashicWoody().noOcclusion()));
public static final RegistryObject<LeavesBlock> AKASHIC_LEAVES1 = blockItem("akashic_leaves1",
() -> new LeavesBlock(leaves(MaterialColor.COLOR_PURPLE)));
public static final RegistryObject<LeavesBlock> AKASHIC_LEAVES2 = blockItem("akashic_leaves2",
() -> new LeavesBlock(leaves(MaterialColor.COLOR_BLUE)));
public static final RegistryObject<LeavesBlock> AKASHIC_LEAVES3 = blockItem("akashic_leaves3",
() -> new LeavesBlock(leaves(MaterialColor.COLOR_YELLOW)));
() -> new PressurePlateBlock(PressurePlateBlock.Sensitivity.EVERYTHING, akashicWoody().noCollission()));
public static final RegistryObject<BlockAkashicLeaves> AKASHIC_LEAVES1 = blockItem("akashic_leaves1",
() -> new BlockAkashicLeaves(leaves(MaterialColor.COLOR_PURPLE)));
public static final RegistryObject<BlockAkashicLeaves> AKASHIC_LEAVES2 = blockItem("akashic_leaves2",
() -> new BlockAkashicLeaves(leaves(MaterialColor.COLOR_BLUE)));
public static final RegistryObject<BlockAkashicLeaves> AKASHIC_LEAVES3 = blockItem("akashic_leaves3",
() -> new BlockAkashicLeaves(leaves(MaterialColor.COLOR_YELLOW)));
private static boolean never(Object... args) {
return false;

View file

@ -13,6 +13,7 @@ import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.Mirror;
@ -109,6 +110,21 @@ public class BlockAkashicBookshelf extends BlockAkashicFloodfiller implements En
return this.defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite());
}
@Override
public float getEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) {
return 1;
}
@Override
public boolean hasAnalogOutputSignal(BlockState pState) {
return true;
}
@Override
public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) {
return pState.getValue(DATUM_TYPE).ordinal();
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {

View file

@ -0,0 +1,28 @@
package at.petrak.hexcasting.common.blocks.akashic;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockState;
public class BlockAkashicLeaves extends LeavesBlock {
public BlockAkashicLeaves(Properties props) {
super(props);
}
@Override
public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return true;
}
@Override
public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 60;
}
@Override
public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 30;
}
}

View file

@ -0,0 +1,28 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.common.blocks.decoration.BlockAxis;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public class BlockAkashicLog extends BlockAxis {
public BlockAkashicLog(Properties props) {
super(props);
}
@Override
public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return true;
}
@Override
public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 5;
}
@Override
public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 5;
}
}

View file

@ -24,6 +24,20 @@ public class BlockAkashicRecord extends Block implements EntityBlock {
return new BlockEntityAkashicRecord(pPos, pState);
}
@Override
public boolean hasAnalogOutputSignal(BlockState pState) {
return true;
}
@Override
public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) {
BlockEntity be = pLevel.getBlockEntity(pPos);
if (be instanceof BlockEntityAkashicRecord record) {
return Math.min(15, record.getCount());
}
return 0;
}
@Override
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
var seen = new HashSet<BlockPos>();

View file

@ -0,0 +1,28 @@
package at.petrak.hexcasting.common.blocks.akashic;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.state.BlockState;
public class BlockAkashicSlab extends SlabBlock {
public BlockAkashicSlab(Properties props) {
super(props);
}
@Override
public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return true;
}
@Override
public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 20;
}
@Override
public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 5;
}
}

View file

@ -0,0 +1,30 @@
package at.petrak.hexcasting.common.blocks.akashic;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.StairBlock;
import net.minecraft.world.level.block.state.BlockState;
import java.util.function.Supplier;
public class BlockAkashicStairs extends StairBlock {
public BlockAkashicStairs(Supplier<BlockState> state, Properties properties) {
super(state, properties);
}
@Override
public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return true;
}
@Override
public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 20;
}
@Override
public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 5;
}
}

View file

@ -0,0 +1,33 @@
package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.common.blocks.decoration.BlockStrippable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import java.util.function.Supplier;
public class BlockAkashicWood extends BlockStrippable {
public BlockAkashicWood(Properties props, Supplier<? extends Block> stripped) {
super(props, stripped);
}
@Override
public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return true;
}
@Override
public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 5;
}
@Override
public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return 5;
}
}

View file

@ -6,6 +6,7 @@ import com.mojang.datafixers.util.Pair;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
@ -15,6 +16,8 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@ -50,9 +53,12 @@ public class BlockEntityStoredPlayerImpetus extends BlockEntityAbstractImpetus {
}
@Override
public List<Pair<ItemStack, Component>> getScryingLensOverlay(BlockState state, BlockPos pos, LocalPlayer observer,
ClientLevel world, InteractionHand lensHand) {
var list = super.getScryingLensOverlay(state, pos, observer, world, lensHand);
@OnlyIn(Dist.CLIENT)
public void applyScryingLensOverlay(List<Pair<ItemStack, Component>> lines,
BlockState state, BlockPos pos, LocalPlayer observer,
ClientLevel world,
Direction hitFace, InteractionHand lensHand) {
super.applyScryingLensOverlay(lines, state, pos, observer, world, hitFace, lensHand);
var bound = this.getPlayer();
if (bound != null) {
@ -60,13 +66,11 @@ public class BlockEntityStoredPlayerImpetus extends BlockEntityAbstractImpetus {
String name = bound.getScoreboardName();
tag.putString("SkullOwner", name);
var head = new ItemStack(Items.PLAYER_HEAD, 1, tag);
list.add(new Pair<>(head, new TranslatableComponent("hexcasting.tooltip.lens.impetus.storedplayer", name)));
lines.add(new Pair<>(head, new TranslatableComponent("hexcasting.tooltip.lens.impetus.storedplayer", name)));
} else {
list.add(new Pair<>(new ItemStack(Items.BARRIER),
lines.add(new Pair<>(new ItemStack(Items.BARRIER),
new TranslatableComponent("hexcasting.tooltip.lens.impetus.storedplayer.none")));
}
return list;
}
@Override

View file

@ -35,7 +35,7 @@ public class BlockStoredPlayerImpetus extends BlockAbstractImpetus {
BlockHitResult pHit) {
if (pLevel.getBlockEntity(pPos) instanceof BlockEntityStoredPlayerImpetus tile) {
var usedStack = pPlayer.getItemInHand(pHand);
var datumContainer = usedStack.getCapability(HexCapabilities.DATUM).resolve();
var datumContainer = HexCapabilities.getCapability(usedStack, HexCapabilities.DATUM);
if (datumContainer.isPresent()) {
if (pLevel instanceof ServerLevel level) {
var stored = datumContainer.get().readDatum(level);
@ -44,9 +44,9 @@ public class BlockStoredPlayerImpetus extends BlockAbstractImpetus {
if (entity instanceof Player) {
// phew, we got something
tile.setPlayer(entity.getUUID());
tile.setChanged();
level.sendBlockUpdated(pPos, pState, pState, Block.UPDATE_CLIENTS);
pLevel.playSound(pPlayer, pPos, HexSounds.IMPETUS_STOREDPLAYER_DING.get(), SoundSource.BLOCKS,
pLevel.playSound(null, pPos, HexSounds.IMPETUS_STOREDPLAYER_DING.get(), SoundSource.BLOCKS,
1f, 1f);
}
}

View file

@ -1,16 +1,13 @@
package at.petrak.hexcasting.common.blocks.decoration;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.ToolAction;
import net.minecraftforge.common.ToolActions;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import java.util.function.Supplier;
// aka, Blockg
@ -25,8 +22,7 @@ public class BlockStrippable extends RotatedPillarBlock {
@Nullable
@Override
public BlockState getToolModifiedState(BlockState state, Level world, BlockPos pos, Player player, ItemStack stack,
ToolAction toolAction) {
public BlockState getToolModifiedState(BlockState state, UseOnContext context, ToolAction toolAction, boolean simulate) {
if (toolAction == ToolActions.AXE_STRIP) {
var out = stripped.get().defaultBlockState();
if (state.hasProperty(AXIS)) {

View file

@ -1,9 +1,13 @@
package at.petrak.hexcasting.common.casting;
import at.petrak.hexcasting.api.PatternRegistry;
import at.petrak.hexcasting.api.misc.ManaConstants;
import at.petrak.hexcasting.api.spell.Operator;
import at.petrak.hexcasting.api.spell.SpellDatum;
import at.petrak.hexcasting.api.spell.Widget;
import at.petrak.hexcasting.api.spell.math.HexAngle;
import at.petrak.hexcasting.api.spell.math.HexDir;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.casting.operators.*;
import at.petrak.hexcasting.common.casting.operators.akashic.OpAkashicRead;
@ -16,6 +20,7 @@ import at.petrak.hexcasting.common.casting.operators.eval.OpEvalDelay;
import at.petrak.hexcasting.common.casting.operators.eval.OpForEach;
import at.petrak.hexcasting.common.casting.operators.lists.*;
import at.petrak.hexcasting.common.casting.operators.math.*;
import at.petrak.hexcasting.common.casting.operators.math.bit.*;
import at.petrak.hexcasting.common.casting.operators.math.logic.*;
import at.petrak.hexcasting.common.casting.operators.math.trig.*;
import at.petrak.hexcasting.common.casting.operators.selectors.OpGetCaster;
@ -29,9 +34,6 @@ import at.petrak.hexcasting.common.casting.operators.spells.sentinel.OpGetSentin
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.OpGetSentinelWayfind;
import at.petrak.hexcasting.common.casting.operators.stack.*;
import at.petrak.hexcasting.common.items.HexItems;
import at.petrak.hexcasting.api.spell.math.HexAngle;
import at.petrak.hexcasting.api.spell.math.HexDir;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import it.unimi.dsi.fastutil.booleans.BooleanArrayList;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.phys.Vec3;
@ -81,11 +83,12 @@ public class RegisterPatterns {
// == Modify Stack ==
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("d", HexDir.EAST), prefix("const/null"), Widget.NULL);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aadaa", HexDir.EAST), prefix("duplicate"),
OpDuplicate.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aadaadaa", HexDir.EAST), prefix("duplicate_n"),
OpDuplicateN.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qwaeawqaeaqa", HexDir.NORTH_WEST), prefix("stack_len"),
OpStackSize.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aawdd", HexDir.EAST), prefix("swap"), OpSwap.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ddad", HexDir.WEST), prefix("fisherman"),
OpFisherman.INSTANCE);
@ -106,6 +109,12 @@ public class RegisterPatterns {
OpAbsLen.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wedew", HexDir.NORTH_WEST), prefix("pow_proj"),
OpPowProj.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ewq", HexDir.EAST), prefix("floor"),
OpFloor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qwe", HexDir.EAST), prefix("ceil"),
OpCeil.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqqqqq", HexDir.EAST), prefix("construct_vec"),
OpConstructVec.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qeeeee", HexDir.EAST), prefix("deconstruct_vec"),
@ -113,12 +122,14 @@ public class RegisterPatterns {
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqaww", HexDir.NORTH_WEST), prefix("coerce_axial"),
OpCoerceToAxial.INSTANCE);
// == Logic ==
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wdw", HexDir.NORTH_EAST), prefix("and"),
OpAnd.INSTANCE);
OpBoolAnd.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("waw", HexDir.SOUTH_EAST), prefix("or"),
OpOr.INSTANCE);
OpBoolOr.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dwa", HexDir.NORTH_WEST), prefix("xor"),
OpXor.INSTANCE);
OpBoolXor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("e", HexDir.SOUTH_EAST), prefix("greater"),
new OpCompare((a, b) -> a > b));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("q", HexDir.SOUTH_WEST), prefix("less"),
@ -132,16 +143,14 @@ public class RegisterPatterns {
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("da", HexDir.EAST), prefix("not_equals"),
new OpEquality(true));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dw", HexDir.NORTH_WEST), prefix("not"),
OpNot.INSTANCE);
OpBoolNot.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aw", HexDir.NORTH_EAST), prefix("identity"),
OpIdentityKindOf.INSTANCE);
OpBoolIdentityKindOf.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ewq", HexDir.EAST), prefix("floor"),
OpFloor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qwe", HexDir.EAST), prefix("ceil"),
OpCeil.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqaqe", HexDir.NORTH_WEST), prefix("logarithm"),
OpLog.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqqq", HexDir.NORTH_WEST), prefix("random"),
OpRandom.INSTANCE);
// == Advanced Math ==
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqaa", HexDir.SOUTH_EAST), prefix("sin"),
OpSin.INSTANCE);
@ -156,8 +165,21 @@ public class RegisterPatterns {
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eadeeeeew", HexDir.NORTH_EAST), prefix("arctan"),
OpArcTan.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqqq", HexDir.NORTH_WEST), prefix("random"),
OpRandom.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqaqe", HexDir.NORTH_WEST), prefix("logarithm"),
OpLog.INSTANCE);
// == Sets ==
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wdweaqa", HexDir.NORTH_EAST), prefix("and_bit"),
OpAnd.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("waweaqa", HexDir.SOUTH_EAST), prefix("or_bit"),
OpOr.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dwaeaqa", HexDir.NORTH_WEST), prefix("xor_bit"),
OpXor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dweaqa", HexDir.NORTH_WEST), prefix("not_bit"),
OpNot.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aweaqa", HexDir.NORTH_EAST), prefix("to_set"),
OpToSet.INSTANCE);
// == Spells ==
@ -205,14 +227,14 @@ public class RegisterPatterns {
OpBeep.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("waqqqqq", HexDir.EAST), prefix("craft/cypher"),
new OpMakePackagedSpell<>(HexItems.CYPHER.get(), 100_000));
new OpMakePackagedSpell<>(HexItems.CYPHER.get(), ManaConstants.CRYSTAL_UNIT));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wwaqqqqqeaqeaeqqqeaeq", HexDir.EAST),
prefix("craft/trinket"),
new OpMakePackagedSpell<>(HexItems.TRINKET.get(), 500_000));
new OpMakePackagedSpell<>(HexItems.TRINKET.get(), 5 * ManaConstants.CRYSTAL_UNIT));
PatternRegistry.mapPattern(
HexPattern.FromAnglesSig("wwaqqqqqeawqwqwqwqwqwwqqeadaeqqeqqeadaeqq", HexDir.EAST),
prefix("craft/artifact"),
new OpMakePackagedSpell<>(HexItems.ARTIFACT.get(), 1_000_000));
new OpMakePackagedSpell<>(HexItems.ARTIFACT.get(), 10 * ManaConstants.CRYSTAL_UNIT));
PatternRegistry.mapPattern(
HexPattern.FromAnglesSig("aqqqaqwwaqqqqqeqaqqqawwqwqwqwqwqw", HexDir.SOUTH_WEST),
prefix("craft/battery"),
@ -221,35 +243,35 @@ public class RegisterPatterns {
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqaqwawaw", HexDir.NORTH_WEST),
prefix("potion/weakness"),
new OpPotionEffect(MobEffects.WEAKNESS, 10_000 / 10, true, false, false));
new OpPotionEffect(MobEffects.WEAKNESS, ManaConstants.DUST_UNIT / 10, true, false, false));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqawwawawd", HexDir.WEST),
prefix("potion/levitation"),
new OpPotionEffect(MobEffects.LEVITATION, 10_000 / 5, false, false, false));
new OpPotionEffect(MobEffects.LEVITATION, ManaConstants.DUST_UNIT / 5, false, false, false));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqaewawawe", HexDir.SOUTH_WEST),
prefix("potion/wither"),
new OpPotionEffect(MobEffects.WITHER, 10_000, true, false, false));
new OpPotionEffect(MobEffects.WITHER, ManaConstants.DUST_UNIT, true, false, false));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqadwawaww", HexDir.SOUTH_EAST),
prefix("potion/poison"),
new OpPotionEffect(MobEffects.POISON, 10_000 / 3, true, false, false));
new OpPotionEffect(MobEffects.POISON, ManaConstants.DUST_UNIT / 3, true, false, false));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqadwawaw", HexDir.SOUTH_EAST),
prefix("potion/slowness"),
new OpPotionEffect(MobEffects.MOVEMENT_SLOWDOWN, 10_000 / 3, true, false, false));
new OpPotionEffect(MobEffects.MOVEMENT_SLOWDOWN, ManaConstants.DUST_UNIT / 3, true, false, false));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqaawawaedd", HexDir.NORTH_WEST),
prefix("potion/regeneration"),
new OpPotionEffect(MobEffects.REGENERATION, 10_000, true, true, true), true);
new OpPotionEffect(MobEffects.REGENERATION, ManaConstants.DUST_UNIT, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqaawawaeqdd", HexDir.WEST),
prefix("potion/night_vision"),
new OpPotionEffect(MobEffects.NIGHT_VISION, 10_000 / 5, false, true, true), true);
new OpPotionEffect(MobEffects.NIGHT_VISION, ManaConstants.DUST_UNIT / 5, false, true, true), true);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqaawawaeqqdd", HexDir.SOUTH_WEST),
prefix("potion/absorption"),
new OpPotionEffect(MobEffects.ABSORPTION, 10_000, true, true, true), true);
new OpPotionEffect(MobEffects.ABSORPTION, ManaConstants.DUST_UNIT, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qaawawaeqqqdd", HexDir.SOUTH_EAST),
prefix("potion/haste"),
new OpPotionEffect(MobEffects.DIG_SPEED, 10_000 / 3, true, true, true), true);
new OpPotionEffect(MobEffects.DIG_SPEED, ManaConstants.DUST_UNIT / 3, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aawawaeqqqqdd", HexDir.EAST),
prefix("potion/strength"),
new OpPotionEffect(MobEffects.DAMAGE_BOOST, 10_000 / 3, true, true, true), true);
new OpPotionEffect(MobEffects.DAMAGE_BOOST, ManaConstants.DUST_UNIT / 3, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("waeawae", HexDir.EAST),
prefix("sentinel/create"),
@ -309,12 +331,21 @@ public class RegisterPatterns {
OpRead.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("deeeee", HexDir.EAST), prefix("write"),
OpWrite.INSTANCE);
// lorge boy
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aqqqqqe", HexDir.EAST), prefix("readable"),
OpReadable.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("deeeeeq", HexDir.EAST), prefix("writable"),
OpWritable.INSTANCE);
// lorge boyes
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wawqwqwqwqwqw", HexDir.EAST),
prefix("read/entity"), OpTheCoolerRead.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wawqwqwqwqwqwew", HexDir.EAST),
prefix("readable/entity"), OpTheCoolerReadable.INSTANCE);
// == Consts ==
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("d", HexDir.EAST), prefix("const/null"), Widget.NULL);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqea", HexDir.NORTH_WEST), prefix("const/vec/px"),
Operator.makeConstantOp(SpellDatum.make(new Vec3(1.0, 0.0, 0.0))));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqew", HexDir.NORTH_WEST), prefix("const/vec/py"),
@ -419,6 +450,10 @@ public class RegisterPatterns {
OpIndexOf.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("edqdewaqa", HexDir.SOUTH_WEST), prefix("list_remove"),
OpRemove.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qaeaqwded", HexDir.NORTH_WEST), prefix("slice"),
OpSlice.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wqaeaqw", HexDir.NORTH_WEST), prefix("modify_in_place"),
OpModifyInPlace.INSTANCE);
} catch (PatternRegistry.RegisterPatternException exn) {
exn.printStackTrace();
@ -455,13 +490,9 @@ public class RegisterPatterns {
PatternRegistry.addSpecialHandler(prefix("mask"), pat -> {
var directions = pat.directions();
HexDir flatDir;
if (pat.angles().isEmpty()) {
return null;
} else if (pat.angles().get(0) == HexAngle.LEFT_BACK) {
HexDir flatDir = pat.startDir();
if (!pat.angles().isEmpty() && pat.angles().get(0) == HexAngle.LEFT_BACK) {
flatDir = directions.get(0).rotatedBy(HexAngle.LEFT);
} else {
flatDir = pat.startDir();
}
var mask = new BooleanArrayList();

View file

@ -1,18 +1,19 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.misc.ManaConstants
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.level.ClipContext
import net.minecraft.world.phys.HitResult
import net.minecraft.world.phys.Vec3
object OpBlockAxisRaycast : ConstManaOperator {
override val argc = 2
override val manaCost = 10
override val manaCost = ManaConstants.DUST_UNIT / 100
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val origin: Vec3 = args.getChecked(0)
val look: Vec3 = args.getChecked(1)

View file

@ -1,18 +1,19 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.misc.ManaConstants
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.level.ClipContext
import net.minecraft.world.phys.HitResult
import net.minecraft.world.phys.Vec3
object OpBlockRaycast : ConstManaOperator {
override val argc = 2
override val manaCost = 10
override val manaCost = ManaConstants.DUST_UNIT / 100
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val origin: Vec3 = args.getChecked(0)
val look: Vec3 = args.getChecked(1)

View file

@ -1,18 +1,19 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.misc.ManaConstants
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.entity.projectile.ProjectileUtil
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
object OpEntityRaycast : ConstManaOperator {
override val argc = 2
override val manaCost = 10
override val manaCost = ManaConstants.DUST_UNIT / 100
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val origin: Vec3 = args.getChecked(0)
val look: Vec3 = args.getChecked(1)

View file

@ -5,9 +5,9 @@ import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.common.misc.PlayerPositionRecorder
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec3
object OpEntityVelocity : ConstManaOperator {
override val argc = 1
@ -17,9 +17,8 @@ object OpEntityVelocity : ConstManaOperator {
ctx.assertEntityInRange(e)
// Player velocity is jank. Really jank. This is the best we can do.
if (e is Player) {
val prevPosition = Vec3(e.xOld, e.yOld, e.zOld)
return spellListOf(e.position().subtract(prevPosition))
if (e is ServerPlayer) {
return spellListOf(PlayerPositionRecorder.getMotion(e))
}
return spellListOf(e.deltaMovement)

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
object OpRead : ConstManaOperator {
@ -11,11 +11,11 @@ object OpRead : ConstManaOperator {
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val (handStack, hand) = ctx.getHeldItemToOperateOn {
val datum = it.getCapability(HexCapabilities.DATUM).resolve()
datum.isPresent && (datum.get().readDatum(ctx.world) != null || datum.get().emptyDatum() != null)
val datum = HexCapabilities.getCapability(it, HexCapabilities.DATUM)
!it.isEmpty && datum.isPresent && (datum.get().readDatum(ctx.world) != null || datum.get().emptyDatum() != null)
}
val datumHolder = handStack.getCapability(HexCapabilities.DATUM).resolve()
val datumHolder = HexCapabilities.getCapability(handStack, HexCapabilities.DATUM)
if (!datumHolder.isPresent)
throw MishapBadOffhandItem.of(handStack, hand, "iota.read")

View file

@ -0,0 +1,26 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
object OpReadable : ConstManaOperator {
override val argc = 0
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val (handStack) = ctx.getHeldItemToOperateOn {
HexCapabilities.getCapability(it, HexCapabilities.DATUM).isPresent
}
val datumHolder = HexCapabilities.getCapability(handStack, HexCapabilities.DATUM)
if (!datumHolder.isPresent)
return spellListOf(0.0)
if (datumHolder.get().readDatum(ctx.world) == null && datumHolder.get().emptyDatum() == null)
return spellListOf(0.0)
return spellListOf(1.0)
}
}

View file

@ -16,13 +16,13 @@ object OpTheCoolerRead : ConstManaOperator {
ctx: CastingContext
): List<SpellDatum<*>> {
val target = args.getChecked<ItemEntity>(0)
val stack = target.item
val datumHolder = stack.getCapability(HexCapabilities.DATUM).resolve()
if (!datumHolder.isPresent)
throw MishapBadItem.of(target, "iota.read")
ctx.assertEntityInRange(target)
val stack = target.item
val datumHolder = HexCapabilities.getCapability(stack, HexCapabilities.DATUM)
if (!datumHolder.isPresent)
throw MishapBadItem.of(target, "iota.read")
val datum = datumHolder.get().readDatum(ctx.world)
?: datumHolder.get().emptyDatum()

View file

@ -0,0 +1,32 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.entity.item.ItemEntity
object OpTheCoolerReadable : ConstManaOperator {
override val argc = 1
override fun execute(
args: List<SpellDatum<*>>,
ctx: CastingContext
): List<SpellDatum<*>> {
val target = args.getChecked<ItemEntity>(0)
ctx.assertEntityInRange(target)
val stack = target.item
val datumHolder = HexCapabilities.getCapability(stack, HexCapabilities.DATUM)
if (!datumHolder.isPresent)
return spellListOf(0.0)
if (datumHolder.get().readDatum(ctx.world) == null && datumHolder.get().emptyDatum() == null)
return spellListOf(0.0)
return spellListOf(1.0)
}
}

View file

@ -0,0 +1,35 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapOthersName
object OpWritable : ConstManaOperator {
override val argc = 1
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val datum = args[0]
val (handStack) = ctx.getHeldItemToOperateOn {
val datumHolder = HexCapabilities.getCapability(it, HexCapabilities.DATUM)
datumHolder.isPresent && datumHolder.get().writeDatum(datum, true)
}
val datumHolder = HexCapabilities.getCapability(handStack, HexCapabilities.DATUM)
if (!datumHolder.isPresent)
return spellListOf(0.0)
if (!datumHolder.get().writeDatum(datum, true))
return spellListOf(0.0)
val trueName = MishapOthersName.getTrueNameFromDatum(datum, ctx.caster)
if (trueName != null)
return spellListOf(0.0)
return spellListOf(1.0)
}
}

View file

@ -1,11 +1,11 @@
package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.spell.mishaps.MishapOthersName
@ -19,12 +19,12 @@ object OpWrite : SpellOperator {
val datum = args[0]
val (handStack, hand) = ctx.getHeldItemToOperateOn {
val datumHolder = it.getCapability(HexCapabilities.DATUM).resolve()
val datumHolder = HexCapabilities.getCapability(it, HexCapabilities.DATUM)
datumHolder.isPresent && datumHolder.get().writeDatum(datum, true)
}
val datumHolder = handStack.getCapability(HexCapabilities.DATUM).resolve()
val datumHolder = HexCapabilities.getCapability(handStack, HexCapabilities.DATUM)
if (!datumHolder.isPresent)
throw MishapBadOffhandItem.of(handStack, hand, "iota.write")
@ -45,12 +45,12 @@ object OpWrite : SpellOperator {
private data class Spell(val datum: SpellDatum<*>) : RenderedSpell {
override fun cast(ctx: CastingContext) {
val (handStack) = ctx.getHeldItemToOperateOn {
val datumHolder = it.getCapability(HexCapabilities.DATUM).resolve()
val datumHolder = HexCapabilities.getCapability(it, HexCapabilities.DATUM)
datumHolder.isPresent && datumHolder.get().writeDatum(datum, true)
}
val datumHolder = handStack.getCapability(HexCapabilities.DATUM).resolve()
val datumHolder = HexCapabilities.getCapability(handStack, HexCapabilities.DATUM)
if (datumHolder.isPresent) {
datumHolder.get().writeDatum(datum, false)

View file

@ -1,19 +1,20 @@
package at.petrak.hexcasting.common.casting.operators.akashic
import at.petrak.hexcasting.api.misc.ManaConstants
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicRecord
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget
import at.petrak.hexcasting.api.spell.mishaps.MishapNoAkashicRecord
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapNoAkashicRecord
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicRecord
import net.minecraft.core.BlockPos
import net.minecraft.world.phys.Vec3
object OpAkashicRead : ConstManaOperator {
override val argc = 2
override val manaCost = 10_000
override val manaCost = ManaConstants.DUST_UNIT
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val pos = args.getChecked<Vec3>(0)

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.common.casting.operators.akashic
import at.petrak.hexcasting.api.misc.ManaConstants
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell
@ -40,7 +41,7 @@ object OpAkashicWrite : SpellOperator {
return Triple(
Spell(tile, key, datum),
10_000,
ManaConstants.DUST_UNIT,
listOf()
)
}

View file

@ -18,9 +18,9 @@ class OpCircleBounds(val max: Boolean) : ConstManaOperator {
return Operator.spellListOf(
if (max)
Vec3(aabb.minX, aabb.minY, aabb.minZ)
Vec3(aabb.maxX - 0.5, aabb.maxY - 0.5, aabb.maxZ - 0.5)
else
Vec3(aabb.maxX, aabb.maxY, aabb.maxZ)
Vec3(aabb.minX + 0.5, aabb.minY + 0.5, aabb.minZ + 0.5)
)
}
}

View file

@ -7,18 +7,19 @@ import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import net.minecraft.network.chat.TranslatableComponent
object OpEval : Operator {
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
override fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
val instrs: List<SpellDatum<*>> = stack.getChecked(stack.lastIndex)
stack.removeLastOrNull()
ctx.incDepth()
val harness = CastingHarness(ctx)
harness.stack.addAll(stack)
harness.localIota = local
val sideEffects = mutableListOf<OperatorSideEffect>()
@ -35,8 +36,7 @@ object OpEval : Operator {
}
harness.applyFunctionalData(res.newData)
}
stack.addAll(harness.stack)
return OperationResult(harness.stack, sideEffects)
return OperationResult(harness.stack, harness.localIota, sideEffects)
}
}

View file

@ -6,7 +6,7 @@ import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
object OpEvalDelay : Operator {
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
return OperationResult(stack, listOf())
override fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
return OperationResult(stack, local, listOf())
}
}

View file

@ -7,13 +7,13 @@ import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
import at.petrak.hexcasting.api.spell.math.HexPattern
import net.minecraft.network.chat.TranslatableComponent
object OpForEach : Operator {
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
override fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
if (stack.size < 2)
throw MishapNotEnoughArgs(2, stack.size)
@ -25,17 +25,20 @@ object OpForEach : Operator {
val out = mutableListOf<SpellDatum<*>>()
val sideEffects = mutableListOf<OperatorSideEffect>()
var localIota = local
for (subdatum in datums) {
ctx.incDepth()
val harness = CastingHarness(ctx)
harness.stack.addAll(stack)
harness.stack.add(subdatum)
harness.localIota = localIota
for (pat in instrs) {
val pattern = if (pat.payload is HexPattern) {
pat.payload
} else {
throw MishapInvalidIota(
pat,
SpellDatum.make(instrs),
1,
TranslatableComponent("hexcasting.mishap.invalid_value.list.pattern")
)
@ -43,14 +46,15 @@ object OpForEach : Operator {
val res = harness.getUpdate(pattern, ctx.world)
sideEffects.addAll(res.sideEffects)
if (res.sideEffects.any { it is OperatorSideEffect.DoMishap }) {
return OperationResult(harness.stack, sideEffects)
return OperationResult(harness.stack, harness.localIota, sideEffects)
}
harness.applyFunctionalData(res.newData)
}
out.addAll(harness.stack)
localIota = harness.localIota
}
stack.add(SpellDatum.make(out))
return OperationResult(stack, sideEffects)
return OperationResult(stack, localIota, sideEffects)
}
}

View file

@ -6,7 +6,6 @@ import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
import net.minecraft.network.chat.TranslatableComponent
@ -14,10 +13,7 @@ import kotlin.math.abs
import kotlin.math.roundToInt
object OpLastNToList : Operator {
val manaCost: Int
get() = 0
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
override fun operate(stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
if (stack.isEmpty())
throw MishapNotEnoughArgs(1, 0)
val arg = stack.takeLast(1).getChecked<Double>(0)
@ -38,8 +34,6 @@ object OpLastNToList : Operator {
}
stack.addAll(spellListOf(output))
val sideEffects = mutableListOf<OperatorSideEffect>(OperatorSideEffect.ConsumeMana(this.manaCost))
return OperationResult(stack, sideEffects)
return OperationResult(stack, local, listOf())
}
}

View file

@ -0,0 +1,29 @@
package at.petrak.hexcasting.common.casting.operators.lists
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import kotlin.math.roundToInt
object OpModifyInPlace : ConstManaOperator {
override val argc = 3
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val list = args.getChecked<List<SpellDatum<*>>>(0)
val index = args.getChecked<Double>(1).roundToInt()
val iota = args[2]
if (0 > index || index > list.size)
return spellListOf(list)
val newList = list.toMutableList()
if (index == list.size)
newList.add(iota)
else
newList[index] = iota
return spellListOf(newList)
}
}

View file

@ -0,0 +1,25 @@
package at.petrak.hexcasting.common.casting.operators.lists
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.util.Mth
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
object OpSlice : ConstManaOperator {
override val argc = 3
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val list = args.getChecked<List<SpellDatum<*>>>(0)
val index1 = Mth.clamp(args.getChecked<Double>(1).roundToInt(), 0, list.size)
val index2 = Mth.clamp(args.getChecked<Double>(2).roundToInt(), 0, list.size)
if (index1 == index2)
return spellListOf(listOf<SpellDatum<*>>())
return spellListOf(list.subList(min(index1, index2), max(index1, index2)))
}
}

View file

@ -0,0 +1,17 @@
package at.petrak.hexcasting.common.casting.operators.local
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.Operator
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
object OpPeekLocal : Operator {
override fun operate(
stack: MutableList<SpellDatum<*>>,
local: SpellDatum<*>,
ctx: CastingContext
): OperationResult {
stack.add(local)
return OperationResult(stack, local, listOf())
}
}

View file

@ -0,0 +1,20 @@
package at.petrak.hexcasting.common.casting.operators.local
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.Operator
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
object OpPushLocal : Operator {
override fun operate(
stack: MutableList<SpellDatum<*>>,
local: SpellDatum<*>,
ctx: CastingContext
): OperationResult {
if (stack.isEmpty())
throw MishapNotEnoughArgs(1, 0)
val newLocal = stack.removeLast()
return OperationResult(stack, newLocal, listOf())
}
}

View file

@ -17,4 +17,15 @@ object MathOpUtils {
TranslatableComponent("hexcasting.mishap.invalid_value.numvec")
)
}
fun GetNumOrList(datum: SpellDatum<*>, reverseIdx: Int): Either<Double, List<SpellDatum<*>>> =
when (datum.payload) {
is Double -> Either.left(datum.payload)
is List<*> -> Either.right(datum.payload.filterIsInstance<SpellDatum<*>>())
else -> throw MishapInvalidIota(
datum,
reverseIdx,
TranslatableComponent("hexcasting.mishap.invalid_value.numlist")
)
}
}

View file

@ -37,9 +37,9 @@ object OpPowProj : ConstManaOperator {
Vec3(lvec.x.pow(rnum), lvec.y.pow(rnum), lvec.z.pow(rnum))
},
{ rvec ->
if (rvec == Vec3.ZERO)
if (lvec == Vec3.ZERO)
throw MishapDivideByZero.of(lvec, rvec, "project")
rvec.scale(lvec.dot(rvec) / rvec.dot(rvec))
rvec.scale(rvec.dot(lvec) / lvec.dot(lvec))
}
)
})

View file

@ -0,0 +1,27 @@
package at.petrak.hexcasting.common.casting.operators.math.bit
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.common.casting.operators.math.MathOpUtils
import kotlin.math.roundToInt
object OpAnd : ConstManaOperator {
override val argc = 2
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val firstParam = MathOpUtils.GetNumOrList(args[0], 0)
if (firstParam.right().isPresent) {
val list1 = firstParam.right().get()
val list2 = args.getChecked<List<SpellDatum<*>>>(1)
return spellListOf(list1.filter { it in list2 })
}
val num1 = firstParam.left().get().roundToInt()
val num2 = args.getChecked<Double>(1).roundToInt()
return spellListOf((num1 and num2).toDouble())
}
}

View file

@ -0,0 +1,17 @@
package at.petrak.hexcasting.common.casting.operators.math.bit
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import kotlin.math.roundToInt
object OpNot : ConstManaOperator {
override val argc = 1
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val num = args.getChecked<Double>(0).roundToInt()
return spellListOf((num.inv()).toDouble())
}
}

View file

@ -0,0 +1,27 @@
package at.petrak.hexcasting.common.casting.operators.math.bit
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.common.casting.operators.math.MathOpUtils
import kotlin.math.roundToInt
object OpOr : ConstManaOperator {
override val argc = 2
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val firstParam = MathOpUtils.GetNumOrList(args[0], 0)
if (firstParam.right().isPresent) {
val list1 = firstParam.right().get()
val list2 = args.getChecked<List<SpellDatum<*>>>(1)
return spellListOf(list1 + list2.filter { it !in list1 })
}
val num1 = firstParam.left().get().roundToInt()
val num2 = args.getChecked<Double>(1).roundToInt()
return spellListOf((num1 or num2).toDouble())
}
}

View file

@ -0,0 +1,16 @@
package at.petrak.hexcasting.common.casting.operators.math.bit
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
object OpToSet : ConstManaOperator {
override val argc = 1
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val payload = args.getChecked<List<SpellDatum<*>>>(0)
return spellListOf(payload.toSet().toList())
}
}

Some files were not shown because too many files have changed in this diff Show more