diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..39824d6 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,2 @@ +Copyright (c) 2024 Byte_Dice +All rights reserved. diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..b21bfdc --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,106 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin("jvm") version "2.0.21" + id("fabric-loom") version "1.7.1" + id("maven-publish") +} + +version = project.property("mod_version") as String +group = project.property("maven_group") as String + +base { + archivesName.set(project.property("archives_base_name") as String) +} + +val targetJavaVersion = 21 +java { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +loom { + splitEnvironmentSourceSets() + + mods { + register("bde_particles") { + sourceSet("main") + sourceSet("client") + } + } +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft("com.mojang:minecraft:${project.property("minecraft_version")}") + mappings("net.fabricmc:yarn:${project.property("yarn_mappings")}:v2") + modImplementation("net.fabricmc:fabric-loader:${project.property("loader_version")}") + modImplementation("net.fabricmc:fabric-language-kotlin:${project.property("kotlin_loader_version")}") + + modImplementation("net.fabricmc.fabric-api:fabric-api:${project.property("fabric_version")}") +} + +tasks.processResources { + inputs.property("version", project.version) + inputs.property("minecraft_version", project.property("minecraft_version")) + inputs.property("loader_version", project.property("loader_version")) + filteringCharset = "UTF-8" + + filesMatching("fabric.mod.json") { + expand( + "version" to project.version, + "minecraft_version" to project.property("minecraft_version"), + "loader_version" to project.property("loader_version"), + "kotlin_loader_version" to project.property("kotlin_loader_version") + ) + } +} + +tasks.withType().configureEach { + // ensure that the encoding is set to UTF-8, no matter what the system default is + // this fixes some edge cases with special characters not displaying correctly + // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html + // If Javadoc is generated, this must be specified in that task too. + options.encoding = "UTF-8" + options.release.set(targetJavaVersion) +} + +tasks.withType().configureEach { + compilerOptions.jvmTarget.set(JvmTarget.fromTarget(targetJavaVersion.toString())) +} + +tasks.jar { + from("LICENSE") { + rename { "${it}_${project.base.archivesName}" } + } +} + +// configure the maven publication +publishing { + publications { + create("mavenJava") { + artifactId = project.property("archives_base_name") as String + from(components["java"]) + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..9073739 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,15 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +# Fabric Properties +# check these on https://modmuss50.me/fabric.html +minecraft_version=1.21 +yarn_mappings=1.21+build.9 +loader_version=0.16.9 +kotlin_loader_version=1.12.3+kotlin.2.0.21 +# Mod Properties +mod_version=1.0-SNAPSHOT +maven_group=com.bytedice +archives_base_name=BDE_ParticleSys +# Dependencies +# check this on https://modmuss50.me/fabric.html +fabric_version=0.102.0+1.21 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..de9161e --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..c9cd717 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,8 @@ +pluginManagement { + repositories { + maven("https://maven.fabricmc.net/") { + name = "Fabric" + } + gradlePluginPortal() + } +} diff --git a/src/client/resources/bde_particles.client.mixins.json b/src/client/resources/bde_particles.client.mixins.json new file mode 100644 index 0000000..2243cf1 --- /dev/null +++ b/src/client/resources/bde_particles.client.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.bytedice.bde_particles.mixin.client", + "compatibilityLevel": "JAVA_21", + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt new file mode 100644 index 0000000..b715bf0 --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -0,0 +1,10 @@ +package com.bytedice.bde_particles + +import net.fabricmc.api.ModInitializer + +class Bde_particles : ModInitializer { + + override fun onInitialize() { + + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt new file mode 100644 index 0000000..5f24eda --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt @@ -0,0 +1,65 @@ +package com.bytedice.bde_particles + +import net.minecraft.entity.EntityType +import net.minecraft.entity.decoration.DisplayEntity.BlockDisplayEntity +import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtFloat +import net.minecraft.nbt.NbtList +import net.minecraft.server.world.ServerWorld + +class DisplayEntity(val properties: DisplayEntityProperties?) { + private var hasSpawned = false + + fun spawn(world: ServerWorld) : BlockDisplayEntity? { + if (this.hasSpawned || properties == null) { return null } + + val e = updateProperties(world, this.properties) + world.spawnEntity(e) + + this.hasSpawned = true + return e + } + + fun updateProperties(world: ServerWorld, properties: DisplayEntityProperties) : BlockDisplayEntity { + val e = BlockDisplayEntity(EntityType.BLOCK_DISPLAY, world) + + val nbt = NbtCompound().apply { + putString("Name", properties.blockType) + put("transformation", NbtCompound().apply { + val offsetList = NbtList().apply { + add(NbtFloat.of(properties.translation.x)) + add(NbtFloat.of(properties.translation.y)) + add(NbtFloat.of(properties.translation.z)) + } + val rotList = NbtList().apply { + add(NbtFloat.of(properties.leftRotation.x)) + add(NbtFloat.of(properties.leftRotation.y)) + add(NbtFloat.of(properties.leftRotation.z)) + add(NbtFloat.of(properties.leftRotation.w)) + } + val scaleList = NbtList().apply { + add(NbtFloat.of(properties.scale.x)) + add(NbtFloat.of(properties.scale.y)) + add(NbtFloat.of(properties.scale.z)) + } + val rightRotList = NbtList().apply { + add(NbtFloat.of(properties.rightRotation.x)) + add(NbtFloat.of(properties.rightRotation.y)) + add(NbtFloat.of(properties.rightRotation.z)) + add(NbtFloat.of(properties.rightRotation.w)) + } + + put("translation", offsetList) + put("left_rotation", rotList) + put("scale", scaleList) + put("right_rotation", rightRotList) + }) + } + + e.readNbt(nbt) + + e.refreshPositionAndAngles(properties.pos.x, properties.pos.y, properties.pos.z, properties.rot.x, properties.rot.y) + + return e + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt new file mode 100644 index 0000000..f0d0187 --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt @@ -0,0 +1,18 @@ +package com.bytedice.bde_particles + +import net.minecraft.util.math.Vec3d +import org.joml.Vector2f +import org.joml.Vector3f +import org.joml.Vector4f + +data class DisplayEntityProperties ( + val pos: Vec3d = Vec3d(0.0, 0.0, 0.0), + val rot: Vector2f = Vector2f(0.0f, 0.0f), + + val blockType: String = "minecraft:purple_concrete", + + val translation: Vector3f = Vector3f(-0.5f, -0.5f, -0.5f), + val leftRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.0f, 1.0f), + val scale: Vector3f = Vector3f(1.0f, 1.0f, 1.0f), + val rightRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.0f, 1.0f) +) diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/GiveParticleEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/GiveParticleEmitter.kt new file mode 100644 index 0000000..e9c58ac --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/commands/GiveParticleEmitter.kt @@ -0,0 +1,28 @@ +package com.bytedice.bde_particles.commands + +import com.bytedice.bde_particles.items.ParticleEmitter +import com.mojang.brigadier.Command +import com.mojang.brigadier.CommandDispatcher +import com.mojang.brigadier.arguments.StringArgumentType +import net.minecraft.command.argument.ItemStackArgumentType +import net.minecraft.server.command.CommandManager +import net.minecraft.server.command.ServerCommandSource +import net.minecraft.text.Text + +object GiveParticleEmitter { + fun register(dispatcher: CommandDispatcher) { + dispatcher.register( + CommandManager.literal("giveParticleEmitter") + .requires { source -> source.hasPermissionLevel(2) } + .then(CommandManager.argument("item name", StringArgumentType.string())) + .then(CommandManager.argument("item type", ItemStackArgumentType.itemStack()))) // error here + .then(CommandManager.argument("particle id", StringArgumentType.string())) + + .executes { context -> + context.source.player?.inventory?.insertStack(ParticleEmitter().makeData()) // error here + context.source.sendFeedback({ Text.literal("Gave you 500Kg bomb. Don\'t get too silly with it :3") }, false) + Command.SINGLE_SUCCESS + } + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/items/ParticleEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/items/ParticleEmitter.kt new file mode 100644 index 0000000..5704875 --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/items/ParticleEmitter.kt @@ -0,0 +1,49 @@ +package com.bytedice.bde_particles.items + +import com.bytedice.bde_particles.math.raycastFromPlayer +import net.minecraft.component.DataComponentTypes +import net.minecraft.component.type.LoreComponent +import net.minecraft.component.type.NbtComponent +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtCompound +import net.minecraft.server.network.ServerPlayerEntity +import net.minecraft.text.Style +import net.minecraft.text.Text +import net.minecraft.text.TextColor +import java.awt.Color + + +class ParticleEmitter { + fun makeData(itemId: Item, name: String, particleId: String): ItemStack { + val i = ItemStack(itemId) + + val nbt = NbtCompound() + nbt.putByte("BPS_particleTool", 1) + nbt.putString("BPS_particleId", particleId) + + val component: NbtComponent = NbtComponent.of(nbt) + + val displayName = Text.literal(name) + .setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 125, 0).rgb)).withItalic(true)) + + val loreLines = listOf( + Text.literal("BPS").setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 125, 0).rgb)).withItalic(true)), + Text.literal("Bound to id \"$particleId\"").setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 125, 0).rgb)).withItalic(true)) + ) + + val lore = LoreComponent(loreLines) + + i.set(DataComponentTypes.ITEM_NAME, displayName) + i.set(DataComponentTypes.CUSTOM_DATA, component) + i.set(DataComponentTypes.LORE, lore) + + return i + } + + fun onRightCLick(player: ServerPlayerEntity) { + val hitResult = raycastFromPlayer(player, 4.5) ?: return + + // spawn particle at hitresult + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/math/main.kt b/src/main/kotlin/com/bytedice/bde_particles/math/main.kt new file mode 100644 index 0000000..bb70cf6 --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/math/main.kt @@ -0,0 +1,31 @@ +package com.bytedice.bde_particles.math + +import net.minecraft.server.network.ServerPlayerEntity +import net.minecraft.util.hit.HitResult +import net.minecraft.util.math.Vec3d +import net.minecraft.world.RaycastContext +import net.minecraft.world.World + + +fun raycastFromPlayer(player: ServerPlayerEntity, maxDistance: Double): HitResult? { + val world: World = player.world + val eyePos: Vec3d = player.getCameraPosVec(1.0f) + val lookVec: Vec3d = player.getRotationVec(1.0f) + val targetPos: Vec3d = eyePos.add(lookVec.multiply(maxDistance)) + + val blockHitResult = world.raycast( + RaycastContext( + eyePos, + targetPos, + RaycastContext.ShapeType.OUTLINE, + RaycastContext.FluidHandling.NONE, + player + ) + ) + + return if (blockHitResult.type == HitResult.Type.BLOCK) { + blockHitResult + } else { + null + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt b/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt new file mode 100644 index 0000000..cd1939c --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt @@ -0,0 +1,31 @@ +package com.bytedice.bde_particles.particle + +import net.minecraft.util.math.Vec3d +import org.joml.Vector3f +import org.joml.Vector4f + +class Particle( + // during init + count: Int = 20, + spawnDur: Int = 20, + lifetime: Int = 20, + offset: Vector3f = Vector3f(-0.5f, -0.5f, -0.5f), + rotation: Vector3f = Vector3f(0.0f, 0.0f, 0.0f), + //shape: Shape, // add later, start with single point + + // during ticking + // transformation + forceFields: Array = arrayOf(Vector4f(0.0f, 0.0f, 0.0f, 0.0f)), // x y z force + rotVel: Vector3f = Vector3f(0.0f, 0.0f, 0.0f), + sizeCurve: Array = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), + // physics + gravity: Vec3d = Vec3d(0.0, -9.0, 0.0), + drag: Float = 0.2f, + minVel: Float = 0.003f, + // rendering + blockCurve: Array = arrayOf("minecraft:black_concrete", "minecraft:green_concrete") + ) { + fun init() { + + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particle/Shape.kt b/src/main/kotlin/com/bytedice/bde_particles/particle/Shape.kt new file mode 100644 index 0000000..b63f571 --- /dev/null +++ b/src/main/kotlin/com/bytedice/bde_particles/particle/Shape.kt @@ -0,0 +1,5 @@ +package com.bytedice.bde_particles.particle + +class Shape { + +} \ No newline at end of file diff --git a/src/main/resources/bde_particles.mixins.json b/src/main/resources/bde_particles.mixins.json new file mode 100644 index 0000000..645900c --- /dev/null +++ b/src/main/resources/bde_particles.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.bytedice.bde_particles.mixin", + "compatibilityLevel": "JAVA_21", + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..b663eac --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "id": "bde_particles", + "version": "${version}", + "name": "BDE Particle System", + "description": "A server-side particle system ", + "authors": [], + "contact": {}, + "license": "All-Rights-Reserved", + "icon": "assets/bde_particles/icon.png", + "environment": "server", + "entrypoints": { + "main": [ + "com.bytedice.bde_particles.Bde_particles" + ] + }, + "mixins": [ + "bde_particles.mixins.json", + { + "config": "bde_particles.client.mixins.json", + "environment": "client" + } + ], + "depends": { + "fabricloader": ">=${loader_version}", + "fabric-language-kotlin": ">=${kotlin_loader_version}", + "fabric": "*", + "minecraft": "${minecraft_version}" + } +}