Jump to content

SoLegendary

Members
  • Posts

    95
  • Joined

  • Last visited

Everything posted by SoLegendary

  1. For some context, I am making a mod that recreates minecraft as a top-down strategy game (see: https://www.youtube.com/watch?v=2kL4vyjE2Mc). As part of this, I am implementing a "fog of war" effect where chunks outside of range of your base and mobs are greyed out and only render blocks as they appeared the last time you explored it with a mob. This currently works in my latest mod build but has the issue that when the chunk is unloaded and then reloaded (eg. by moving it out of your render chunk range and then back in), the blocks in the chunk are updated, which is not ideal. If I can keep these unexplored chunks loaded indefinitely, then this issue would be fixed because the client would never update the chunk's blocks. I'm not too concerned for performance issues here as I would only need to apply this indefinite loading to a select few chunks at a time (the ones containing other players' buildings). I've tried cancelling the ChunkEvent.Unload event but it doesn't seem to do anything, and I'm not actually sure its related to rendering at all.
  2. Ok actually nevermind, I found I can cancel BlockRenderDispatcher.renderBatched with a mixin to hide the blocks entirely. If there a way to do the transparency route though I would still like to know as that will mean I can retain the leaf texture instead of having to use some other transparent block.
  3. For some context, since this sounds like something trying to make a cheat mod would be doing, I have a mod that has you play Minecraft in a top-down perspective controlling mobs as units in a strategy game. https://www.youtube.com/watch?v=2kL4vyjE2Mc One issue I have right now is that forests are very difficult to move through because you can't easily see your mobs through leaves. To combat this, I want to be able to make these vanilla leaf blocks either completely hidden or transparent at specific locations (I know where all of the required BlockPoses will be to do this). Ideally I would like them to be transparent, but if they their rendering can be cancelled entirely, I can also render blocks which are partially transparent (eg. glass) in their place to achieve the same effect. Another idea I had was to have all vanilla leaf blocks replaced by some equivalent custom block that I have control over, but that would be a lot of work and I wanted to know if I could do it without that first before attempting it.
  4. I am trying to update my code from 1.19.3 to 1.19.4 but am having trouble adapting the NbtUtils.readBlockState method - this function used to just take one CompoundTag parameter but now it takes the CompoundTag and a HolderGetter<Block> pBlockGetter parameter. Where am I supposed to get pBlockGetter from? I primarily use this method for reading NBT structure data from my mod's resource files. The player can create structures which are saved into both client and server sides (so this method can run on both sides). My code for the method is here: https://github.com/SoLegendary/reignofnether/blob/1.19.4/src/main/java/com/solegendary/reignofnether/building/BuildingBlockData.java#L67-L74 In the future is there a guide for how to update methods like this on a new Minecraft version?
  5. I want to disable the generation of specific biomes on new world creation. I also want to tweak some other world generation features of specific other biomes (eg. changing density of trees in a forest, density of surface ores on a mountain, etc.) I see lots of options for creating new custom biomes with datapacks (eg. using https://misode.github.io/worldgen/biome/), I don't know how to modify existing biomes or remove them entirely. Is there a way to do it in the Java code or are data packs the best way? Is there a guide someone can provide for it?
  6. In case anyone else has this very specific problem managed to solve it by writing a mixin for LevelRenderer.renderLevel() with just the blockDestructionProgress snippet but with the > 1024 condition reversed: // rerun blockDestroyProgress actions but with > sqrt(1024) range @Inject( method = "renderLevel", at = @At("TAIL") ) private void renderLevel(PoseStack pPoseStack, float pPartialTick, long pFinishNanoTime, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pProjectionMatrix, CallbackInfo ci) { Vec3 vec3 = pCamera.getPosition(); double d0 = vec3.x(); double d1 = vec3.y(); double d2 = vec3.z(); ObjectIterator var42 = this.destructionProgress.long2ObjectEntrySet().iterator(); while (var42.hasNext()) { Long2ObjectMap.Entry<SortedSet<BlockDestructionProgress>> entry = (Long2ObjectMap.Entry) var42.next(); BlockPos blockpos2 = BlockPos.of(entry.getLongKey()); double d3 = (double) blockpos2.getX() - d0; double d4 = (double) blockpos2.getY() - d1; double d5 = (double) blockpos2.getZ() - d2; if ((d3 * d3 + d4 * d4 + d5 * d5 > 1024.0)) { SortedSet<BlockDestructionProgress> sortedset1 = (SortedSet) entry.getValue(); if (sortedset1 != null && !sortedset1.isEmpty()) { int k1 = (sortedset1.last()).getProgress(); pPoseStack.pushPose(); pPoseStack.translate((double) blockpos2.getX() - d0, (double) blockpos2.getY() - d1, (double) blockpos2.getZ() - d2); PoseStack.Pose posestack$pose = pPoseStack.last(); VertexConsumer vertexconsumer1 = new SheetedDecalTextureGenerator(this.renderBuffers.crumblingBufferSource().getBuffer((RenderType) ModelBakery.DESTROY_TYPES.get(k1)), posestack$pose.pose(), posestack$pose.normal()); ModelData modelData = this.level.getModelDataManager().getAt(blockpos2); this.minecraft.getBlockRenderer().renderBreakingTexture(this.level.getBlockState(blockpos2), blockpos2, this.level, pPoseStack, vertexconsumer1, modelData == null ? ModelData.EMPTY : modelData); pPoseStack.popPose(); } } } }
  7. My mod is often viewed from far distances (up to 100s of blocks away), which means that the crack overlay textures from blocks being destroyed aren't being rendered (I have custom mobs that break blocks with these overlays applied). I am applying the destroyProgress textures like this (clientside): this.mob.level.destroyBlockProgress(this.mob.getId(), this.gatherTarget, gatherProgress); How can I extend the range that they are rendered at?
  8. I have a custom humanoid mob with arms that I can directly control the XYZ rotation values of. I want to be able to trigger a swinging animation just like the one that the player has when left clicking. I've tried using the LivingEntity.swing() method from clientside but it doesn't seem to do anything. I understand it probably needs to be triggered from serverside so that all clients can see the animation, but I'm just testing it for the time being. Is there a way I can use a swing() method here or something similar or do I need to actually meticulously set the rotation values of my mob's arm myself? If the latter, where are those calculations done so I can copy the numbers?
  9. I'm playing around with changing the client brightness of specific chunks by modifying shading functions with mixins. I've got this working properly and I set the affected chunks as dirty whenever their brightness is changed so it updates automatically. Note that this is purely clientside as I am not changing block light values, only the rendering functions. However, there are often lines at the edges of the chunks with the original brightness. This only happens when smooth lighting is enabled. For example, when I change chunks from full brightness to dark, I get effects like this left over: These are removed when I place or destroy a block in the chunk, however, they sometimes reappear when the chunk is rerendered, even when just moving it out of the view frustum by turning around. How can I trigger a lighting update in code that I can run whenever the chunk is rendered? This is what I've tried so far after reading ClientLevel.setBlock() but it doesn't seem to do anything. MC.level.getProfiler().push("queueCheckLight"); MC.level.getChunkSource().getLightEngine().checkBlock(MC.player.getOnPos()); MC.level.getProfiler().pop(); MC.level.markAndNotifyBlock(MC.player.getOnPos(), (LevelChunk) MC.level.getChunk(MC.player.getOnPos()), Blocks.AIR.defaultBlockState(), Blocks.DIRT.defaultBlockState(), 3, 512);
  10. I'm trying to add a mixin to ChunkRenderDispatcher.RenderChunk.RebuildTask I also need to access class methods from its superclass, ChunkRenderDispatcher.RenderChunk.ChunkCompileTask so I had my mixin extend this same class and put in a dummy constructor to avoid the compile error. However, I'm getting this error when I try to run: This is the code I have: https://pastebin.com/kSPaEPYU I've also tried wrapping my mixin class with a class extending ChunkRenderDispatcher.RenderChunk which in turn is wrapped with a class extending ChunkRenderDispatcher like so: https://pastebin.com/33JnUSKZ However, this gives me the error: But when I make it static, I get the same original error again. EDIT: Nevermind, found a different solution not requiring mixins here
  11. I've been playing around with how chunk rendering works, and found how to conditionally render specific chunks with this code: https://pastebin.com/5UzA0s1F This code prevents the rendering of all chunks outside of a 30 block radius around a specific mob type. However, my end goal is to just apply a shader to show those chunks are out of range, rather than just not render them at all - something simple like painting them all black or changing it to monochrome. I believe I'd have to write a fragment shader (.fsh) for this which I've done before but only in isolation, playing around with this editor here: https://patriciogonzalezvivo.github.io/glslEditor/. I am assuming here that the shader I write can get an input of the original colour of each pixel which I can then modify. Does Forge provide this compatibility and if so, how can I go about registering and applying the shader in code once it's been written? Also, I don't think I'm going worry about rendering entities or block entities in these "dark" chunks so hopefully that simplifies this. EDIT: nevermind, I found a solution that doesn't require shaders - since I just want to darken the chunks and not apply any complex effects, I realised I can just mixin ModelBlockRenderer and change the lightmap values.
  12. I think you meant to extend a class further down than LivingEntity (probably at least Mob?), there's a lot of classes in the inheritance line between LivingEntity and most vanilla mobs. Eg. a zombie: LivingEntity -> Mob -> PathfinderMob -> Monster -> Zombie
  13. Make sure where you're inserting the code is actually the last place it's being updated. In your case, PlayerRenderer.renderHand() runs setModelProperties() where your code sets it to 90F, THEN it sets the arm xRot to 0.0F again, so you probably want to set the xRot at the TAIL of renderHand()
  14. If you want to apply conditional damage (eg, bonus against a particular enemy) I'd suggest using LivingDamageEvent, where you can get the entity being damaged, the source of the damage, and get/set the amount of damage.
  15. I think I found the issue: when the player is in an unloaded chunk (ie. has never been loaded before in the world) renderChunkInfos is reduced to only your current chunk and adjacent chunks, but since my code only allowed rendering of the chunks near the mob I specified, it never gets a chance to load anything else. The solution may be to allow the player's immediate chunk to be loaded to avoid this issue, though I hope I can still not actually render it somehow.
  16. Ok so i've got it mostly reliable now, and managed to force a frustum update every tick so it doesn't rely on the camera to move to update. @Final @Shadow private ObjectArrayList<LevelRenderer.RenderChunkInfo> renderChunksInFrustum; @Final @Shadow private AtomicReference<LevelRenderer.RenderChunkStorage> renderChunkStorage = new AtomicReference<>(); @Final @Shadow private Minecraft minecraft; @Inject( method = "applyFrustum(Lnet/minecraft/client/renderer/culling/Frustum;)V", at = @At("HEAD"), cancellable = true ) private void applyFrustum(Frustum pFrustum, CallbackInfo ci) { ci.cancel(); if (!Minecraft.getInstance().isSameThread()) { throw new IllegalStateException("applyFrustum called from wrong thread: " + Thread.currentThread().getName()); } else { this.minecraft.getProfiler().push("apply_frustum"); this.renderChunksInFrustum.clear(); LinkedHashSet<LevelRenderer.RenderChunkInfo> renderChunkInfos = (this.renderChunkStorage.get()).renderChunks; for(LevelRenderer.RenderChunkInfo chunkInfo : renderChunkInfos) { if (pFrustum.isVisible(chunkInfo.chunk.getBoundingBox())) { for (LivingEntity entity : UnitClientEvents.getAllUnits()) { Vec3 centre = chunkInfo.chunk.bb.getCenter(); Vec2 centre2d = new Vec2((float) centre.x(), (float) centre.z()); Vec2 entity2d = new Vec2((float) entity.getX(), (float) entity.getZ()); if (entity2d.distanceToSqr(centre2d) < 900) { this.renderChunksInFrustum.add(chunkInfo); break; } } } } this.minecraft.getProfiler().pop(); } } However, i'm testing out only rendering chunks close to specific entities (for testing, centre of the chunk must be within 30 blocks of the entity), which kind of works but only when the viewing player is at specific positions: However, if I move the player too far away from the entity, all of these chunks disappear, and renderChunkInfos contains only 7 items, instead of the usual 1000+, so it's not even an issue of my filtering logic. It's not the case that the entity i'm using to test distance with no longer exists as it is still loaded clientside (the leftmost mob in the below image). It also doesn't seem to be a frustum issue as it still happens even as I move the camera around. What is causing this and why is it tied to the player position? EDIT: by "too far away" I mean only a few blocks away, basically just 1 chunk further than away than in the top image, not out of normal render distance of course
  17. I'm trying to conditionally hide specific chunks by disabling their rendering logic. I've found that LevelRenderer does this using renderChunksInFrustum but I don't think this is the only place they are rendered. I've got this mixin that (for testing purposes) just hides every 2nd chunk on the X axis: @Mixin(LevelRenderer.class) public abstract class LevelRendererMixin { @Final @Shadow private ObjectArrayList<LevelRenderer.RenderChunkInfo> renderChunksInFrustum; @Inject( method = "renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;FJZLnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/GameRenderer;Lnet/minecraft/client/renderer/LightTexture;Lcom/mojang/math/Matrix4f;)V", at = @At("HEAD") ) private void renderlevel(PoseStack pPoseStack, float pPartialTick, long pFinishNanoTime, boolean pRenderBlockOutline, Camera pCamera, GameRenderer pGameRenderer, LightTexture pLightTexture, Matrix4f pProjectionMatrix, CallbackInfo ci) { if (OrthoviewClientEvents.isEnabled()) renderChunksInFrustum.removeIf(chunkInfo -> chunkInfo.chunk.bb.minX % 32 == 0) } } While this does hide the chunks I expected (see below), it seems it only works while the camera is stationary. While the camera is moving, all chunks will still show, causing a flickering effect as you move around. Note that the Orthoview flag in my mod is just the isometric camera being enabled, but this problem happens in the regular camera too so that isn't an issue. Where is the logic to render chunks while the camera is moving and how can I apply the same conditions I want to it from my mixin?
  18. Oh I found the issue, for some reason this only works while NOT in spectator mode, but unfortunately my mod requires you to be in spectator mode most of the time... I've tried with all stages, and it seems spectator mode just hard-sets the depth test on or something like that. If anyone knows where this is actually done, I could maybe modify it with a mixin or access transformer...
  19. I have this function to render some simple boxes: public static void drawLineBox(PoseStack matrixStack, AABB aabb, float r, float g, float b, float a) { Entity camEntity = MC.getCameraEntity(); double d0 = camEntity.getX(); double d1 = camEntity.getY() + camEntity.getEyeHeight(); double d2 = camEntity.getZ(); RenderSystem.disableDepthTest(); // enable showing lines through blocks RenderSystem.depthMask(false); VertexConsumer vertexConsumer = MC.renderBuffers().bufferSource().getBuffer(RenderType.lines()); matrixStack.pushPose(); matrixStack.translate(-d0, -d1, -d2); // because we start at 0,0,0 relative to camera LevelRenderer.renderLineBox(matrixStack, vertexConsumer, aabb, r, g, b, a); matrixStack.popPose(); } But these though i've disabled the depth test and depthMask the lines still won't show through blocks. I'm running the above inside RenderLevelStageEvent with the stage set to RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS (I've also tried AFTER_SOLID_BLOCKS). I've also tried moving around the disable lines to after the pushPose() but that's not worked either...
  20. I've tried replacing the DepthTestStateShard in RenderType.CompositeRenderType.OUTLINE with different variations: I sourced the values for the 2nd param from here: https://github.com/drbrain/opengl/blob/master/ext/opengl/gl-enums.h for the comparison operators listed here https://learnopengl.com/Advanced-OpenGL/Depth-testing new RenderStateShard.DepthTestStateShard("always", 0x0207), // GL_ALWAYS new RenderStateShard.DepthTestStateShard("never", 0x0200), // GL_NEVER new RenderStateShard.DepthTestStateShard("<", 0x0201), // GL_LESS new RenderStateShard.DepthTestStateShard("==", 0x0202), // GL_EQUAL new RenderStateShard.DepthTestStateShard("<=", 0x0203), // GL_LEQUAL new RenderStateShard.DepthTestStateShard(">", 0x0204), // GL_GREATER new RenderStateShard.DepthTestStateShard("!=", 0x0205), // GL_NOTEQUAL new RenderStateShard.DepthTestStateShard(">=", 0x0206) // GL_GEQUAL And I assigned it like this, with the above values in myShard (and after making all the necessary fields public with access transformer) RenderType.CompositeRenderType.OUTLINE = Util.memoize((p_173272_, p_173273_) -> { return RenderType.create("outline", DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, RenderType.CompositeState.builder() .setShaderState(RenderStateShard.RENDERTYPE_OUTLINE_SHADER) .setTextureState(new RenderStateShard.TextureStateShard(p_173272_, false, false)).setCullState(p_173273_) .setDepthTestState(myShard).setOutputState(RenderStateShard.OUTLINE_TARGET) .createCompositeState(RenderType.OutlineProperty.IS_OUTLINE)); }); However, this didn't seem to really have the desired effect, half of them (==, !=, never, >, >=) just remove the glow entirely, except for held items (maybe since they use a different shard), while the other half have no effect at all on the glow. Am I looking at the completely wrong thing code-wise?
  21. I think I might need to take a step back: How can I just render this kind of entity outline on demand in the first place? I have code like the one above to draw line boxes and lines (RenderType.lines()) and solid planes with transparency (RenderType.entityTranslucent()), but have never tried anything as complex as an entity outline. I've found there is RenderType.outline() and I've that it accepts POSITION_COLOR_TEX vertices in the form of quads, but I have zero clue how I would even quantify the vertices and their positions, or if this is even the correct strategy for rendering entity outlines.
  22. What do you mean by 'create a new shard' ? EDIT: also, how can I actually get the depth of the render output when I do basic rendering functions, like in my sample code above?
  23. My mod relies on a top-down view, which makes it very difficult to see mobs indoors and behind trees and other structures. I know that the glow effect is a thing which looked like a nice solution, however I don't want the full effect of it displayed at all times. Ideally, I want only the portion of a mob's model that is behind any block to be highlighted with the glow effect. Here's a mockup of what I mean: Additionally, I want to be able to control the thickness and colour of the effect too, with the same mob showing as different colours to different people based on my own variables. EDIT: If this turns out to be too complex, I may settle for just drawing simple lines, which I already do for my mobs (see the red square at the bottom of the villager's feet above). However, I can't seem to get those to render on the top layer (ie. in front of all other mobs and blocks). This is the code I have to render this now: public static void drawLineBox(PoseStack matrixStack, AABB aabb, float r, float g, float b, float a) { Entity camEntity = MC.getCameraEntity(); double d0 = camEntity.getX(); double d1 = camEntity.getY() + camEntity.getEyeHeight(); double d2 = camEntity.getZ(); RenderSystem.depthMask(true); // should control whether lines show behind blocks or not but has no effect whether true or false? VertexConsumer vertexConsumer = MC.renderBuffers().bufferSource().getBuffer(RenderType.lines()); matrixStack.pushPose(); matrixStack.translate(-d0, -d1, -d2); LevelRenderer.renderLineBox(matrixStack, vertexConsumer, aabb, r, g, b, a); matrixStack.popPose(); }
  24. Ok actually I just realised it may be related to the fact that the vanilla IronGolem class already has a getAttackDamage method so maybe the client thinks i'm trying to override that instead of implementing the attackerUnit method? I'm still confused as to why this only happens in the Forge client and not my local environment though. If anyone can please enlighten me that would be great to avoid issues like this in the future.
×
×
  • Create New...

Important Information

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