Jump to content

Alex Sim

Members
  • Posts

    46
  • Joined

  • Last visited

Everything posted by Alex Sim

  1. Maybe, but that's exactly what the Javassist library is designed for: to assist me raping the JVM Jokes aside, this would allow me to retain the old logic for a method on top of mine, and also possibly be compatible with any other hypothetical mod that would use the same approach (as if). I'm honestly not sure whether that's possible with coremods, but as far as I know two mods replacing the same class will conflict with each other If that's not the case I'll look into coremods
  2. Doesn't redefineClasses also retransform classes? public class Hello { public int helloWorld() { LogManager.getLogger().log(Level.INFO, "Hello World") } } init { //Based on my tests val hello = Hello() hello.helloWorld() //Prints "Hello World" Hello::class.addMethodAfter(Hello::helloWorld) { LogManager.getLogger().log(Level.INFO, "Goodbye World") } hello.helloWorld() //Prints "Hello World", then "Goodbye World" } I cannot add new methods or fields, but what I CAN do is change an existing method's bytecode, which is exactly what I'm doing (if you look at my source I found a little workaround to call my local variable (functional interface) by creating a new static class at runtime)
  3. ClassPool.getDefault().apply {appendClassPath(LoaderClassPath(Thread.currentThread().contextClassLoader))} This seems to work on non-dev-environment Minecraft, it used to throw javassist.NotFoundException without it; But you probably already know why this won't work and crush my hopes and dreams ?
  4. Should or could? Sorry if I sound insistent but I don't see what's the issue. Aside from practical ones (whether I could, and I seem to be one dll away from being able to), why should I not? My boredom knows no "should"
  5. BTW correct me if I'm wrong but the only issue here seems to be the attach library, if there was a way to use it in JRE (I'm open to suggestions) the rest would probably work
  6. I use Johnrengelman's shadowJar plugin to embed the libraries I use in my mod (and rename the base package), including the Kotlin runtime You're right about the instrumentation stuff though, it apparently doesn't work outside the dev environment ?
  7. My quarantine fueled boredom led my to try this anyway (would be useful for other purposes in my mod) So I made an utility class that uses Kotlin (1.4) extension functions, here is the Kotlin class on pastebin The methods to use are `addMethodAfter`, `addMethodBefore`, `replaceMethod` and `replaceMethodOrFallback` It's pretty small and should be easy enough to convert it to Java Here is an usage example (I call it from my mod's constructor): /** * Replaces animateTick so that it does nothing (fire particles not spawned) if in the Glacia dimension * Otherwise fallback to default method **/ WallTorchBlock::class.replaceMethodOrFallback(WallTorchBlock::animateTick) {(_, world) -> if ((world as World).dimension?.type != Glacia.DIMENSION.type) RedefineUtils.fallback() }
  8. Thanks, that's very helpful, I basically have to do something like this, definitely way easier than whatever tf I was trying to do
  9. I was just experimenting for now but my (probably unreachable) goal is to light every pixel differently (maybe using the alpha level) like so:
  10. Ok thanks for the info, how would I go about it tho? After a little bit of digging i found out WorldRenderer calls renderBlockLayer for each block RenderType inside the updateCameraAndRender method, is it possible to render my blocks without changing vanilla code?
  11. Hello, I'm trying to create a custom RenderType for my block, using a custom lightmap LightmapStateCustom object RenderTypes { private val SHADE_ENABLED = RenderState.ShadeModelState(true) private val LIGHTMAP_ENABLED = LightmapStateCustom() private val BLOCK_SHEET_MIPPED = RenderState.TextureState(AtlasTexture.LOCATION_BLOCKS_TEXTURE, false, true) val SOLID2: RenderType = RenderType.makeType("solid2", DefaultVertexFormats.BLOCK, 7, 2097152, true, false, RenderType.State.getBuilder().shadeModel(SHADE_ENABLED).lightmap(LIGHTMAP_ENABLED).texture(BLOCK_SHEET_MIPPED).build(true)) } For now the only methods LightmapStateCustom overrides are `equals(other)` and `hashCode()` (`RenderType.makeType` would otherwise return an existing RenderType) so the RenderType is logically identical to SOLID, but the block does not render (as you can see on the screenshot below)
  12. Thank you, I did that, however I still have a small issue: the recipe result's stack size is not updated if I insert the items one-by-one, only if I insert the whole stack alltogether, any idea how to fix this? Also I need to consume all of the ingredients' stack instead of one per ingredient BTW I have overridden ShapedRecipe and only changed the method getCraftingResult as below override fun getCraftingResult(inv: CraftingInventory): ItemStack { var count = 64 for (i in 0 until inv.sizeInventory) { val stack = inv.getStackInSlot(i) if (!stack.isEmpty) count = min(count, if(stack.isStackable) stack.count else 64) } return super.getCraftingResult(inv).apply {this.count = count} }
  13. Let's suppose I want to make a recipe with two items, a stackable one (eg: stick) and a non-stackable one (eg: plasma bucket) 1x plasma_bucket + 1x stick makes a plasma torch; 1x plasma_bucket + 64x stick makes 64 plasma torches Is this behaviour possible with forge?
  14. As I wrote above, I'm doing this for torches AND fire. I can just use the entity placement event for torches but not for fire (explosions, flint and steel, lava...)
  15. For some reason I get a terrible lag the moment I use world.setBlockState inside NeighborNotifyEvent, what would be the best "flags" argument to use in setBlockState
  16. That might be a good solution; is there any event that's fired when a block is placed even if it wasn't placed by an entity? (eg. an explosion starts a fire, but I don't want fire to spawn)
  17. I'm trying to make torches and wall torches not generate any light in my custom dimension To do that I use reflection to access the lightLevel parameter inside BlockState var BlockState.lightLevelKt : Int by ReflectField("field_215708_d", true) I then made a function to change the value for all possible BlockStates in a block, or reset it to default if no argument is passed fun Block.overrideLightValue(value: Int? = null) = stateContainer.validStates.forEach {it.lightLevelKt = value ?: getLightValue(it)} I then use the WorldEvent.Load event to change the lightLevel accordingly @SubscribeEvent fun onWorldLoad(event: WorldEvent.Load) = event.runClient { if (world.dimension.type.id == Glacia.DIMENSION.dimensionType.id) { Blocks.TORCH.overrideLightValue(0) Blocks.WALL_TORCH.overrideLightValue(0) } else { Blocks.TORCH.overrideLightValue() Blocks.WALL_TORCH.overrideLightValue() } } But I can see how this approach could conflict with any other mod using the same approach (even though it's kind of unlikely that two installed mods do this) as they would reset each other's lightValues Any ideas?
  18. I'm trying to port a dimension mod to 1.15.2; I have only this one issue: mobs spawned with EntityClassification.MONSTER spawn like they should (at night or in caves), but mobs with EntityClassification.CREATURE do not spawn at all (and yes, I register the spawn with EntitySpawnPlacementRegistry) here is the function i use (code is in Kotlin, very similar to Java) EntitySpawnPlacementRegistry.register(MY_ENTITY_TYPE, PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, EntitySpawnPlacementRegistry.IPlacementPredicate({ world, _, pos, _ -> world.getBlockState(pos.down()).run {this == Glacia.Blocks.GLACIAL_DIRT.stateSnowy || block == Blocks.GRASS_BLOCK} && world.getLightSubtracted(pos, 0) > 8; })) ^ snippet from Glacia_Entity.kt I call the `registerProperties()` function from my FMLCommonSetupEvent call and register the entities on my RegistryEvents class (the process might be a bit unusual, but it works, and i can spawn them with commands) Here is how I add the spawns in my Biome constructor this.addSpawn(EntityClassification.MONSTER, SpawnListEntry(EntityType.SLIME, 50, 4, 4)) this.addSpawn(EntityClassification.CREATURE, SpawnListEntry(Glacia.Entity.GLACIAL_TURTLE, 40, 4, 4)) this.addSpawn(EntityClassification.CREATURE, SpawnListEntry(Glacia.Entity.SABER_TOOTHED_CAT, 30, 4, 4)) this.addSpawn(EntityClassification.CREATURE, SpawnListEntry(Glacia.Entity.REINDEER, 25, 5, 8)) this.addSpawn(EntityClassification.CREATURE, SpawnListEntry(Glacia.Entity.PENGUIN, 20, 5, 8)) this.addSpawn(EntityClassification.MONSTER, SpawnListEntry(Glacia.Entity.GLACIAL_SEEKER, 100, 5, 8)) ^ snippet from BiomeGlaciaPlains.kt As I previously said, GLACIAL_SEEKER spawns correctly while the other custom mobs do not; am I missing something? EDIT: if that can help, my biome uses a custom block as "grass", which I already added to the spawn conditions
  19. What I find unnecessary is the fact that this can't be set though a block property (eg. setRenderType(RenderType)) and handled during block registration; after all it's very similar to what I'm doing now with reflection so it's definitely possible
  20. Need some extra info: how would I go about making an armor set translucent?
  21. Wow that's an unnecessarily complicated change Thank god I can use Kotlin extension properties... And I'm already using reflection for registration ?
  22. I'm trying to create transparent/translucent blocks in Minecraft 1.15.2 (Forge v. 31.1.30). The leaves and flowers in the screenshot below should have cutout spots, while the blue blocks on the right should be translucent (semi-transparent) like glass or ice. And yes I am using the notSolid() property, I have overridden getAmbientOcclusionLightValue, propagatesSkylightDown, isNormalCube and isSideInvisible, I have even tried using the default GlassBlock class for the blue block on the right (same result). I am trying to port a mod from 1.14.4, the blocks looked fine in that version
  23. I tried to make something similar to what @jabelar does here (this was from 1.12) but it seems to only work for other entities, not the player; Here's my code so far, it's in Kotlin BTW: //This variable uses a small reflection delegate I made var Entity.submergedHeightKt : Double by ReflectField("field_211517_W") @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) fun onPlayerTickEvent(event: PlayerTickEvent) = event.player.takeIf {event.phase === TickEvent.Phase.START && it.world.isRemote}?.apply { handleFluidAccelerationKt(Glacia.Blocks.PLASMA) } @SubscribeEvent(priority=EventPriority.NORMAL, receiveCanceled=true) fun onWorldTickEvent(event: TickEvent.WorldTickEvent) = (event.world as? ServerWorld)?.takeIf {event.phase !== TickEvent.Phase.END}?.entities?.forEach { entity -> entity.handleFluidAccelerationKt(Glacia.Blocks.PLASMA) } fun Entity.handleFluidAccelerationKt(block: Block): Boolean { val axisAlignedBB = boundingBox.shrink(0.001) val i = MathHelper.floor(axisAlignedBB.minX) val j = MathHelper.ceil(axisAlignedBB.maxX) val k = MathHelper.floor(axisAlignedBB.minY) val l = MathHelper.ceil(axisAlignedBB.maxY) val i1 = MathHelper.floor(axisAlignedBB.minZ) val j1 = MathHelper.ceil(axisAlignedBB.maxZ) if (!world.isAreaLoaded(i, k, i1, j, l, j1)) return false else { var d0 = 0.0 val flag = this.isPushedByWater var flag1 = false var vec3d = Vec3d.ZERO var k1 = 0 BlockPos.PooledMutableBlockPos.retain().use {mutableBlockPos -> for (l1 in i until j) { for (i2 in k until l) { for (j2 in i1 until j1) { mutableBlockPos.setPos(l1, i2, j2) val fluidState = this.world.getFluidState(mutableBlockPos) if (fluidState.blockState.block === block) { val d1 = (i2.toFloat() + fluidState.func_215679_a(this.world, mutableBlockPos)).toDouble() if (d1 >= axisAlignedBB.minY) { flag1 = true d0 = Math.max(d1 - axisAlignedBB.minY, d0) if (flag) { var vec3d1 = fluidState.getFlow(this.world, mutableBlockPos) if (d0 < 0.4) { vec3d1 = vec3d1.scale(d0) } vec3d = vec3d.add(vec3d1) ++k1 } } } } } } } if (vec3d.length() > 0.0) { if (k1 > 0) vec3d = vec3d.scale(1.0 / k1.toDouble()) if (this !is PlayerEntity) vec3d = vec3d.normalize() motion = motion.add(vec3d.scale(0.014)) } submergedHeightKt = d0 return flag1 } }
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.