48 Commits

Author SHA1 Message Date
wisplite 824683c25b update ver 2026-06-12 18:53:48 -05:00
wisplite 867c169830 fix rendering with shaders as much as i can 2026-06-12 18:50:02 -05:00
wisplite 75e0a72d89 make the sky loop around under the horizon 2026-06-12 18:11:40 -05:00
techno-sam 33947801ad fix modrinth config II 2026-05-15 01:07:37 +02:00
techno-sam 262ea3c695 fix modrinth config 2026-05-15 00:47:55 +02:00
techno-sam 5cbe650030 only sync body once in release 2026-05-15 00:45:27 +02:00
techno-sam de9814c899 hopefully fix mapping stack IV
gradle-native mappings converter
2026-05-15 00:24:51 +02:00
techno-sam 1069db95f9 hopefully fix mapping stack III
provide neoforge with a version of custom_mappings.tiny from intermediary->named, instead of official->[intermediary, named]
2026-05-14 23:38:40 +02:00
techno-sam 10f402b6b7 hopefully fix mapping stack II
try restricting custom mappings to common
2026-05-14 22:19:04 +02:00
techno-sam 986988f2c7 hopefully fix mapping stack
fabric.loom.dropNonIntermediateRootMethods should be true after all, perhaps
2026-05-14 22:12:09 +02:00
techno-sam e5567c2ead fix release action 2026-05-14 21:08:06 +02:00
techno-sam 69319ff896 fix release script 2026-05-14 21:00:54 +02:00
techno-sam a63212ae28 fix fabric 2026-05-14 20:58:41 +02:00
techno-sam 4aec74c6aa fix item tab order 2026-05-14 20:43:59 +02:00
techno-sam ad53d760b6 bump version 2026-05-14 20:23:40 +02:00
techno-sam 2f63523af8 Skybox XII
add sunny day skybox
2026-05-14 20:23:04 +02:00
techno-sam 9bded51abf Skybox XI
neoforge iris compat
2026-05-14 19:44:00 +02:00
techno-sam c9f13607fc Skybox X
neoforge sodium compat
2026-05-14 19:23:21 +02:00
techno-sam f4d0573332 Skybox IX
neoforge
2026-05-14 17:32:03 +02:00
techno-sam 4ae5ff2b7c Skybox VIII
add block tags for use in shader block.properties for specially-rendered blocks
2026-05-12 14:02:03 +02:00
techno-sam b630570360 Skybox VII
iris compat
2026-05-06 14:38:31 +02:00
techno-sam b0cfd425cc Skybox V
iris doesn't explode, at least
2026-04-25 17:42:10 +02:00
techno-sam 4bd557f846 Skybox IV
sodium support, nether functions
2026-04-25 16:35:41 +02:00
techno-sam acb6e0bb30 Skybox III
clean up GameRendererMixin
2026-04-25 13:28:39 +02:00
techno-sam e130a9d47c Skybox II
better fabric model loading, clean up shaders
2026-04-25 13:28:01 +02:00
techno-sam bad5f29b4e Skybox I
basic functioning on fabric
2026-04-25 13:00:26 +02:00
techno-sam 62ed623c1f Multiloader VIII
neoforge sodium doesn't work from gradle because of jar-in-jar
2026-04-24 19:19:25 +02:00
techno-sam 808a80d9f4 Multiloader VII
cleanup registration api
2026-04-17 00:03:13 +02:00
techno-sam 212fcbfad3 Multiloader VI
neoforge is working
2026-04-16 23:28:41 +02:00
techno-sam dc1670123e Multiloader VI
datagen
2026-04-16 11:05:55 +02:00
techno-sam d4b8894a3b Multiloader V
fabric is working
2026-04-16 10:54:53 +02:00
techno-sam b4355e8fd8 Multiloader IV
client setup ported
2026-04-05 22:20:27 +02:00
techno-sam 7c20d34844 Multiloader III
start loader-specific mod classes
2026-04-05 21:28:36 +02:00
techno-sam 581a236a6b Multiloader II
setup gradle
2026-04-05 20:30:52 +02:00
techno-sam 7d48193324 Multiloader I
move all of src
2026-04-05 11:56:59 +02:00
techno-sam b16c3e4ec9 a few fixes 2026-04-05 03:03:42 +02:00
techno-sam 4e4a46b37e a few more renames 2026-04-05 03:01:45 +02:00
techno-sam 2c6c100b62 switch to mojmap 2026-04-05 03:00:12 +02:00
techno-sam e0c571a1fd clean up old comments 2026-04-04 23:39:04 +02:00
techno-sam bd780af62f fix axiom version 2026-04-04 22:32:14 +02:00
techno-sam 295d902ce7 Porting V 2026-04-04 20:14:52 +02:00
techno-sam db3bce91ca Porting IV 2026-04-04 19:14:19 +02:00
techno-sam e6c2434619 Porting III 2026-04-04 17:42:44 +02:00
techno-sam 7d4eaf38c9 Porting II 2026-04-04 17:10:08 +02:00
techno-sam 88a73023c1 disable gradle config cache 2026-04-04 16:45:58 +02:00
techno-sam bec8232663 Porting I 2026-04-04 16:35:57 +02:00
techno-sam cb423ccf6b fix custom mappings 2026-04-04 14:00:23 +02:00
techno-sam 7ec56d95cd start 1.21.1 port 2026-04-04 12:03:50 +02:00
284 changed files with 5274 additions and 1801 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ indent_style = tab
tab_width = 4 tab_width = 4
insert_final_newline = true insert_final_newline = true
[{*.py,*.ipynb}] [{*.py,*.ipynb,*.fsh,*.vsh}]
indent_size = 4 indent_size = 4
indent_style = space indent_style = space
+11 -4
View File
@@ -50,6 +50,8 @@ jobs:
run: chmod +x ./gradlew run: chmod +x ./gradlew
- name: Gradle Build - name: Gradle Build
env:
RELEASE_BUILD: ${{ github.event_name == 'release' && github.event.action == 'published' }}
run: ./gradlew build run: ./gradlew build
- name: Attest Build Provenance - name: Attest Build Provenance
@@ -62,18 +64,22 @@ jobs:
with: with:
name: Artifacts name: Artifacts
path: | path: |
build/libs/*.jar fabric/build/libs/*.jar
!build/libs/*-sources.jar !fabric/build/libs/*-sources.jar
neoforge/build/libs/*.jar
!neoforge/build/libs/*-sources.jar
- name: Maven Publish - name: Maven Publish
if: github.event_name == 'release' && github.event.action == 'published' if: github.event_name == 'release' && github.event.action == 'published'
env:
RELEASE_BUILD: true
run: ./gradlew publish run: ./gradlew publish
- name: Github Publish - name: Github Publish
if: github.event_name == 'release' && github.event.action == 'published' if: github.event_name == 'release' && github.event.action == 'published'
uses: AButler/upload-release-assets@v2.0 uses: AButler/upload-release-assets@v2.0
with: with:
files: 'build/libs/*.jar;!build/libs/*-sources.jar' files: 'fabric/build/libs/*.jar;!fabric/build/libs/*-sources.jar;neoforge/build/libs/*.jar;!neoforge/build/libs/*-sources.jar'
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
# set modrinth release type if tag matches v#.#.#-(alpha|beta).* # set modrinth release type if tag matches v#.#.#-(alpha|beta).*
@@ -90,10 +96,11 @@ jobs:
- name: Modrinth Publish - name: Modrinth Publish
env: env:
RELEASE_BUILD: true
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
CHANGELOG: ${{ github.event.release.body }} CHANGELOG: ${{ github.event.release.body }}
RELEASE_TYPE: ${{ steps.detect-release-type.outputs.type }} RELEASE_TYPE: ${{ steps.detect-release-type.outputs.type }}
if: ${{ github.event_name == 'release' && github.event.action == 'published' && env.MODRINTH_TOKEN != '' }} if: ${{ github.event_name == 'release' && github.event.action == 'published' && env.MODRINTH_TOKEN != '' }}
run: | run: |
./gradlew --no-configuration-cache modrinth ./gradlew --no-configuration-cache modrinth
./gradlew --no-configuration-cache modrinthSyncBody ./gradlew --no-configuration-cache :fabric:modrinthSyncBody
+6
View File
@@ -22,3 +22,9 @@ Crystalline Sky adds several sky-light emitting blocks:
--- ---
![weeping sky blocks illuminating a cave](https://cdn.modrinth.com/data/dhKWKlrK/images/5dc5430dd318361d12c962ac555d79f68aeac243.png) ![weeping sky blocks illuminating a cave](https://cdn.modrinth.com/data/dhKWKlrK/images/5dc5430dd318361d12c962ac555d79f68aeac243.png)
---
**Additional Credits**
`skybox_sunny_day.png` is a scaled down version of [KIIRA's asset](https://opengameart.org/content/sky-box-sunny-day) provided under CC-BY 3.0, CC-BY-SA 3.0, GPL 3.0, GPL 2.0, or OGA-BY 3.0 at your choice.
-173
View File
@@ -1,173 +0,0 @@
//file:noinspection GroovyAssignabilityCheck
//file:noinspection GroovyAccessibility
plugins {
id "maven-publish"
alias libs.plugins.loom
alias libs.plugins.minotaur
}
boolean inCI = System.getenv("GITHUB_RUN_NUMBER") != null
version = "$modVersion+$branchName"
base.archivesName = project.slug
repositories {
exclusiveContent {
forRepository {
//noinspection ForeignDelegate
maven {
name 'Modrinth'
url "https://api.modrinth.com/maven"
}
}
filter {
includeGroup "maven.modrinth"
}
}
exclusiveContent {
forRepository {
//noinspection ForeignDelegate
maven {
name 'Terraformers'
url "https://maven.terraformersmc.com/"
}
}
filter {
includeGroup "com.terraformersmc"
}
}
exclusiveContent { // Fabric ASM
//"https://jitpack.io/"
forRepository {
//noinspection ForeignDelegate
maven {
name 'JitPack (Manningham Mills)'
url "https://jitpack.io/"
}
}
filter {
includeGroup "com.github.Chocohead"
}
}
flatDir {
dir("libs")
}
}
dependencies {
minecraft libs.mc
mappings loom.layered {
it.mappings variantOf(libs.yarn) { classifier "v2" }
it.mappings file("custom_mappings.tiny")
}
modImplementation libs.fl
modImplementation libs.fapi
// Fabric ASM (enum extension etc)
modImplementation(libs.manningham) {
exclude (group: "net.fabricmc.fabric-api")
}
include libs.manningham
if (!inCI) {
modRuntimeOnly libs.mm
}
modCompileOnly libs.sodium
if (!inCI && enable_sodium.toBoolean()) {
modLocalRuntime libs.sodium
}
modCompileOnly libs.axiom
if (!inCI && enable_axiom.toBoolean()) {
modLocalRuntime(
libs.axiom,
libs.axiom.axiomclientapi,
libs.axiom.lattice,
libs.axiom.mixinconstraints
)
}
include(implementation(annotationProcessor(libs.mixinextras.get())))
}
processResources {
final Map<String, String> meta = [
version : version,
modId : modId,
modName : modName,
modDescription: modDescription,
homepage : "https://modrinth.com/mod/${slug}",
issues : "https://github.com/${user}/${slug}/issues",
sources : "https://github.com/${user}/${slug}",
license : license,
authors : authors.split(", ").join("\",\n \""),
contributors : contributors.split(", ").join("\",\n \""),
members : "${authors}${contributors ? ". Contributions by ${contributors}." : ""}",
mc : compatibleVersions.split(", ")[0],
fl : libs.versions.fl.get(),
fapi : libs.versions.fapi.get(),
]
inputs.properties meta
filesMatching("*.mod.json") { expand(meta) }
filesMatching("META-INF/*mods.toml") { expand(meta) }
// don't add development or to-do files into built jar
exclude("**/*.bbmodel", "**/*.lnk", "**/*.xcf", "**/*.blend", "**/*.blend1")
}
loom {
runs.configureEach {
vmArg("-XX:+AllowEnhancedClassRedefinition")
vmArg("-XX:+IgnoreUnrecognizedVMOptions")
vmArg("-Dmixin.debug.export=true")
vmArg("-Dfabric-tag-conventions-v2.missingTagTranslationWarning=VERBOSE")
}
}
fabricApi {
configureDataGeneration {
client = true
outputDirectory = file("src/generated/resources")
}
}
tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8"
it.options.release = 21
}
java {
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
publishing {
repositories {
}
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
modrinth {
token = "$System.env.MODRINTH_TOKEN"
projectId = slug
versionNumber = project.version
versionType = System.getenv().getOrDefault("RELEASE_TYPE", "release")
uploadFile = remapJar
gameVersions = compatibleVersions.split(", ").toList()
loaders = compatibleLoaders.split(", ").toList()
changelog = "$System.env.CHANGELOG"
syncBodyFrom = "<!--DO NOT EDIT MANUALLY: synced from gh readme-->\n" + rootProject.file("README.md").text
dependencies {
required.version "fabric-api", libs.versions.fapi.get()
}
}
+305
View File
@@ -0,0 +1,305 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.modrinth.minotaur.ModrinthExtension
import dev.architectury.plugin.ArchitectPluginExtension
import net.fabricmc.loom.api.LoomGradleExtensionAPI
import net.fabricmc.loom.task.RemapJarTask
import org.gradle.kotlin.dsl.libs
plugins {
java
`maven-publish`
alias(libs.plugins.arch)
alias(libs.plugins.loom) apply false
alias(libs.plugins.shadow) apply false
alias(libs.plugins.minotaur) apply false
}
println("Crystalline Sky v${"modVersion"()}")
val isRelease = System.getenv("RELEASE_BUILD")?.toBoolean() ?: false
val buildNumber = System.getenv("GITHUB_RUN_NUMBER")?.toInt()
val inCI = buildNumber != null
val gitHash = "\"${calculateGitHash() + (if (hasUnstaged()) "-modified" else "")}\""
extra["inCI"] = inCI
architectury {
minecraft = libs.versions.mc.get()
}
allprojects {
val libs = rootProject.libs
apply(plugin = "java")
apply(plugin = libs.plugins.arch.get().pluginId)
apply(plugin = "maven-publish")
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
base.archivesName.set("slug"())
group = "mavenGroup"()
// Formats the mod version to include the loader, Minecraft version, and build number (if present)
// example: 1.0.0+fabric-1.19.2-build.100 (or -local)
val build = buildNumber?.let { "-build.${it}" } ?: "-local"
var gitBranchLabel = "";
if (!isRelease && "modVersion"().endsWith("-alpha")) {
// gitBranchLabel should be "-" + the current git branch (replacing any slashes with underscores)
gitBranchLabel = "-" + calculateGitBranch().replace("/", "_")
}
version = "${"modVersion"()}${gitBranchLabel}+${project.name}-mc${libs.versions.mc.get()}${if (isRelease) "" else build}"
tasks.withType<JavaCompile>().configureEach {
options.encoding = "UTF-8"
options.release = 21
}
}
subprojects {
val libs = rootProject.libs
apply(plugin = libs.plugins.loom.get().pluginId)
setupRepositories()
val capitalizedName = {
if (project.name == "neoforge") {
"NeoForge"
} else {
project.name.replaceFirstChar { it.titlecase() }
}
}();
val loom = project.extensions.getByType<LoomGradleExtensionAPI>()
loom.apply {
silentMojangMappingsLicense()
runs.configureEach {
vmArg("-XX:+AllowEnhancedClassRedefinition")
vmArg("-XX:+IgnoreUnrecognizedVMOptions")
// Disabled by default: exports every mixin target to disk and can make startup hang for minutes.
// Enable manually when debugging mixins: -Dmixin.debug.export=true
vmArg("-Dmixin.env.remapRefMap=true")
vmArg("-Dmixin.env.refMapRemappingFile=${projectDir}/build/createSrgToMcp/output.srg")
}
}
configurations.configureEach {
resolutionStrategy {
force(libs.fl)
}
}
@Suppress("UnstableApiUsage")
dependencies {
"minecraft"(libs.mc)
"mappings"(loom.layered {
officialMojangMappings { nameSyntheticMembers = false }
parchment(variantOf(libs.parchment) { artifactType("zip") })
if (project.path == ":neoforge") {
val strippedMappings = rootProject.file("custom_mappings_stripped.tiny")
if (strippedMappings.exists()) {
mappings(strippedMappings)
}
} else {
mappings(rootProject.file("custom_mappings.tiny"))
}
})
}
// from here down is platform configuration
if(project.path == ":common") {
return@subprojects
}
apply(plugin = libs.plugins.shadow.get().pluginId)
apply(plugin = libs.plugins.minotaur.get().pluginId)
architectury {
platformSetupLoomIde()
}
val common: Configuration by configurations.creating
val shadowCommon: Configuration by configurations.creating
val development = configurations.maybeCreate("development${capitalizedName}")
configurations {
compileOnly.get().extendsFrom(common)
runtimeOnly.get().extendsFrom(common)
development.extendsFrom(common)
}
dependencies {
common(project(":common", "namedElements")) { isTransitive = false }
shadowCommon(project(":common", "transformProduction${capitalizedName}")) { isTransitive = false }
}
tasks.named<ShadowJar>("shadowJar") {
archiveClassifier = "dev-shadow"
configurations = listOf(shadowCommon)
exclude("architectury.common.json")
destinationDirectory = layout.buildDirectory.dir("devlibs").get()
}
val remapJar = tasks.named<RemapJarTask>("remapJar") {
from("${rootProject.projectDir}/LICENSE")
val shadowJar = project.tasks.named<ShadowJar>("shadowJar").get()
inputFile.set(shadowJar.archiveFile)
injectAccessWidener = true
dependsOn(shadowJar)
archiveClassifier = null
}
tasks.processResources {
val authors = "authors"()
val contributors = "contributors"()
val properties: Map<String, String> = mapOf(
"version" to version.toString(),
"modId" to "modId"(),
"modName" to "modName"(),
"modDescription" to "modDescription"(),
"homepage" to "https://modrinth.com/mod/${"slug"()}",
"issues" to "https://github.com/${"user"()}/${"slug"()}/issues",
"sources" to "https://github.com/${"user"()}/${"slug"()}",
"license" to "license"(),
"authors" to authors.split(", ").joinToString("\",\n \""),
"contributors" to contributors.split(", ").joinToString("\",\n \""),
"members" to "${authors}${if (contributors.isNotBlank()) ". Contributions by ${contributors}." else ""}",
"mc" to "compatibleVersions"().split(", ")[0],
"fl" to libs.versions.fl.get(),
"fapi" to libs.versions.fapi.get(),
)
inputs.properties(properties)
filesMatching("*.mod.json") { expand(properties) }
filesMatching("META-INF/*mods.toml") { expand(properties) }
// don't add development or to-do files into built jar
exclude("**/*.bbmodel", "**/*.lnk", "**/*.xcf", "**/*.blend", "**/*.blend1")
}
tasks.jar {
archiveClassifier = "dev"
manifest {
attributes(mapOf("Git-Hash" to gitHash))
}
}
tasks.named<Jar>("sourcesJar") {
val commonSources = project(":common").tasks.getByName<Jar>("sourcesJar")
dependsOn(commonSources)
from(commonSources.archiveFile.map { zipTree(it) })
manifest {
attributes(mapOf("Git-Hash" to gitHash))
}
}
components.getByName<AdhocComponentWithVariants>("java") {
withVariantsFromConfiguration(project.configurations["shadowRuntimeElements"]) {
skip()
}
}
val isFabric = project.name == "fabric"
val description = "<!--DO NOT EDIT MANUALLY: synced from gh readme-->\n" + rootProject.file("README.md").readText()
configure<ModrinthExtension> {
token.set(providers.environmentVariable("MODRINTH_TOKEN"))
projectId = "slug"()
versionNumber.set(project.version.toString())
versionType.set(providers.environmentVariable("RELEASE_TYPE").orElse("release"))
uploadFile.set(remapJar.get().archiveFile)
gameVersions = "compatibleVersions"().split(", ").toList()
if (isFabric) {
loaders.add("fabric")
loaders.add("quilt")
} else {
loaders.add("neoforge")
}
changelog.set(providers.environmentVariable("CHANGELOG"))
syncBodyFrom.set(description) // lazyness doesn't seem to work for this?
dependencies {
if (isFabric) {
required.version("fabric-api", libs.versions.fapi.get())
}
}
}
}
fun Project.setupRepositories() {
repositories {
exclusiveMaven("https://api.modrinth.com/maven", "maven.modrinth") // Axiom, Sodium
exclusiveMaven("https://maven.terraformersmc.com/", "com.terraformersmc") // Mod Menu
exclusiveMaven("https://maven.parchmentmc.org", "org.parchmentmc.data") // Parchment Mappings
exclusiveMaven("https://maven.su5ed.dev/releases", "org.sinytra.forgified-fabric-api") // FFAPI, for NeoForge Sodium compat
flatDir {
dir("$rootDir/libs")
}
}
}
fun calculateGitHash(): String {
try {
val output = providers.exec {
commandLine("git", "rev-parse", "HEAD")
}
return output.standardOutput.asText.get().trim()
} catch(_: Throwable) {
return "unknown"
}
}
fun calculateGitBranch(): String {
try {
val output = providers.exec {
commandLine("git", "rev-parse", "--abbrev-ref", "HEAD")
}
return output.standardOutput.asText.get().trim()
} catch(_: Throwable) {
return "unknown"
}
}
fun hasUnstaged(): Boolean {
try {
val output = providers.exec {
commandLine("git", "status", "--porcelain")
}
val result = output.standardOutput.asText.get().replace(Regex("M gradlew(\\.bat)?"), "").trimEnd()
if (result.isNotEmpty())
println("Found stageable results:\n${result}\n")
return result.isNotEmpty()
} catch(_: Throwable) {
return false
}
}
fun Project.architectury(action: Action<ArchitectPluginExtension>) {
action.execute(this.extensions.getByType<ArchitectPluginExtension>())
}
fun RepositoryHandler.exclusiveMaven(url: String, vararg groups: String) {
exclusiveContent {
forRepository { maven(url) }
filter {
groups.forEach {
@Suppress("UnstableApiUsage")
includeGroupAndSubgroups(it)
}
}
}
}
operator fun String.invoke(): String {
return rootProject.ext[this] as? String
?: throw IllegalStateException("Property $this is not defined")
}
+31
View File
@@ -0,0 +1,31 @@
architectury {
common {
for (p in rootProject.subprojects) {
if (p != project) {
this@common.add(p.name)
}
}
}
}
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
// Do NOT use other classes from fabric loader
modImplementation(libs.fl)
// required for proper remapping and compiling
modCompileOnly(libs.fapi)
compileOnly(libs.jsr305)
modCompileOnly(libs.sodium.fabric)
modCompileOnly(libs.iris.fabric)
compileOnly(annotationProcessor(libs.mixinextras.common.get())!!)!!
}
sourceSets.main {
resources { // include generated resources in resources
srcDir("src/generated/resources")
exclude(".cache/**")
}
}
@@ -1,48 +1,50 @@
// 1.21.8 -999999999-01-01T00:00:00 Crystalline Sky/Model Definitions // 1.21.1 2026-05-14T20:11:05.252735359 Crystalline Sky/Model Definitions
e832366c216102270b75085db7a7169881b853b3 assets/crystalline_sky/blockstates/sky.json
ecc125a24d3e2c86d922352d8449f26a4e06d122 assets/crystalline_sky/blockstates/sky_light.json
03e2eb768bc34fbeaabffbff8ed3a2a3044a6db1 assets/crystalline_sky/blockstates/weeping_sky.json
9b3d01168a1cc29b99cf69fe225ad69b0923c9fe assets/crystalline_sky/blockstates/weeping_sky_light.json
c0168359bc7e3978778cee2d000b21c3889c235c assets/crystalline_sky/items/sky.json
c9ebbcbf9d632aeab6bfab2014d7c225f2b290d9 assets/crystalline_sky/items/sky_light.json
2371c7a720a552589983925a24677fd3d1b649b4 assets/crystalline_sky/items/weeping_sky.json
b14b5a0b951ae24fb4b79df59416163b1303d32e assets/crystalline_sky/items/weeping_sky_light.json
6d1e10716c05150e73b2b9e254091125264a7a3d assets/crystalline_sky/models/block/sky.json
3183aeb9fff78d0c65f1ddd0dfb599420573e281 assets/crystalline_sky/models/block/sky_light_00.json
7eaa4c3d4913e0cb117585204dd1dd9e58402b83 assets/crystalline_sky/models/block/sky_light_01.json
59463cef438e58b137e5ce27402acf42a3a0ae87 assets/crystalline_sky/models/block/sky_light_02.json
ee9cb7604922cdb2ad71d021a593ca82f0baf493 assets/crystalline_sky/models/block/sky_light_03.json
317f9881c20b1aaa3902b3999dd1c76d00afbde6 assets/crystalline_sky/models/block/sky_light_04.json
2ce612b8445da92c6cecd07bd5364a25bcfb127f assets/crystalline_sky/models/block/sky_light_05.json
19859c3124196f3788bfbae1ec2bcd4d1e46db2e assets/crystalline_sky/models/block/sky_light_06.json
fceb0c59b7f6d431200764ccf87596541bacb17f assets/crystalline_sky/models/block/sky_light_07.json
c0d693e4f78ce15c238909130382909abda4c922 assets/crystalline_sky/models/block/sky_light_08.json
ef9e5aca345b59cb4692a7bcfaac539aed6f6889 assets/crystalline_sky/models/block/sky_light_09.json
9c6ba4d90f2c4f2a9beb910c1b32023e49445749 assets/crystalline_sky/models/block/sky_light_10.json
e91808daecfc454b784f5fb27003c58bb0caedce assets/crystalline_sky/models/block/sky_light_11.json
e2c7bebd9eca446bb06fff866ec4d4996917e7e4 assets/crystalline_sky/models/block/sky_light_12.json
0b4015acca6117ea633ae3cdaf3fe40fcab6b628 assets/crystalline_sky/models/block/sky_light_13.json
0ac5351c3a01e0f9e76517452918e12770b3b54b assets/crystalline_sky/models/block/sky_light_14.json 0ac5351c3a01e0f9e76517452918e12770b3b54b assets/crystalline_sky/models/block/sky_light_14.json
a87d8988452529a1f5af5662ad636223fdd98fec assets/crystalline_sky/models/block/sky_light_15.json
14508173fcca14cb42755d47374c94d3eace42ce assets/crystalline_sky/models/block/weeping_sky.json
508ffb97ee711b53767b9d33659596197f69ee20 assets/crystalline_sky/models/block/weeping_sky_light.json
008a0d0a76a34d8f375fa355452a5d0f93f9af3b assets/crystalline_sky/models/item/sky.json
2fedd8aff557d4e559ffa8166b4e5ac78136046d assets/crystalline_sky/models/item/sky_light.json
9f0d9fe5dfb05bbe18177db5c40e600c5b256858 assets/crystalline_sky/models/item/sky_light_00.json
0e8a96cfb88f4c58679709cc9397b5700878a9c4 assets/crystalline_sky/models/item/sky_light_01.json
ed5894de7afa66f73c72093f2dd7d046cf647070 assets/crystalline_sky/models/item/sky_light_02.json
b29c14f77a08da7a6994cff4c6801d6f04b12ec0 assets/crystalline_sky/models/item/sky_light_03.json
51fa40ff02afcec303e7a18478cbae5375dfb140 assets/crystalline_sky/models/item/sky_light_04.json
42f8b696ba0f511edce656b9055764ed13013221 assets/crystalline_sky/models/item/sky_light_05.json
910c51120a0931851db6b75b337bc21241165c2f assets/crystalline_sky/models/item/sky_light_06.json
dff33a68a694de0f3ef177886c002204ffe49a8c assets/crystalline_sky/models/item/sky_light_07.json
89582890605d371d936384a83950af603d2fe495 assets/crystalline_sky/models/item/sky_light_08.json
7115b88da2cc0bfdc68646d034de8d14f181eb01 assets/crystalline_sky/models/item/sky_light_09.json
9c6c61b7f805a614d2d15d8dde390ed068913182 assets/crystalline_sky/models/item/sky_light_10.json
04f1e4eba184b8e7b1669fc61006e3d00e09d164 assets/crystalline_sky/models/item/sky_light_11.json
b8795df31017499b35a5b37a4dfbe555a8242cb0 assets/crystalline_sky/models/item/sky_light_12.json b8795df31017499b35a5b37a4dfbe555a8242cb0 assets/crystalline_sky/models/item/sky_light_12.json
19859c3124196f3788bfbae1ec2bcd4d1e46db2e assets/crystalline_sky/models/block/sky_light_06.json
9a726a3ed95dc9b35b9ce000d501c5f45c8642ac assets/crystalline_sky/models/item/skybox_sunny_day.json
7115b88da2cc0bfdc68646d034de8d14f181eb01 assets/crystalline_sky/models/item/sky_light_09.json
2ce612b8445da92c6cecd07bd5364a25bcfb127f assets/crystalline_sky/models/block/sky_light_05.json
ef5afdbcc8401a27029b6f0a29fa1117761c620d assets/crystalline_sky/models/item/sky_light.json
2763952a1919802e34f0976b023fc7b486456b91 assets/crystalline_sky/models/item/skybox_test.json
1507d8530a97e5c3fb562b224acdce3d5551522e assets/crystalline_sky/models/block/skybox_test.json
008a0d0a76a34d8f375fa355452a5d0f93f9af3b assets/crystalline_sky/models/item/sky.json
9b3d01168a1cc29b99cf69fe225ad69b0923c9fe assets/crystalline_sky/blockstates/weeping_sky_light.json
25f0831f8c64db0e5c08fc968445e329f1e3a91c assets/crystalline_sky/models/item/sky_light_13.json 25f0831f8c64db0e5c08fc968445e329f1e3a91c assets/crystalline_sky/models/item/sky_light_13.json
58349dc5dedb8016fb0bc958fcd4a9ccde13a1cd assets/crystalline_sky/models/item/sky_light_14.json 0b4015acca6117ea633ae3cdaf3fe40fcab6b628 assets/crystalline_sky/models/block/sky_light_13.json
ed5894de7afa66f73c72093f2dd7d046cf647070 assets/crystalline_sky/models/item/sky_light_02.json
fceb0c59b7f6d431200764ccf87596541bacb17f assets/crystalline_sky/models/block/sky_light_07.json
7eaa4c3d4913e0cb117585204dd1dd9e58402b83 assets/crystalline_sky/models/block/sky_light_01.json
317f9881c20b1aaa3902b3999dd1c76d00afbde6 assets/crystalline_sky/models/block/sky_light_04.json
e2c7bebd9eca446bb06fff866ec4d4996917e7e4 assets/crystalline_sky/models/block/sky_light_12.json
51fa40ff02afcec303e7a18478cbae5375dfb140 assets/crystalline_sky/models/item/sky_light_04.json
dff33a68a694de0f3ef177886c002204ffe49a8c assets/crystalline_sky/models/item/sky_light_07.json
a87d8988452529a1f5af5662ad636223fdd98fec assets/crystalline_sky/models/block/sky_light_15.json
d500e56057c0c2f3c948894694e2826f1726fd9e assets/crystalline_sky/models/item/sky_light_15.json d500e56057c0c2f3c948894694e2826f1726fd9e assets/crystalline_sky/models/item/sky_light_15.json
662d2389357e6f00a3a59042d08aec47df9c2c10 assets/crystalline_sky/blockstates/skybox_test.json
e832366c216102270b75085db7a7169881b853b3 assets/crystalline_sky/blockstates/sky.json
0e4687d67163446b33dc32eed29154467bea6c0f assets/crystalline_sky/blockstates/skybox_sunny_day.json
ee9cb7604922cdb2ad71d021a593ca82f0baf493 assets/crystalline_sky/models/block/sky_light_03.json
e91808daecfc454b784f5fb27003c58bb0caedce assets/crystalline_sky/models/block/sky_light_11.json
910c51120a0931851db6b75b337bc21241165c2f assets/crystalline_sky/models/item/sky_light_06.json
0e8a96cfb88f4c58679709cc9397b5700878a9c4 assets/crystalline_sky/models/item/sky_light_01.json
ef9e5aca345b59cb4692a7bcfaac539aed6f6889 assets/crystalline_sky/models/block/sky_light_09.json
59463cef438e58b137e5ce27402acf42a3a0ae87 assets/crystalline_sky/models/block/sky_light_02.json
c0d693e4f78ce15c238909130382909abda4c922 assets/crystalline_sky/models/block/sky_light_08.json
508ffb97ee711b53767b9d33659596197f69ee20 assets/crystalline_sky/models/block/weeping_sky_light.json
9c6ba4d90f2c4f2a9beb910c1b32023e49445749 assets/crystalline_sky/models/block/sky_light_10.json
9c6c61b7f805a614d2d15d8dde390ed068913182 assets/crystalline_sky/models/item/sky_light_10.json
42f8b696ba0f511edce656b9055764ed13013221 assets/crystalline_sky/models/item/sky_light_05.json
ecc125a24d3e2c86d922352d8449f26a4e06d122 assets/crystalline_sky/blockstates/sky_light.json
89582890605d371d936384a83950af603d2fe495 assets/crystalline_sky/models/item/sky_light_08.json
15c0a47d504ddd41bbecd4ac58c0c8ccd0f37943 assets/crystalline_sky/models/item/weeping_sky.json 15c0a47d504ddd41bbecd4ac58c0c8ccd0f37943 assets/crystalline_sky/models/item/weeping_sky.json
04f1e4eba184b8e7b1669fc61006e3d00e09d164 assets/crystalline_sky/models/item/sky_light_11.json
58349dc5dedb8016fb0bc958fcd4a9ccde13a1cd assets/crystalline_sky/models/item/sky_light_14.json
03e2eb768bc34fbeaabffbff8ed3a2a3044a6db1 assets/crystalline_sky/blockstates/weeping_sky.json
7c7d944714b5bcbee6a7e8014599ade8fbc5e804 assets/crystalline_sky/models/block/weeping_sky.json
b29c14f77a08da7a6994cff4c6801d6f04b12ec0 assets/crystalline_sky/models/item/sky_light_03.json
be0be7e1d7ce1ccabed01ef09c6499a2a7f2b132 assets/crystalline_sky/models/item/weeping_sky_light.json be0be7e1d7ce1ccabed01ef09c6499a2a7f2b132 assets/crystalline_sky/models/item/weeping_sky_light.json
9f0d9fe5dfb05bbe18177db5c40e600c5b256858 assets/crystalline_sky/models/item/sky_light_00.json
b3c45423bfa6ceab87b0463a8f0b0860f539b875 assets/crystalline_sky/models/block/skybox_sunny_day.json
3183aeb9fff78d0c65f1ddd0dfb599420573e281 assets/crystalline_sky/models/block/sky_light_00.json
04fb705807dd052f00ff861343ebe6fe0a78ca41 assets/crystalline_sky/models/block/sky.json
@@ -0,0 +1,5 @@
// 1.21.1 2026-05-14T20:11:05.251123123 Crystalline Sky/Tags for minecraft:block
836c24460dd2bc0b6a3107ec086877b31acf2cfe data/crystalline_sky/tags/block/rendering/cubemap.json
1389c0b812f7a6e4d5dd00edac1dc07beb5f9552 data/crystalline_sky/tags/block/sky_light_emitters.json
606477607a09045ff2830cbc036e744d6a728bbd data/minecraft/tags/block/crystal_sound_blocks.json
606477607a09045ff2830cbc036e744d6a728bbd data/crystalline_sky/tags/block/rendering/projection.json
@@ -0,0 +1,5 @@
// 1.21.1 2026-05-14T20:11:05.2536566 Crystalline Sky/Block Loot Tables
067d0b2196d6ce5905ce5af492a2a710947675a5 data/crystalline_sky/loot_table/blocks/skybox_sunny_day.json
337de0acfc1b9b86adde0705e342ed1d4b5c9c4e data/crystalline_sky/loot_table/blocks/weeping_sky.json
553f34591ac91c8bd174e24e3585e6a62490ff56 data/crystalline_sky/loot_table/blocks/skybox_test.json
6a9b7a08424cbd3d699dfd3252d432517254aa45 data/crystalline_sky/loot_table/blocks/sky.json
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "crystalline_sky:block/skybox_sunny_day"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "crystalline_sky:block/skybox_test"
}
}
}
@@ -1,5 +1,6 @@
{ {
"parent": "minecraft:block/cube_all", "parent": "minecraft:block/cube_all",
"render_type": "crystalline_sky:sky",
"textures": { "textures": {
"all": "crystalline_sky:block/sky" "all": "crystalline_sky:block/sky"
} }
@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/cube_all",
"crystalline_sky:atlas": "crystalline_sky:textures/atlas/skyboxes.png",
"loader": "crystalline_sky:skybox",
"render_type": "crystalline_sky:skybox",
"textures": {
"all": "crystalline_sky:crystalline_sky_skybox/skybox_sunny_day",
"particle": "crystalline_sky:block/skybox_sunny_day"
}
}
@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/cube_all",
"crystalline_sky:atlas": "crystalline_sky:textures/atlas/skyboxes.png",
"loader": "crystalline_sky:skybox",
"render_type": "crystalline_sky:skybox",
"textures": {
"all": "crystalline_sky:crystalline_sky_skybox/skybox_test",
"particle": "crystalline_sky:block/skybox_test"
}
}
@@ -1,5 +1,6 @@
{ {
"parent": "minecraft:block/cube_all", "parent": "minecraft:block/cube_all",
"render_type": "crystalline_sky:sky",
"textures": { "textures": {
"all": "crystalline_sky:block/weeping_sky" "all": "crystalline_sky:block/weeping_sky"
} }
@@ -0,0 +1,104 @@
{
"parent": "minecraft:item/generated",
"overrides": [
{
"model": "crystalline_sky:item/sky_light_00",
"predicate": {
"level": 0.0
}
},
{
"model": "crystalline_sky:item/sky_light_01",
"predicate": {
"level": 0.0625
}
},
{
"model": "crystalline_sky:item/sky_light_02",
"predicate": {
"level": 0.125
}
},
{
"model": "crystalline_sky:item/sky_light_03",
"predicate": {
"level": 0.1875
}
},
{
"model": "crystalline_sky:item/sky_light_04",
"predicate": {
"level": 0.25
}
},
{
"model": "crystalline_sky:item/sky_light_05",
"predicate": {
"level": 0.3125
}
},
{
"model": "crystalline_sky:item/sky_light_06",
"predicate": {
"level": 0.375
}
},
{
"model": "crystalline_sky:item/sky_light_07",
"predicate": {
"level": 0.4375
}
},
{
"model": "crystalline_sky:item/sky_light_08",
"predicate": {
"level": 0.5
}
},
{
"model": "crystalline_sky:item/sky_light_09",
"predicate": {
"level": 0.5625
}
},
{
"model": "crystalline_sky:item/sky_light_10",
"predicate": {
"level": 0.625
}
},
{
"model": "crystalline_sky:item/sky_light_11",
"predicate": {
"level": 0.6875
}
},
{
"model": "crystalline_sky:item/sky_light_12",
"predicate": {
"level": 0.75
}
},
{
"model": "crystalline_sky:item/sky_light_13",
"predicate": {
"level": 0.8125
}
},
{
"model": "crystalline_sky:item/sky_light_14",
"predicate": {
"level": 0.875
}
},
{
"model": "crystalline_sky:item/sky_light_15",
"predicate": {
"level": 0.9375
}
}
],
"textures": {
"layer0": "crystalline_sky:item/sky_light"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "crystalline_sky:block/skybox_sunny_day"
}
}
@@ -1,6 +1,6 @@
{ {
"parent": "minecraft:item/generated", "parent": "minecraft:item/generated",
"textures": { "textures": {
"layer0": "crystalline_sky:item/sky_light" "layer0": "crystalline_sky:block/skybox_test"
} }
} }
@@ -0,0 +1,32 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:match_tool",
"predicate": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
}
],
"entries": [
{
"type": "minecraft:item",
"name": "crystalline_sky:skybox_sunny_day"
}
],
"rolls": 1.0
}
]
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:match_tool",
"predicate": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
}
],
"entries": [
{
"type": "minecraft:item",
"name": "crystalline_sky:skybox_test"
}
],
"rolls": 1.0
}
]
}
@@ -0,0 +1,6 @@
{
"values": [
"crystalline_sky:skybox_test",
"crystalline_sky:skybox_sunny_day"
]
}
@@ -0,0 +1,6 @@
{
"values": [
"crystalline_sky:sky",
"crystalline_sky:weeping_sky"
]
}
@@ -0,0 +1,32 @@
package io.github.slimeistdev.crystalline_sky;
import io.github.slimeistdev.crystalline_sky.foundation.registration.CatnipRegistry;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CrystallineSky {
public static final String ID = "crystalline_sky";
public static final Logger LOG = LoggerFactory.getLogger(ID);
private static final CatnipRegistry REGISTRY = new CatnipRegistry(ID);
public static void init() {
ModSetup.init();
}
public static ResourceLocation id(String path) {
return ResourceLocation.fromNamespaceAndPath(ID, path);
}
public static <T> ResourceKey<T> key(ResourceKey<? extends Registry<T>> registryKey, String path) {
return ResourceKey.create(registryKey, id(path));
}
@ApiStatus.Internal
public static CatnipRegistry registry() {
return REGISTRY;
}
}
@@ -0,0 +1,67 @@
package io.github.slimeistdev.crystalline_sky;
import com.mojang.blaze3d.platform.InputConstants;
import io.github.slimeistdev.crystalline_sky.annotation.multiloader.MultiLoaderEvent;
import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DebugRenderer_Duck;
import io.github.slimeistdev.crystalline_sky.multiloader.ClientPlatformHelper;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.ChatFormatting;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.component.BlockItemStateProperties;
import net.minecraft.world.level.block.LightBlock;
import org.lwjgl.glfw.GLFW;
import java.util.function.Consumer;
@Environment(EnvType.CLIENT)
public class CrystallineSkyClient {
private static final KeyMapping KEY_TOGGLE_DEBUG = new KeyMapping(
"crystalline_sky.key.toggle_weeping_sky_debug",
InputConstants.Type.KEYSYM,
GLFW.GLFW_KEY_UNKNOWN,
"crystalline_sky.category.crystalline_sky"
);
public static void init() {
CrystallineItems.SKY_LIGHT.onRegistered(i -> {
ClientPlatformHelper.registerItemProperty(
i,
ResourceLocation.withDefaultNamespace("level"),
(stack, world, entity, seed) -> {
BlockItemStateProperties state = stack.getOrDefault(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY);
Integer level = state.get(LightBlock.LEVEL);
return level != null ? level / 16.0F : 1.0F;
}
);
});
}
public static void registerKeybindings(Consumer<KeyMapping> registrar) {
registrar.accept(KEY_TOGGLE_DEBUG);
}
@MultiLoaderEvent
public static void onEndTick(Minecraft mc) {
while (KEY_TOGGLE_DEBUG.consumeClick()) {
int mode = ((DebugRenderer_Duck) mc.debugRenderer).crystalline_sky$toggleWeepingSky();
Component message = getDebugMessage(ChatFormatting.YELLOW,
Component.translatable("message.crystalline_sky.weeping_sky_debug." + mode)
);
mc.gui.getChat().addMessage(message);
}
}
@SuppressWarnings("SameParameterValue")
private static Component getDebugMessage(ChatFormatting formatting, Component message) {
return Component.empty().append(Component.translatable("debug.prefix").withStyle(formatting, ChatFormatting.BOLD)).append(CommonComponents.SPACE).append(message);
}
}
@@ -0,0 +1,33 @@
/*
* Steam 'n' Rails
* Copyright (c) 2025 The Railways Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.slimeistdev.crystalline_sky.annotation.multiloader;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to mark classes that are used via abstracted loader-specific methods.
* <p>
* Meant purely for documentation and does not exist at compile-time or runtime.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ImplClass { }
@@ -0,0 +1,33 @@
/*
* Steam 'n' Rails
* Copyright (c) 2022-2025 The Railways Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.slimeistdev.crystalline_sky.annotation.multiloader;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to mark methods that are called via abstracted loader-specific events.
* <p>
* Meant purely for documentation and does not exist at compile-time or runtime.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface MultiLoaderEvent { }
@@ -1,12 +1,13 @@
package io.github.slimeistdev.crystalline_sky.compat; package io.github.slimeistdev.crystalline_sky.compat;
import net.fabricmc.loader.api.FabricLoader; import dev.architectury.injectables.annotations.ExpectPlatform;
import java.util.Optional; import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
public enum Mods { public enum Mods {
SODIUM("sodium"), SODIUM("sodium"),
IRIS("iris"),
AXIOM("axiom"); AXIOM("axiom");
public final String id; public final String id;
@@ -14,7 +15,12 @@ public enum Mods {
Mods(String id) { Mods(String id) {
this.id = id; this.id = id;
this.isLoaded = FabricLoader.getInstance().isModLoaded(id); this.isLoaded = isModLoaded(id);
}
@ExpectPlatform
public static boolean isModLoaded(String id) {
throw new AssertionError();
} }
/** /**
@@ -0,0 +1,51 @@
package io.github.slimeistdev.crystalline_sky.compat.iris;
import com.mojang.blaze3d.pipeline.RenderTarget;
import io.github.slimeistdev.crystalline_sky.mixin.client.compat.iris.IrisRenderingPipelineAccessor;
import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.IrisRenderingPipeline_Duck;
import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.RenderTarget_Duck;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.irisshaders.iris.Iris;
import net.irisshaders.iris.pipeline.IrisRenderingPipeline;
import net.irisshaders.iris.pipeline.WorldRenderingPhase;
import net.irisshaders.iris.targets.RenderTargets;
import net.irisshaders.iris.vertices.ImmediateState;
@Environment(EnvType.CLIENT)
public class IrisHelpers {
public static boolean isShaderpackPipelineActive() {
return Iris.getPipelineManager().getPipelineNullable() instanceof IrisRenderingPipeline;
}
public static void pushVanillaShaders() {
ImmediateState.bypass = true;
}
public static void popVanillaShaders() {
ImmediateState.bypass = false;
}
public static void resetRenderingPhase() {
var pipeline = Iris.getPipelineManager().getPipelineNullable();
if (pipeline instanceof IrisRenderingPipeline irisPipeline) {
irisPipeline.setPhase(WorldRenderingPhase.NONE);
}
}
public static boolean copySkyToBuffer(RenderTarget skyBuffer) {
var pipeline = Iris.getPipelineManager().getPipelineNullable();
if (!(pipeline instanceof IrisRenderingPipeline irisPipeline)) return false;
IrisRenderingPipelineAccessor pipelineAccessor = ((IrisRenderingPipelineAccessor) irisPipeline);
RenderTargets targets = pipelineAccessor.crystalline_sky$getRenderTargets();
var defaultTarget = targets.get(pipelineAccessor.crystalline_sky$getPackDirectives().getFallbackTex());
((RenderTarget_Duck) skyBuffer).crystalline_sky$copyColorFrom(
((IrisRenderingPipeline_Duck) irisPipeline)::crystalline_sky$bindDefaultForRead,
irisPipeline::bindDefault,
defaultTarget.getWidth(), defaultTarget.getHeight()
);
return true;
}
}
@@ -1,18 +1,20 @@
package io.github.slimeistdev.crystalline_sky.compat.sodium; package io.github.slimeistdev.crystalline_sky.compat.sodium;
import com.mojang.blaze3d.opengl.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.textures.GpuTextureView; import com.mojang.blaze3d.systems.RenderSystem;
import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.LevelRenderer_Duck;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems; import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat3v; import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat3v;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat4v; import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat4v;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformInt; import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformInt;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformMatrix4f; import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformMatrix4f;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.*; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderFogComponent;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderInterface;
import net.caffeinemc.mods.sodium.client.util.FogParameters; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderOptions;
import net.minecraft.client.MinecraftClient; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderTextureSlot;
import net.minecraft.client.texture.GlTexture; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ShaderBindingContext;
import net.minecraft.util.math.MathHelper; import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
import org.joml.Matrix4fc; import org.joml.Matrix4fc;
import org.lwjgl.opengl.GL32C; import org.lwjgl.opengl.GL32C;
@@ -31,6 +33,8 @@ public class SkyShaderInterface implements ChunkShaderInterface {
// The fog shader component used by this program in order to set up the appropriate GL state // The fog shader component used by this program in order to set up the appropriate GL state
private final ChunkShaderFogComponent fogShader; private final ChunkShaderFogComponent fogShader;
private final float[] colorModulator = new float[] {1.0f, 1.0f, 1.0f, 1.0f};
public SkyShaderInterface(ShaderBindingContext context, ChunkShaderOptions options) { public SkyShaderInterface(ShaderBindingContext context, ChunkShaderOptions options) {
this.uniformModelViewMatrix = context.bindUniform("u_ModelViewMatrix", GlUniformMatrix4f::new); this.uniformModelViewMatrix = context.bindUniform("u_ModelViewMatrix", GlUniformMatrix4f::new);
this.uniformProjectionMatrix = context.bindUniform("u_ProjectionMatrix", GlUniformMatrix4f::new); this.uniformProjectionMatrix = context.bindUniform("u_ProjectionMatrix", GlUniformMatrix4f::new);
@@ -38,34 +42,38 @@ public class SkyShaderInterface implements ChunkShaderInterface {
this.uniformColorModulator = context.bindUniform("u_ColorModulator", GlUniformFloat4v::new); this.uniformColorModulator = context.bindUniform("u_ColorModulator", GlUniformFloat4v::new);
this.uniformTextures = new EnumMap<>(ChunkShaderTextureSlot.class); this.uniformTextures = new EnumMap<>(ChunkShaderTextureSlot.class);
this.uniformTextures.put(ChunkShaderTextureSlot.BLOCK, context.bindUniform("u_BlockTex", GlUniformInt::new)); this.uniformTextures.put(ChunkShaderTextureSlot.BLOCK, context.bindUniformOptional("u_BlockTex", GlUniformInt::new));
this.fogShader = options.fog().getFactory().apply(context); this.fogShader = options.fog().getFactory().apply(context);
} }
@Override // the shader interface should not modify pipeline state protected int getBoundTextureId() {
public void setupState(TerrainRenderPass pass, FogParameters parameters) { var fb = ((LevelRenderer_Duck) Minecraft.getInstance().levelRenderer).crystalline_sky$getSkyFramebuffer();
this.bindTexture(ChunkShaderTextureSlot.BLOCK, pass.getAtlas()); return fb.getColorTextureId();
}
MinecraftClient client = MinecraftClient.getInstance(); @Override
if (client.world != null public void setupState() {
this.bindTexture(ChunkShaderTextureSlot.BLOCK, getBoundTextureId());
Minecraft client = Minecraft.getInstance();
if (client.level != null
&& client.player != null && client.player != null
&& (client.player.getMainHandStack().isOf(CrystallineItems.SKY) && (CrystallineItems.isSky(client.player.getMainHandItem())
|| client.player.getOffHandStack().isOf(CrystallineItems.SKY) || CrystallineItems.isSky(client.player.getOffhandItem()))) {
|| client.player.getMainHandStack().isOf(CrystallineItems.WEEPING_SKY)
|| client.player.getOffHandStack().isOf(CrystallineItems.WEEPING_SKY))) {
float f = client.world.getTime() + client.getRenderTickCounter().getTickProgress(true); float f = client.level.getGameTime() + client.getTimer().getGameTimeDeltaPartialTick(true);
float alpha = (MathHelper.sin(f / 10.0f) + 1.0f) / 2.0f; float alpha = (Mth.sin(f / 10.0f) + 1.0f) / 2.0f;
// remap alpha from [0, 1] to [0, 0.75] // remap alpha from [0, 1] to [0, 0.75]
float maxAlpha = 1.0f - 0.25f; float maxAlpha = 1.0f - 0.25f;
alpha = alpha * maxAlpha; alpha = alpha * maxAlpha;
this.uniformColorModulator.set(1.0f, 1.0f, 1.0f, alpha); colorModulator[3] = alpha;
} else { } else {
this.uniformColorModulator.set(1.0f, 1.0f, 1.0f, 1.0f); colorModulator[3] = 1.0f;
} }
this.uniformColorModulator.set(colorModulator);
this.fogShader.setup(parameters); this.fogShader.setup();
} }
@Override // the shader interface should not modify pipeline state @Override // the shader interface should not modify pipeline state
@@ -73,16 +81,16 @@ public class SkyShaderInterface implements ChunkShaderInterface {
// This is used by alternate implementations. // This is used by alternate implementations.
} }
@Deprecated(forRemoval = true) // should be handled properly in GFX instead. /** @deprecated */
private void bindTexture(ChunkShaderTextureSlot slot, GpuTextureView textureView) { @Deprecated(
GlTexture tex = (GlTexture) textureView.texture(); forRemoval = true
)
private void bindTexture(ChunkShaderTextureSlot slot, int textureId) {
RenderSystem.setShaderTexture(slot.ordinal(), textureId);
GlStateManager._activeTexture(GL32C.GL_TEXTURE0 + slot.ordinal()); GlStateManager._activeTexture(GL32C.GL_TEXTURE0 + slot.ordinal());
GlStateManager._bindTexture(tex.getGlId()); GlStateManager._bindTexture(textureId);
GlStateManager._texParameter(GL32C.GL_TEXTURE_2D, 33084, textureView.baseMipLevel()); GlUniformInt uniform = this.uniformTextures.get(slot);
GlStateManager._texParameter(GL32C.GL_TEXTURE_2D, 33085, textureView.baseMipLevel() + textureView.mipLevels() - 1); if (uniform != null)
tex.checkDirty(GL32C.GL_TEXTURE_2D);
var uniform = this.uniformTextures.get(slot);
uniform.setInt(slot.ordinal()); uniform.setInt(slot.ordinal());
} }
@@ -0,0 +1,42 @@
package io.github.slimeistdev.crystalline_sky.compat.sodium;
import io.github.slimeistdev.crystalline_sky.mixin.client.TextureAtlasAccessor;
import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineAtlases;
import io.github.slimeistdev.crystalline_sky.util.SharedRenderVariables;
import net.caffeinemc.mods.sodium.client.gl.device.GLRenderDevice;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat2v;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformMatrix4f;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderOptions;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.ShaderBindingContext;
import net.minecraft.client.Minecraft;
public class SkyboxShaderInterface extends SkyShaderInterface {
private final GlUniformMatrix4f uniformInvViewProjMatrix;
private final GlUniformFloat2v uniformTexCoordShrink;
public SkyboxShaderInterface(ShaderBindingContext context, ChunkShaderOptions options) {
super(context, options);
this.uniformInvViewProjMatrix = context.bindUniform("u_InvViewProjMatrix", GlUniformMatrix4f::new);
this.uniformTexCoordShrink = context.bindUniformOptional("u_TexCoordShrink", GlUniformFloat2v::new);
}
@Override
public void setupState() {
super.setupState();
this.uniformInvViewProjMatrix.set(SharedRenderVariables.invSkyboxMat);
if (this.uniformTexCoordShrink != null) {
TextureAtlasAccessor textureAtlas = (TextureAtlasAccessor) Minecraft.getInstance().getTextureManager().getTexture(CrystallineAtlases.SKYBOXES.texture);
double subTexelPrecision = 1 << GLRenderDevice.INSTANCE.getSubTexelPrecisionBits();
double subTexelOffset = 3.0517578E-5F;
this.uniformTexCoordShrink.set(
(float) (subTexelOffset - (double) 1.0F / (double) textureAtlas.crystalline_sky$getWidth() / subTexelPrecision),
(float) (subTexelOffset - (double) 1.0F / (double) textureAtlas.crystalline_sky$getHeight() / subTexelPrecision)
);
}
}
@Override
protected int getBoundTextureId() {
return Minecraft.getInstance().getTextureManager().getTexture(CrystallineAtlases.SKYBOXES.texture).getId();
}
}
@@ -0,0 +1,9 @@
package io.github.slimeistdev.crystalline_sky.content.blocks;
import net.minecraft.world.level.block.TransparentBlock;
public class SkyBlock extends TransparentBlock {
public SkyBlock(Properties properties) {
super(properties);
}
}
@@ -0,0 +1,21 @@
package io.github.slimeistdev.crystalline_sky.content.blocks;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.LightBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public class SkyLightBlock extends LightBlock {
public SkyLightBlock(Properties settings) {
super(settings);
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
return context.isHoldingItem(CrystallineItems.SKY_LIGHT.value()) ? Shapes.block() : Shapes.empty();
}
}
@@ -0,0 +1,74 @@
package io.github.slimeistdev.crystalline_sky.content.blocks;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public class WeepingSkyLightBlock extends Block implements SimpleWaterloggedBlock {
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public WeepingSkyLightBlock(Properties settings) {
super(settings);
registerDefaultState(getStateDefinition().any().setValue(WATERLOGGED, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(WATERLOGGED);
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
return context.isHoldingItem(CrystallineItems.WEEPING_SKY_LIGHT.value()) ? Shapes.block() : Shapes.empty();
}
@Override
protected boolean propagatesSkylightDown(BlockState state, BlockGetter world, BlockPos pos) {
return state.getFluidState().isEmpty();
}
@Override
protected RenderShape getRenderShape(BlockState state) {
return RenderShape.INVISIBLE;
}
@Override
protected float getShadeBrightness(BlockState state, BlockGetter world, BlockPos pos) {
return 1.0f;
}
@Override
protected BlockState updateShape(
BlockState state,
Direction direction,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (state.getValue(WATERLOGGED)) {
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
}
return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
}
@Override
protected FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}
}
@@ -0,0 +1,3 @@
@javax.annotation.ParametersAreNonnullByDefault
@net.minecraft.MethodsReturnNonnullByDefault
package io.github.slimeistdev.crystalline_sky.content.blocks;
@@ -0,0 +1,48 @@
package io.github.slimeistdev.crystalline_sky.content.items;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineDataComponentTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ColumnPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.NotNull;
public class WeepingSkyBlockItem extends BlockItem {
public WeepingSkyBlockItem(Block block, Properties settings) {
super(block, settings);
}
@Override
public @NotNull InteractionResult useOn(UseOnContext context) {
ItemStack stack = context.getItemInHand();
if (stack.get(CrystallineDataComponentTypes.WEEPING_SKY_DEBUG_COLUMN_TOOL.value()) != null) {
if (context.getLevel().isClientSide) {
BlockPos pos = context.getClickedPos();
WeepingSkyBlockItemClient.setSelectedColumn(new ColumnPos(pos.getX(), pos.getZ()));
}
return InteractionResult.SUCCESS;
}
return super.useOn(context);
}
@Override
public @NotNull InteractionResultHolder<ItemStack> use(Level world, Player user, InteractionHand hand) {
ItemStack stack = user.getItemInHand(hand);
if (stack.get(CrystallineDataComponentTypes.WEEPING_SKY_DEBUG_COLUMN_TOOL.value()) != null) {
if (world.isClientSide) {
WeepingSkyBlockItemClient.setSelectedColumn(null);
}
return InteractionResultHolder.success(stack);
}
return super.use(world, user, hand);
}
}
@@ -4,22 +4,22 @@ import io.github.slimeistdev.crystalline_sky.infrastructure.client.WeepingSkyDeb
import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DebugRenderer_Duck; import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DebugRenderer_Duck;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import net.minecraft.util.math.ColumnPos; import net.minecraft.server.level.ColumnPos;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class WeepingSkyBlockItemClient { public class WeepingSkyBlockItemClient {
// todone check if this is server-safe // todone check if this is server-safe
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public static void setSelectedColumn(@Nullable ColumnPos column) { public static void setSelectedColumn(@Nullable ColumnPos column) {
MinecraftClient mc = MinecraftClient.getInstance(); Minecraft mc = Minecraft.getInstance();
WeepingSkyDebugRenderer weepingSkyDebugRenderer = ((DebugRenderer_Duck) mc.debugRenderer).crystalline_sky$getWeepingSkyDebugRenderer(); WeepingSkyDebugRenderer weepingSkyDebugRenderer = ((DebugRenderer_Duck) mc.debugRenderer).crystalline_sky$getWeepingSkyDebugRenderer();
weepingSkyDebugRenderer.setColumn(column); weepingSkyDebugRenderer.setColumn(column);
Text text = column == null Component text = column == null
? Text.translatable("message.crystalline_sky.weeping_sky_debug.column.cleared") ? Component.translatable("message.crystalline_sky.weeping_sky_debug.column.cleared")
: Text.translatable("message.crystalline_sky.weeping_sky_debug.column.set", column.x(), column.z()); : Component.translatable("message.crystalline_sky.weeping_sky_debug.column.set", column.x(), column.z());
mc.inGameHud.setOverlayMessage(text, false); mc.gui.setOverlayMessage(text, false);
} }
} }
@@ -0,0 +1,3 @@
@javax.annotation.ParametersAreNonnullByDefault
@net.minecraft.MethodsReturnNonnullByDefault
package io.github.slimeistdev.crystalline_sky.content.items;
@@ -0,0 +1,63 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import io.github.slimeistdev.crystalline_sky.foundation.registration.builder.BlockBuilder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.builder.DataComponentTypeBuilder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.builder.ItemBuilder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.BaseHolder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.BlockHolder;
import net.minecraft.core.Registry;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.BiFunction;
import java.util.function.Function;
public class CatnipRegistry {
public final String modId;
private static final Multimap<Registry<?>, Registration<?, ?, ?>> REGISTRATIONS = ArrayListMultimap.create();
public static final Multimap<Registry<?>, Registration<?, ?, ?>> REGISTRATIONS_VIEW = Multimaps.unmodifiableMultimap(REGISTRATIONS);
public CatnipRegistry(String modId) {
this.modId = modId;
}
@ApiStatus.Internal
public static <R, T extends R, H extends BaseHolder<T>> void addToRegistrationMap(Registry<R> registry, Registration<R, T, H> registration) {
REGISTRATIONS.put(registry, registration);
}
public <T> DataComponentTypeBuilder<T> dataComponentType(String id) {
return new DataComponentTypeBuilder<>(this, id);
}
public BlockBuilder<Block> block(String id) {
return block(id, Block::new);
}
public <R extends Block> BlockBuilder<R> block(String id, Function<BlockBehaviour.Properties, R> factory) {
return new BlockBuilder<>(this, id, factory);
}
public ItemBuilder<Item> item(String id) {
return item(id, Item::new);
}
public <R extends Item> ItemBuilder<R> item(String id, Function<Item.Properties, R> factory) {
return new ItemBuilder<>(this, id, factory);
}
public <B extends Block> ItemBuilder<BlockItem> item(BlockHolder<B> block) {
return item(block, BlockItem::new);
}
public <R extends BlockItem, B extends Block> ItemBuilder<R> item(BlockHolder<B> block, BiFunction<? super B, Item.Properties, R> factory) {
return new ItemBuilder<>(this, block.getRegisteredNamePath(), properties -> factory.apply(block.value(), properties));
}
}
@@ -0,0 +1,24 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.BaseHolder;
import io.github.slimeistdev.crystalline_sky.mixin.Holder$ReferenceAccessor;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import java.util.function.Consumer;
import java.util.function.Supplier;
public record Registration<R, T extends R, H extends BaseHolder<T>>(
ResourceLocation id,
Registry<R> registry,
Supplier<T> value,
H holder,
Consumer<H> afterRegisterCallback
) {
@SuppressWarnings("unchecked")
public void register() {
T registered = Registry.register(registry, id, value.get());
((Holder$ReferenceAccessor<T>) holder).crystalline_sky$bindValue(registered);
afterRegisterCallback.accept(holder);
}
}
@@ -0,0 +1,28 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
public class RegistrationListeners<T> {
private @Nullable T obj;
private @Nullable Consumer<T> cons;
public synchronized void registered(T obj) {
this.obj = obj;
if (cons != null) {
cons.accept(obj);
cons = null;
}
}
public synchronized void addListener(Consumer<? super T> consumer) {
if (obj != null) {
consumer.accept(obj);
} else if (cons == null) {
cons = consumer::accept;
} else {
cons = cons.andThen(consumer);
}
}
}
@@ -0,0 +1,49 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.builder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.CatnipRegistry;
import io.github.slimeistdev.crystalline_sky.foundation.registration.Registration;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.BaseHolder;
import io.github.slimeistdev.crystalline_sky.multiloader.Loader;
import net.minecraft.core.HolderOwner;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
public abstract class AbstractBuilder<R, T extends R, H extends BaseHolder<T>> {
protected final CatnipRegistry owner;
protected final ResourceLocation id;
protected final Registry<R> registry;
protected @Nullable H holder;
private Consumer<H> afterRegisterCallback = h -> h.getInternalRegistrationListener().accept(h.value());
public AbstractBuilder(CatnipRegistry owner, String name, Registry<R> registry) {
this.owner = owner;
this.id = ResourceLocation.fromNamespaceAndPath(owner.modId, name);
this.registry = registry;
}
public void chainAfterRegisterCallback(Consumer<H> callback) {
afterRegisterCallback = afterRegisterCallback.andThen(callback);
}
abstract T build();
abstract H getHolder(HolderOwner<R> owner, ResourceKey<R> key);
public H register() {
ResourceKey<R> key = ResourceKey.create(registry.key(), id);
holder = getHolder(registry.holderOwner(), key);
Registration<R, T, H> registration = new Registration<>(id, registry, this::build, holder, afterRegisterCallback);
if (Loader.FABRIC.isCurrent()) {
registration.register();
} else {
CatnipRegistry.addToRegistrationMap(registry, registration);
}
return holder;
}
}
@@ -0,0 +1,47 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.builder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.CatnipRegistry;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.BlockHolder;
import net.minecraft.core.HolderOwner;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockBehaviour.Properties;
import java.util.function.Function;
import java.util.function.Supplier;
public class BlockBuilder<T extends Block> extends AbstractBuilder<Block, T, BlockHolder<T>> {
private final Function<Properties, T> factory;
private Supplier<Properties> initialProperties = Properties::of;
private Function<Properties, Properties> properties = Function.identity();
public BlockBuilder(CatnipRegistry owner, String name, Function<Properties, T> factory) {
super(owner, name, BuiltInRegistries.BLOCK);
this.factory = factory;
}
public BlockBuilder<T> initialProperties(Supplier<? extends BlockBehaviour> block) {
initialProperties = () -> Properties.ofFullCopy(block.get());
return this;
}
public BlockBuilder<T> properties(Function<Properties, Properties> properties) {
this.properties = this.properties.andThen(properties);
return this;
}
@Override
T build() {
Properties properties = initialProperties.get();
properties = this.properties.apply(properties);
return factory.apply(properties);
}
@Override
BlockHolder<T> getHolder(HolderOwner<Block> owner, ResourceKey<Block> key) {
//noinspection unchecked
return (BlockHolder<T>) new BlockHolder<>(owner, key);
}
}
@@ -0,0 +1,46 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.builder;
import com.mojang.serialization.Codec;
import io.github.slimeistdev.crystalline_sky.foundation.registration.CatnipRegistry;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.DataComponentTypeHolder;
import net.minecraft.core.HolderOwner;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceKey;
public class DataComponentTypeBuilder<T> extends AbstractBuilder<DataComponentType<?>, DataComponentType<T>, DataComponentTypeHolder<T>> {
private final DataComponentType.Builder<T> builder;
public DataComponentTypeBuilder(CatnipRegistry owner, String name) {
super(owner, name, BuiltInRegistries.DATA_COMPONENT_TYPE);
this.builder = DataComponentType.builder();
}
public DataComponentTypeBuilder<T> persistent(Codec<T> codec) {
this.builder.persistent(codec);
return this;
}
public DataComponentTypeBuilder<T> networkSynchronized(StreamCodec<? super RegistryFriendlyByteBuf, T> streamCodec) {
this.builder.networkSynchronized(streamCodec);
return this;
}
public DataComponentTypeBuilder<T> cacheEncoding() {
this.builder.cacheEncoding();
return this;
}
@Override
DataComponentType<T> build() {
return builder.build();
}
@Override
DataComponentTypeHolder<T> getHolder(HolderOwner<DataComponentType<?>> owner, ResourceKey<DataComponentType<?>> key) {
//noinspection rawtypes,unchecked
return new DataComponentTypeHolder<T>((HolderOwner) owner, (ResourceKey) key);
}
}
@@ -0,0 +1,39 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.builder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.CatnipRegistry;
import io.github.slimeistdev.crystalline_sky.foundation.registration.holder.ItemHolder;
import net.minecraft.core.HolderOwner;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Item.Properties;
import java.util.function.Function;
public class ItemBuilder<T extends Item> extends AbstractBuilder<Item, T, ItemHolder<T>> {
private final Function<Properties, T> factory;
private Function<Properties, Properties> properties = Function.identity();
public ItemBuilder(CatnipRegistry owner, String name, Function<Properties, T> factory) {
super(owner, name, BuiltInRegistries.ITEM);
this.factory = factory;
}
public ItemBuilder<T> properties(Function<Properties, Properties> properties) {
this.properties = this.properties.andThen(properties);
return this;
}
@Override
T build() {
Properties properties = new Properties();
properties = this.properties.apply(properties);
return factory.apply(properties);
}
@Override
ItemHolder<T> getHolder(HolderOwner<Item> owner, ResourceKey<Item> key) {
//noinspection unchecked
return (ItemHolder<T>) new ItemHolder<>(owner, key);
}
}
@@ -0,0 +1,5 @@
@net.minecraft.FieldsAreNonnullByDefault
@javax.annotation.ParametersAreNonnullByDefault
@net.minecraft.MethodsReturnNonnullByDefault
package io.github.slimeistdev.crystalline_sky.foundation.registration.builder;
// Copied from IThundxr's 1.21.1/registration branch of https://github.com/Creators-of-Create/Ponder/
@@ -0,0 +1,39 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.holder;
import io.github.slimeistdev.crystalline_sky.foundation.registration.RegistrationListeners;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderOwner;
import net.minecraft.resources.ResourceKey;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.Consumer;
public class BaseHolder<T> extends Holder.Reference<T> {
private final RegistrationListeners<T> registrationListeners = new RegistrationListeners<>();
protected BaseHolder(HolderOwner<T> owner, ResourceKey<T> key) {
super(Type.STAND_ALONE, owner, key, null);
}
public <V> boolean is(V value) {
return value() == value;
}
@ApiStatus.Internal
public Consumer<T> getInternalRegistrationListener() {
return registrationListeners::registered;
}
public void onRegistered(Consumer<? super T> consumer) {
registrationListeners.addListener(consumer);
}
public static <T> Holder<T> downcast(Holder<? extends T> holder) {
//noinspection unchecked
return (Holder<T>) holder;
}
public String getRegisteredNamePath() {
return this.unwrapKey().map((resourceKey) -> resourceKey.location().getPath()).orElse("[unregistered]");
}
}
@@ -0,0 +1,20 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.holder;
import net.minecraft.core.HolderOwner;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
public class BlockHolder<T extends Block> extends ItemLikeHolder<T> {
public BlockHolder(HolderOwner<T> owner, ResourceKey<T> key) {
super(owner, key);
}
public BlockState defaultBlockState() {
return value().defaultBlockState();
}
public boolean is(BlockState state) {
return is(state.getBlock());
}
}
@@ -0,0 +1,11 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.holder;
import net.minecraft.core.HolderOwner;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.resources.ResourceKey;
public class DataComponentTypeHolder<T> extends BaseHolder<DataComponentType<T>> {
public DataComponentTypeHolder(HolderOwner<DataComponentType<T>> owner, ResourceKey<DataComponentType<T>> key) {
super(owner, key);
}
}
@@ -0,0 +1,11 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.holder;
import net.minecraft.core.HolderOwner;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Item;
public class ItemHolder<T extends Item> extends ItemLikeHolder<T> {
public ItemHolder(HolderOwner<T> owner, ResourceKey<T> key) {
super(owner, key);
}
}
@@ -0,0 +1,34 @@
package io.github.slimeistdev.crystalline_sky.foundation.registration.holder;
import net.minecraft.core.HolderOwner;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;
abstract class ItemLikeHolder<T extends ItemLike> extends BaseHolder<T> implements ItemLike {
protected ItemLikeHolder(HolderOwner<T> owner, ResourceKey<T> key) {
super(owner, key);
}
public ItemStack asStack() {
return new ItemStack(this);
}
public ItemStack asStack(int count) {
return new ItemStack(this, count);
}
public boolean is(ItemStack stack) {
return is(stack.getItem());
}
public boolean is(Item item) {
return asItem() == item;
}
@Override
public Item asItem() {
return value().asItem();
}
}
@@ -0,0 +1,5 @@
@net.minecraft.FieldsAreNonnullByDefault
@javax.annotation.ParametersAreNonnullByDefault
@net.minecraft.MethodsReturnNonnullByDefault
package io.github.slimeistdev.crystalline_sky.foundation.registration.holder;
// Copied from IThundxr's 1.21.1/registration branch of https://github.com/Creators-of-Create/Ponder/
@@ -0,0 +1,5 @@
@net.minecraft.FieldsAreNonnullByDefault
@javax.annotation.ParametersAreNonnullByDefault
@net.minecraft.MethodsReturnNonnullByDefault
package io.github.slimeistdev.crystalline_sky.foundation.registration;
// Copied from IThundxr's 1.21.1/registration branch of https://github.com/Creators-of-Create/Ponder/
@@ -1,28 +1,28 @@
package io.github.slimeistdev.crystalline_sky.infrastructure; package io.github.slimeistdev.crystalline_sky.infrastructure;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineBlocks; import io.github.slimeistdev.crystalline_sky.registry.CrystallineBlocks;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.BlockView; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.chunk.light.ChunkLightProvider; import net.minecraft.world.level.lighting.LightEngine;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class MutableWeepingScanner implements WeepingStorage.WeepingScanner { public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
private @Nullable BlockView blockView; private @Nullable BlockGetter blockView;
private final int minY; private final int minY;
private final BlockPos.Mutable reusablePos1 = new BlockPos.Mutable(); private final BlockPos.MutableBlockPos reusablePos1 = new BlockPos.MutableBlockPos();
private final BlockPos.Mutable reusablePos2 = new BlockPos.Mutable(); private final BlockPos.MutableBlockPos reusablePos2 = new BlockPos.MutableBlockPos();
public MutableWeepingScanner(int minY) { public MutableWeepingScanner(int minY) {
this.minY = minY; this.minY = minY;
} }
public void setBlockView(@Nullable BlockView blockView) { public void setBlockView(@Nullable BlockGetter blockView) {
this.blockView = blockView; this.blockView = blockView;
} }
@@ -34,7 +34,7 @@ public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
return y == Integer.MIN_VALUE ? -1 : y - minY; return y == Integer.MIN_VALUE ? -1 : y - minY;
} }
private @NotNull BlockView checkBlockView() { private @NotNull BlockGetter checkBlockView() {
if (blockView == null) { if (blockView == null) {
throw new IllegalStateException("blockView is not set"); throw new IllegalStateException("blockView is not set");
} else { } else {
@@ -44,17 +44,17 @@ public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
@Override @Override
public int scan(int localX, int yMax, int localZ) { public int scan(int localX, int yMax, int localZ) {
BlockView blockView = checkBlockView(); BlockGetter blockView = checkBlockView();
int actualYMax = transformInputY(yMax); int actualYMax = transformInputY(yMax);
BlockPos.Mutable topPos = reusablePos1.set(localX, actualYMax, localZ); BlockPos.MutableBlockPos topPos = reusablePos1.set(localX, actualYMax, localZ);
BlockPos.Mutable bottomPos = reusablePos2.set(localX, actualYMax - 1, localZ); BlockPos.MutableBlockPos bottomPos = reusablePos2.set(localX, actualYMax - 1, localZ);
BlockState topState = blockView.getBlockState(topPos); BlockState topState = blockView.getBlockState(topPos);
while (bottomPos.getY() >= minY) { while (bottomPos.getY() >= minY) {
BlockState bottomState = blockView.getBlockState(bottomPos); BlockState bottomState = blockView.getBlockState(bottomPos);
if (faceBlocksLight(topState, bottomState)) { if (faceBlocksLight(blockView, topState, bottomState, topPos, bottomPos)) {
return transformOutputY(bottomPos.getY()); return transformOutputY(bottomPos.getY());
} }
@@ -68,12 +68,12 @@ public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
@Override @Override
public int scanForWeepingSky(int localX, int yMax, int localZ) { public int scanForWeepingSky(int localX, int yMax, int localZ) {
BlockView blockView = checkBlockView(); BlockGetter blockView = checkBlockView();
int actualYMax = transformInputY(yMax); int actualYMax = transformInputY(yMax);
BlockPos.Mutable topPos = reusablePos1.set(localX, actualYMax, localZ); BlockPos.MutableBlockPos topPos = reusablePos1.set(localX, actualYMax, localZ);
BlockPos.Mutable bottomPos = reusablePos2.set(localX, actualYMax - 1, localZ); BlockPos.MutableBlockPos bottomPos = reusablePos2.set(localX, actualYMax - 1, localZ);
BlockState topState = blockView.getBlockState(topPos); BlockState topState = blockView.getBlockState(topPos);
if (CrystallineBlocks.isWeepingSky(topState)) if (CrystallineBlocks.isWeepingSky(topState))
@@ -85,7 +85,7 @@ public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
return transformOutputY(bottomPos.getY()); return transformOutputY(bottomPos.getY());
} }
if (faceBlocksLight(topState, bottomState)) { if (faceBlocksLight(blockView, topState, bottomState, topPos, bottomPos)) {
return -1; return -1;
} }
@@ -99,7 +99,7 @@ public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
@Override @Override
public boolean faceBlocksLight(int localX, int upperY, int localZ) { public boolean faceBlocksLight(int localX, int upperY, int localZ) {
BlockView blockView = checkBlockView(); BlockGetter blockView = checkBlockView();
int actualY = transformInputY(upperY); int actualY = transformInputY(upperY);
reusablePos1.set(localX, actualY, localZ); reusablePos1.set(localX, actualY, localZ);
@@ -107,16 +107,16 @@ public class MutableWeepingScanner implements WeepingStorage.WeepingScanner {
BlockState upper = blockView.getBlockState(reusablePos1); BlockState upper = blockView.getBlockState(reusablePos1);
BlockState lower = blockView.getBlockState(reusablePos2); BlockState lower = blockView.getBlockState(reusablePos2);
return faceBlocksLight(upper, lower); return faceBlocksLight(blockView, upper, lower, reusablePos1, reusablePos2);
} }
private static boolean faceBlocksLight(BlockState upper, BlockState lower) { private static boolean faceBlocksLight(BlockGetter world, BlockState upper, BlockState lower, BlockPos upperPos, BlockPos lowerPos) {
if (lower.getOpacity() != 0) { if (lower.getLightBlock(world, lowerPos) != 0) {
return true; return true;
} else { } else {
VoxelShape voxelShape = ChunkLightProvider.getOpaqueShape(upper, Direction.DOWN); VoxelShape voxelShape = LightEngine.getOcclusionShape(world, upperPos, upper, Direction.DOWN);
VoxelShape voxelShape2 = ChunkLightProvider.getOpaqueShape(lower, Direction.UP); VoxelShape voxelShape2 = LightEngine.getOcclusionShape(world, lowerPos, lower, Direction.UP);
return VoxelShapes.unionCoversFullCube(voxelShape, voxelShape2); return Shapes.faceShapeOccludes(voxelShape, voxelShape2);
} }
} }
} }

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