Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ffa-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
api(project(":katara", configuration = "namedElements"))
api(project(":aang", configuration = "namedElements"))
api(project(":toph", configuration = "namedElements"))
api(project(":spiderman", configuration = "namedElements"))

modApi(libs.bundles.fabric)
modApi(libs.bundles.silk)
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ include(":hero-api")
include(":katara")
include(":aang")
include(":toph")
include(":spiderman")
include(":ffa-server")

18 changes: 18 additions & 0 deletions spiderman/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version = "1.0.0"

dependencies {
implementation(project(":hero-api", configuration = "namedElements"))
implementation(project(":datatracker", configuration = "namedElements"))

modApi(libs.bundles.fabric)
modApi(libs.bundles.silk)
modApi(libs.bundles.performance)
modApi(libs.owolib)
modApi(libs.geckolib)
modApi(libs.emoteLib)
}

loom {
accessWidenerPath.set(file("src/main/resources/spiderman.accesswidener"))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package gg.norisk.heroes.spiderman

import gg.norisk.heroes.common.hero.Hero
import gg.norisk.heroes.common.hero.HeroManager.registerHero
import gg.norisk.heroes.spiderman.ability.SwingAbility
import gg.norisk.heroes.spiderman.ability.ThrowWebsAbility
import gg.norisk.heroes.spiderman.registry.EntityRegistry
import gg.norisk.heroes.spiderman.registry.EntityRendererRegistry
import net.fabricmc.api.ClientModInitializer
import net.fabricmc.api.DedicatedServerModInitializer
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
import net.minecraft.util.Identifier
import org.apache.logging.log4j.LogManager
import java.awt.Color

object SpidermanManager : ModInitializer, ClientModInitializer, DedicatedServerModInitializer {
private const val MOD_ID = "spiderman"
val logger = LogManager.getLogger(MOD_ID)
fun String.toId() = Identifier.of(MOD_ID, this)

override fun onInitialize() {
logger.info("Starting $MOD_ID Hero...")
EntityRegistry.init()
}

override fun onInitializeClient() {
ClientLifecycleEvents.CLIENT_STARTED.register {
registerHero(Spiderman)
}
EntityRendererRegistry.init()
}

override fun onInitializeServer() {
registerHero(Spiderman)
}

val Spiderman by Hero("Spiderman") {
color = Color.RED.rgb
ability(SwingAbility)
ability(ThrowWebsAbility)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package gg.norisk.heroes.spiderman.ability

import gg.norisk.heroes.client.option.HeroKeyBindings
import gg.norisk.heroes.common.HeroesManager.client
import gg.norisk.heroes.common.ability.NumberProperty
import gg.norisk.heroes.common.ability.operation.AddValueTotal
import gg.norisk.heroes.common.hero.ability.AbilityScope
import gg.norisk.heroes.common.hero.ability.implementation.PressAbility
import gg.norisk.heroes.spiderman.entity.SwingWebEntity
import gg.norisk.heroes.spiderman.registry.EntityRegistry
import io.wispforest.owo.ui.component.Components
import io.wispforest.owo.ui.core.Component
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.Items
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.Identifier
import net.minecraft.util.TypeFilter
import net.silkmc.silk.core.annotations.ExperimentalSilkApi
import net.silkmc.silk.core.entity.directionVector
import net.silkmc.silk.core.item.itemStack

val ropeLength = NumberProperty(50.0, 3, "Rope length", AddValueTotal(5.0, 10.0, 15.0, 20.0), 10).apply {
icon = {
Components.item(Items.FIREWORK_ROCKET.defaultStack)
}
}

val webShootPower = NumberProperty(1.0, 3, "Web shoot power", AddValueTotal(1.4, 1.9, 2.5), 20).apply {
icon = {
Components.item(Items.FIREWORK_ROCKET.defaultStack)
}
}

@OptIn(ExperimentalSilkApi::class)
object SwingAbility : PressAbility("Swing") {
init {
client {
keyBind = HeroKeyBindings.firstKeyBind
}
properties = listOf(ropeLength, webShootPower)
cooldownProperty = buildCooldown(60.0, 5, AddValueTotal(-10.0, -5.0, -5.0, -5.0, -10.0))
}

override fun getIconComponent(): Component {
return Components.item(itemStack(Items.STRING) {})
}

override fun getBackgroundTexture(): Identifier {
return Identifier.of("textures/block/packed_mud.png")
}

override fun onStart(player: PlayerEntity, abilityScope: AbilityScope) {
if (player.world is ServerWorld) {
val web = SwingWebEntity(EntityRegistry.SWING_WEB, player.world)
web.setPosition(player.eyePos)
web.owner = player
web.velocity = player.directionVector.multiply(webShootPower.getValue(player.uuid))
web.ropeLength = ropeLength.getValue(player.uuid)
player.world.spawnEntity(web)
}
}

override fun onDisable(player: PlayerEntity) {
val world = player.world as ServerWorld
for (entity in world.getEntitiesByType(TypeFilter.instanceOf(SwingWebEntity::class.java)) { true }) {
if (entity.owner == player) {
entity.discard()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package gg.norisk.heroes.spiderman.ability

import gg.norisk.heroes.client.option.HeroKeyBindings
import gg.norisk.heroes.common.HeroesManager.client
import gg.norisk.heroes.common.ability.NumberProperty
import gg.norisk.heroes.common.ability.operation.AddValueTotal
import gg.norisk.heroes.common.hero.ability.AbilityScope
import gg.norisk.heroes.common.hero.ability.implementation.PressAbility
import io.wispforest.owo.ui.component.Components
import io.wispforest.owo.ui.core.Component
import net.minecraft.block.Blocks
import net.minecraft.entity.EntityType
import net.minecraft.entity.FallingBlockEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.Items
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.Identifier
import net.silkmc.silk.core.annotations.ExperimentalSilkApi
import net.silkmc.silk.core.entity.directionVector
import net.silkmc.silk.core.item.itemStack

val webAmount = NumberProperty(1.0, 4, "Web amount", AddValueTotal(1.0, 1.0, 2.0, 2.0)).apply {
icon = {
Components.item(Items.COBWEB.defaultStack)
}
}

@OptIn(ExperimentalSilkApi::class)
object ThrowWebsAbility : PressAbility("Throw webs") {
init {
client {
keyBind = HeroKeyBindings.secondKeyBind
}
properties = listOf(webAmount)
cooldownProperty = buildCooldown(90.0, 5, AddValueTotal(-9.0, -9.0, -9.0, -9.0, -9.0))
}

override fun getIconComponent(): Component {
return Components.item(itemStack(Items.COBWEB) {})
}

override fun getBackgroundTexture(): Identifier {
return Identifier.of("textures/block/packed_mud.png")
}

override fun onStart(player: PlayerEntity, abilityScope: AbilityScope) {
if (player.world is ServerWorld) {
repeat(webAmount.getValue(player.uuid).toInt()) {
val web = FallingBlockEntity(EntityType.FALLING_BLOCK, player.world)
web.setPosition(player.eyePos)
web.block = Blocks.COBWEB.defaultState
web.velocity = player.directionVector.multiply(0.6).addRandom(player.world.random, 0.3f)
player.world.spawnEntity(web)
}
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reformat the code, indentations are not consistent and make the code hard to read (CTRL + ALT + L)

Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package gg.norisk.heroes.spiderman.client.render

import gg.norisk.heroes.spiderman.entity.SwingWebEntity
import net.minecraft.client.render.*
import net.minecraft.client.render.entity.EntityRenderer
import net.minecraft.client.render.entity.EntityRendererFactory
import net.minecraft.client.render.entity.state.EntityRenderState
import net.minecraft.client.render.entity.state.EntityRenderState.LeashData
import net.minecraft.client.render.item.ItemRenderState
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.item.ModelTransformationMode
import net.minecraft.util.math.MathHelper
import org.joml.Matrix4f

private val webItemStack = ItemStack(Items.COBWEB)

class SwingWebRenderState : EntityRenderState() {
val itemRenderState = ItemRenderState()
}

class SwingWebRenderer(context: EntityRendererFactory.Context) :
EntityRenderer<SwingWebEntity, SwingWebRenderState>(context) {
private val itemModelManager = context.itemModelManager

override fun createRenderState(): SwingWebRenderState? {
return SwingWebRenderState()
}

override fun updateRenderState(entity: SwingWebEntity, state: SwingWebRenderState, tickDelta: Float) {
super.updateRenderState(entity, state, tickDelta)
itemModelManager.updateForNonLivingEntity(
state.itemRenderState,
webItemStack,
ModelTransformationMode.GROUND,
entity)
if (state.leashData == null) {
state.leashData = LeashData()
}
state.leashData!!.startPos = entity.pos
val owner = entity.owner
state.leashData!!.endPos = if (owner != null) owner.pos.add(0.0, owner.height / 2.0, 0.0) else entity.pos
}

override fun render(state: SwingWebRenderState,
matrixStack: MatrixStack,
vertexConsumerProvider: VertexConsumerProvider,
light: Int) {
matrixStack.push()
matrixStack.multiply(dispatcher.rotation)
matrixStack.scale(4f, 4f, 4f)
state.itemRenderState.render(
matrixStack,
vertexConsumerProvider,
light,
OverlayTexture.DEFAULT_UV)
matrixStack.pop()

val leashData = state.leashData
if (leashData != null) {
renderLeash(matrixStack, vertexConsumerProvider, leashData)
}
}

// net.minecraft.client.render.entity.EntityRenderer.renderLeash
private fun renderLeash(matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, leashData: LeashData) {
val g = (leashData.endPos.x - leashData.startPos.x).toFloat()
val h = (leashData.endPos.y - leashData.startPos.y).toFloat()
val i = (leashData.endPos.z - leashData.startPos.z).toFloat()
val j = MathHelper.inverseSqrt(g * g + i * i) * 0.025f / 2.0f
val k = i * j
val l = g * j
matrices.push()
matrices.translate(leashData.offset)
val vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getLeash())
val matrix4f = matrices.peek().getPositionMatrix()

for (m in 0..24) {
renderLeashSegment(
vertexConsumer,
matrix4f,
g,
h,
i,
leashData.leashedEntityBlockLight,
leashData.leashHolderBlockLight,
leashData.leashedEntitySkyLight,
leashData.leashHolderSkyLight,
0.025f,
0.025f,
k,
l,
m,
false)
}

for (m in 24 downTo 0) {
renderLeashSegment(
vertexConsumer,
matrix4f,
g,
h,
i,
leashData.leashedEntityBlockLight,
leashData.leashHolderBlockLight,
leashData.leashedEntitySkyLight,
leashData.leashHolderSkyLight,
0.025f,
0.0f,
k,
l,
m,
true)
}

matrices.pop()
}

// net.minecraft.client.render.entity.EntityRenderer.renderLeashSegment
private fun renderLeashSegment(vertexConsumer: VertexConsumer,
matrix: Matrix4f,
leashedEntityX: Float,
leashedEntityY: Float,
leashedEntityZ: Float,
leashedEntityBlockLight: Int,
leashHolderBlockLight: Int,
leashedEntitySkyLight: Int,
leashHolderSkyLight: Int,
f: Float,
g: Float,
h: Float,
i: Float,
segmentIndex: Int,
isLeashKnot: Boolean) {
val j = segmentIndex.toFloat() / 24.0f
val k = MathHelper.lerp(j, leashedEntityBlockLight.toFloat(), leashHolderBlockLight.toFloat()).toInt()
val l = MathHelper.lerp(j, leashedEntitySkyLight.toFloat(), leashHolderSkyLight.toFloat()).toInt()
val m = LightmapTextureManager.pack(k, l)
val n = if (segmentIndex % 2 == (if (isLeashKnot) 1 else 0)) 0.7f else 1.0f
val o = 0.75f * n
val p = 0.75f * n
val q = 0.75f * n
val r = leashedEntityX * j
val s = if (leashedEntityY > 0.0f)
leashedEntityY * j * j
else
leashedEntityY - leashedEntityY * (1.0f - j) * (1.0f - j)
val t = leashedEntityZ * j
vertexConsumer.vertex(matrix, r - h * 6, s + g, t + i * 6).color(o, p, q, 1.0f).light(m)
vertexConsumer.vertex(matrix, r + h * 6, s + f - g, t - i * 6).color(o, p, q, 1.0f).light(m)
}
}
Loading