Jump to content

Andrew Murdza

Members
  • Posts

    35
  • Joined

  • Last visited

Everything posted by Andrew Murdza

  1. I made a cavevines decorator feature which places cave vines under the leaves of trees public class CaveVinesFeature extends TreeDecorator { public static Codec<CaveVinesFeature> CODEC; public static TreeDecoratorType<CaveVinesFeature> type; public static float chance=1.0F; public static float maxPercent=100F;//0.01F; //private float chance; private int minAge; private int maxAge; private float berriesChance; private Function<Random, Integer> height; //this structure doesn't do anything public CaveVinesFeature(float chance){//, int minAge, int maxAge, float berriesChance, Function<Random,Integer> height){ this.chance=chance; this.minAge=25;//minAge; this.maxAge=25;//maxAge; this.berriesChance=1;//berriesChance; this.height=height; //CODEC=Codec.unit(() -> this); } public CaveVinesFeature(){ this(chance); } public boolean generateVineColumn(LevelSimulatedReader world, Random random, BlockPos.MutableBlockPos pos, BiConsumer<BlockPos, BlockState> replacer) { int length=0;//height.apply(random); BlockPos.MutableBlockPos pos1=pos.mutable(); for(int i=0;i<4;i++){ Direction dir=Direction.from2DDataValue(i); if(!Feature.isAir(world,pos1.move(dir))){ return false; } for(int j=0;j<4;j++) { Direction dir1 = Direction.from2DDataValue(j); if(!Feature.isAir(world,pos1.move(dir).move(dir1))){ return false; } } } while(Feature.isAir(world,pos1)){ length++; pos1.move(Direction.DOWN); } length=length-4; length=Math.min(length,6); //length=length<=0?0:random.nextInt(length); boolean flag=false; for (int i = 0; i <= length; ++i) { if (Feature.isAir(world,pos)) { if (i == length || !Feature.isAir(world,pos.below())) { flag=true; int age= Mth.nextInt(random, minAge, maxAge); BlockState state= Blocks.CAVE_VINES.defaultBlockState().setValue(BlockStateProperties.AGE_25, age); state=state.setValue(BlockStateProperties.BERRIES,random.nextFloat()<berriesChance?true:false); replacer.accept(pos,state); break; } replacer.accept(pos,Blocks.CAVE_VINES_PLANT.defaultBlockState().setValue(BlockStateProperties.BERRIES,random.nextFloat()<berriesChance?true:false)); } pos.move(Direction.DOWN); } return flag; } protected TreeDecoratorType<?> type() { return type; } @Override public void place(LevelSimulatedReader world, BiConsumer<BlockPos, BlockState> blockSetter, Random random, List<BlockPos> pLogPositions, List<BlockPos> leafPositions) { AtomicInteger sum= new AtomicInteger(); int maxVines=(int)(maxPercent*leafPositions.size()); List<BlockPos> positions=new ArrayList<>(); leafPositions.forEach(pos -> { if(random.nextFloat()<chance&& sum.get() <maxVines){ sum.set(sum.get() + 1); generateVines(pos,world,random,blockSetter,positions); } }); } private void generateVines(BlockPos pos, LevelSimulatedReader world, Random random, BiConsumer<BlockPos, BlockState> replacer, List<BlockPos> positions) { BlockPos.MutableBlockPos mutable = pos.mutable().move(Direction.DOWN); if (!Feature.isAir(world,mutable)) { return; } for(BlockPos pos1: positions){ int x=pos1.getX(); int z=pos1.getZ(); if(Math.abs(x-pos.getX())<4||Math.abs(z-pos.getZ())<4){ return; } } if(generateVineColumn(world, random, mutable, replacer)){ positions.add(mutable); } } } Then I registered the cave vines feature @Mod.EventBusSubscriber(modid = "aoemod", bus = Mod.EventBusSubscriber.Bus.MOD) public class TreeDecoratorRegistry { @SubscribeEvent public static void registerFeatures(RegistryEvent.Register<TreeDecoratorType<?>> event) { IForgeRegistry registry=event.getRegistry(); CaveVinesFeature caveVines=new CaveVinesFeature(); CaveVinesFeature.CODEC= Codec.unit(() -> caveVines); CaveVinesFeature.type=(TreeDecoratorType<CaveVinesFeature>) TreeDecoratedAccessor.createType(CaveVinesFeature.CODEC); register("cave_vines",registry, CaveVinesFeature.type); } public static void register(String name,IForgeRegistry registry, TreeDecoratorType decoratorType){ decoratorType.setRegistryName(new ResourceLocation("aoemod", name)); registry.register(decoratorType); } } Then I made JSON file for a configured feature which is a tree that uses my decorator { "type": "minecraft:tree", "config": { "decorators": [ { "type": "minecraft:cocoa", "probability": 0.2 }, { "type": "minecraft:trunk_vine" }, { "type": "aoemod:cave_vines" }, { "type": "minecraft:leave_vine", "probability": 0.25 } ], "dirt_provider": { "type": "minecraft:simple_state_provider", "state": { "Name": "minecraft:dirt" } }, "foliage_placer": { "type": "minecraft:blob_foliage_placer", "height": 3, "offset": 0, "radius": 2 }, "foliage_provider": { "type": "minecraft:simple_state_provider", "state": { "Name": "minecraft:jungle_leaves", "Properties": { "distance": "7", "persistent": "false", "waterlogged": "false" } } }, "force_dirt": false, "ignore_vines": true, "minimum_size": { "type": "minecraft:two_layers_feature_size", "limit": 1, "lower_size": 0, "upper_size": 1 }, "trunk_placer": { "type": "minecraft:straight_trunk_placer", "base_height": 4, "height_rand_a": 8, "height_rand_b": 0 }, "trunk_provider": { "type": "minecraft:simple_state_provider", "state": { "Name": "minecraft:jungle_log", "Properties": { "axis": "y" } } } } } When I try to create a world I get the following error: I believe that I have registered my cave vines treedecoratedtype incorrectly. I have also put in a print statement instead of the registry event so I know the registry event runs. Please let me know how I can fix the registry event.
  2. I found the method public static <T extends Mob> void register(EntityType<T> pEntityType, SpawnPlacements.Type pDecoratorType, Heightmap.Types pHeightMapType, SpawnPlacements.SpawnPredicate<T> pDecoratorPredicate) { SpawnPlacements.Data spawnplacements$data = DATA_BY_TYPE.put(pEntityType, new SpawnPlacements.Data(pHeightMapType, pDecoratorType, pDecoratorPredicate)); if (spawnplacements$data != null) { throw new IllegalStateException("Duplicate registration for type " + Registry.ENTITY_TYPE.getKey(pEntityType)); } } Which refers to DATA_BY_TYPE. private static final Map<EntityType<?>, SpawnPlacements.Data> DATA_BY_TYPE = Maps.newHashMap(); The register method itself cannot be used to replace the Axolotl spawn condition because of the IllegalStateException but I could use reflection to access DATA_BY_TYPE and then call the put method with my custom method (which always returns true) in place of checkAxolotlSpawnRules. The problem is that I don't know where/when to use the reflection because the reflection must occur after register(EntityType.AXOLOTL, SpawnPlacements.Type.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Axolotl::checkAxolotlSpawnRules); Which occurs as part of the static{...} of the SpawnPlacements class
  3. The line of code that causes the issue is register(EntityType.AXOLOTL, SpawnPlacements.Type.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Axolotl::checkAxolotlSpawnRules); Which references the method public static boolean checkAxolotlSpawnRules(EntityType<? extends LivingEntity> p_186250_, ServerLevelAccessor p_186251_, MobSpawnType p_186252_, BlockPos p_186253_, Random p_186254_) { return p_186251_.getBlockState(p_186253_.below()).is(BlockTags.AXOLOTLS_SPAWNABLE_ON); } I found that the method I am interested in is private static boolean isValidSpawnPostitionForType(ServerLevel pLevel, MobCategory pCategory, StructureFeatureManager pStructureManager, ChunkGenerator pGenerator, MobSpawnSettings.SpawnerData pData, BlockPos.MutableBlockPos pPos, double pDistance) { EntityType<?> entitytype = pData.type; if (entitytype.getCategory() == MobCategory.MISC) { return false; } else if (!entitytype.canSpawnFarFromPlayer() && pDistance > (double)(entitytype.getCategory().getDespawnDistance() * entitytype.getCategory().getDespawnDistance())) { return false; } else if (entitytype.canSummon() && canSpawnMobAt(pLevel, pStructureManager, pGenerator, pCategory, pData, pPos)) { SpawnPlacements.Type spawnplacements$type = SpawnPlacements.getPlacementType(entitytype); if (!isSpawnPositionOk(spawnplacements$type, pLevel, pPos, entitytype)) { return false; } else if (!SpawnPlacements.checkSpawnRules(entitytype, pLevel, MobSpawnType.NATURAL, pPos, pLevel.random)) { return false; } else { return pLevel.noCollision(entitytype.getAABB((double)pPos.getX() + 0.5D, (double)pPos.getY(), (double)pPos.getZ() + 0.5D)); } } else { return false; } } The problem is that it checks isSpawnPositionOk before checking checkSpawnRules which is where the event is fired.
  4. I want to make Axotols spawn on water without needing clay. This is my code: @Mod.EventBusSubscriber(modid = "aoemod", bus = Mod.EventBusSubscriber.Bus.FORGE) public class SpawnConditionsEventHandler { @SubscribeEvent public static void spawnConditionChanges(LivingSpawnEvent.CheckSpawn event){ LivingEntity entity=event.getEntityLiving(); if(entity instanceof Axolotl){ BlockPos pos=new BlockPos(event.getX(),event.getY(),event.getZ()); BlockState state=event.getWorld().getBlockState(pos); if(state.is(Blocks.WATER)&&state.getValue(BlockStateProperties.LEVEL)==8){ event.setResult(Event.Result.ALLOW); } } } } I created a breakpoint under the first if statement. If the world doesn't contain any clay, the breakpoint never fires but if there is clay then the event fires. Essentially the problem is that I think I have the wrong event because the event only runs after the vanilla condition of needing clay is met.
  5. I want to an event to prevent damage from Sweet Berries and Cacti. I am working in 1.18.1. This is my EventHandler: @Mod.EventBusSubscriber(modid = "aoemod", bus = Mod.EventBusSubscriber.Bus.FORGE) public class BlockDamageEventHandler { @SubscribeEvent public static void cancelBlockDamage(LivingHurtEvent event){ DamageSource source=event.getSource(); if(source==DamageSource.SWEET_BERRY_BUSH||source==DamageSource.CACTUS){ event.setCanceled(true); } } } The event does prevent entities from taking damage, but has the following problems Entities still get highlighted in red and make their damaged sound when they next to cacti or moving in sweet berries The player's camera still gets moved when moving through sweet berries and the hurt sound is still made The player's is still knocked back when next to a cactus Is there a way I can fix these issues either with additional EventHandlers or changing this EventHandler?
  6. I am interested in hiring someone to update a 1.12.2 mod called Tektopia and a 1.12.2 mod called Craftstudio (which is needed by Tektopia) to 1.17.1. Both Tektopia and CraftStudio are relatively large mods but I am willing to pay at least $800 (you let me know what an appropriate amount would be) for this and I can also perform tasks as long as you make it clear what I need to do (I know Java). The one catch is that for the Tektopia mod you cannot post the mod publicly (I talked to the author and he is ok with me updating the mod and hiring someone as long as I send it to him to upload to curse forge it himself so that he still owns it) so before I send you the source code for Tektopia I need you to promise that you will not share it with anyone else. I have already removed most of the errors that are easier to fix in Tektopia so I will send you the updated project.
  7. I'm sorry for wasting your time I figured out that the reason it wasn't working is because I used to use a different scale of biome scores (with varied between 0 and 2 instead of 0 and 4) which made the crops seem to grow at the same rate. When I scaled the scores by 2 everything worked.
  8. I want my mod to change how quickly crops grow based on the biome. But when I test my mod the crops grow the same regardless of the biome. I have other methods inside of ModClientEvents that do work and when I add a print statement above the state.randomTick line it gives the correct score that the biomes should have when I am within each biome which means that the method is being called when the event occurs, the method calculates the biome scores connectly, and the code inside of the if statement is being run. This makes me think that the problem is with state.randomTick. How I can fix my code to make it so that state.randomTick actually alters the growth age of crops? @Mod.EventBusSubscriber(modid = AOEMod.MOD_ID, bus=Mod.EventBusSubscriber.Bus.FORGE, value= Dist.CLIENT) public class ModClientEvents { public static double[] growth_chances=new double[]{0,0,1.0/3.0,1.0/2.0,2.0/3.0}; @SubscribeEvent public static void onPlantTick(BlockEvent.CropGrowEvent.Pre event) { IWorld world=event.getWorld(); BlockPos pos=event.getPos(); BlockState state=event.getState(); int score=getScore(world,pos,state.getBlock()); if(world.getRandom().nextDouble()<growth_chances[score]){ state.randomTick((ServerWorld) world,pos,world.getRandom());//NOT WORKING!!! } } }
  9. I am interested in registering my own BiomeProviderType which uses my custom BiomeProvider BiomeProviderNew. I am familiar with java reflection and the Function<C,T> generic class and I read this question. The problem that I am having is that in order to get the constructor I need to get the class of BiomeProviderType<OverworldBiomeProviderSettings, OverworldBiomeProvider> (once I get things to work I will replace OverworldBiomeProvider with BiomeProviderNew). I want to say Class<BiomeProviderType<OverworldBiomeProviderSettings, OverworldBiomeProvider>> class=BiomeProviderType<OverworldBiomeProviderSettings, OverworldBiomeProvider>.class; But this is not possible. I read that I could get the class using Types according to the second answer on this link and on this link, but this resulted in the exception sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class. This link talks about the exception but I don't know how to apply it to my case. Similarly, I also need to get the class of Function<OverworldBiomeProviderSettings, OverworldBiomeProvider> and Function<OverworldBiomeProviderSettings, OverworldBiomeProvider> This is my code: This is the stacktrace I got I guess this is more of a java question than a question about forge. Thanks!
  10. I am now making a mod for 1.15 I would like to know when the event comes to forge 1.15. I went to the link Draco18s provided and it seems that there is no project or milestone. I subscribed to that github thread, but I was wondering if anyone has a time estimate for the number of months before it gets added.
  11. I recently started my mod over and I am unable to run minecraft in eclipse with the play or debug buttons (I already ran gradlew genEclipseRuns) I am able to run my mod with gradlew runClient and and everything works until I try to create a world. The world tries to load until it reaches 100% and then stays at 100% without generating the world. This is my log: I might be wrong, but I believe the problem is that my mod is trying to find the website http://myurl.me/ but this website doesn't have the information it is expecting. The only place I could find that URL is in my mods.toml file. This is my .toml I commented out the line updateJSONURL="http://myurl.me/", which is the only place where myurl.me appeared, but when I type gradlew runClient again it is still searching for myurl.me. The problem might also be what is wrong with the forge-client.toml file. This is my forge-clent.toml file: I don't understand why is it saying that I am missing zoomInMissingModelTextInGui and the other fields because they are in the file and my forge-client.toml file looks exactly like Cadiboo's github file for 1.15 and I was able to successfully run his mod from eclipse without any problems. Let me if know if any other information would be helpful in determining what I did wrong and how I could fix it. Thanks, Andrew Murdza
  12. Thanks for replying! I ended up using Minecraft Deobfuscator v3.0 which deobfuscated the majority of the functions.
  13. I figured out how to make the changes I wanted by overriding the vanilla blocks with my own blocks. Even if I unload the mod, the blocks are still there and they function as normal.
  14. I also just realized that the max growth heights for cacti and sugarcane are determined before the onCropsGrowPre is called. So I'm hoping there is a solution for cacti and sugarcane as well.
  15. I found that beetroots, carrots, wheat, potatoes, cacti, sugarcane, chorus flowers, cocoa beans, kelp, nether wart, sweet berries, pumpkin and melon stems when they grow in age, and pumpkin and melon stems when they grow pumpkins and melons all call the ForgeHooks onCropsGrowPre event which is related to the BlockEvent.CropGrowEvent.Pre event. This leaves Bamboo, Mushrooms, Saplings, and Vines. I am especially interested in the mushroom block. The only three methods that are called when deciding when there are too many mushrooms in the area are BlockPos.getAllInBoxMutable, the getBlockState method of ServerWorld, and the getBlock method of BlockState. All of these methods do not seem to lead to any forge events. Is some way to involve events? If not, is there a way I can either work with the ServerWorld or introduce a fake replica of the mushroom block with my tick method that will not cause the mushrooms to disappear if I unload the mod? The code is below: I would like to change the number 25 in the nextInt method and the value of i depending on the biome, with the value of i being most important.
  16. When I run gradlew eclipse I get the source code but the code is still obfuscated. I read that the correct approach to solve this is to use MCPBot. In the website it says that I should replace "mappings channel: 'snapshot', version: '20191219-1.14.3'" with "mappings=stable_60" in the build.gradle file. When I do this and run gradlew build in command prompt, I get the follow stacktrace: The problem is that there is no file at the link https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.15.2-31.1.0_mapped_stable_60/forge-1.15.2-31.1.0_mapped_stable_60.jar. I tried to search that link manually and I got no results. What should I put in build.gradle that will allow MCPBot to deobfuscate the class files?
  17. I am making a mod for 1.15 that alters the growth rate of wheat, cocoa beans, etc. based on the biome they are growing in and affects the max height of cacti and sugarcane depending on the biome and the maximum number of mushrooms that can spread in an area depending on the biome. The brute force way to do it would be to replace mushrooms, crops, etc. with custom blocks, but I want my world to still be playable even if I remove the mod. I've looked at the source code and the method I am interested in is called tick and I am interested specifically when it is called from the following classes: There are many other blocks that use the tick method (such as redstone ore and leaves) that I don't care about. The way I was planning to do this is look for an event that fires whenever the tick method runs and then check if the block in the event is one of the blocks I am interested in. If it is, then I cancel the event and run my own custom tick method that accounts for higher max height, growth rate, and/or maximum mushroom density. The problem that I am having is that I cannot find an event that fires whenever the tick method is called. I expected that the TickEvent would work but it didn't seem to do what I wanted (I want an event to include the world and the position of the block that is trying to grow). If there is a method that works specifically when the tick event fires for all the blocks I listed but not for all blocks in general, then that's even better. I don't want the event to fire only when the plant grows, I want it to fire every time the plant tries to grow. Thanks, Andrew Murdza
  18. Today I downloaded the MDK for Minecraft forge 1.15 to work on a mod, but I am not able to see the source code for Minecraft like I was for previous versions. I'm a novice modder so the source code helped me do things that I would not have been able to do without it. I read another question that was saying that Forge no longer has the right to deobfuscate the code but I also read this quote: "You can use the eclipse task to decompile the sources and then find them in a jar hidden in a cache directory" on this stack overflow question. I also saw in the New LTS System, 1.14 and moving forward that I can use MCPConfig to see the source code. I was wondering if you could tell me 1) if it is possible to view Minecraft source code for 1.15+ and 2) if it is possible, how can I view it using some hidden jar file, MCPConfig, or something else (I don't know what MCPConfig is other than that MCP is mentioned in many of the forge files). I was able to find the .class files corresponding to the .java I was interested in but they weren't helpful. It might also be that I just messed up the process because I used the same steps as the tutorials based on 1.14 and I was able to successfully find the source code for 1.12 and 1.13 in the past. Thanks, Andrew Murdza
  19. Thanks, Draco! This answers my question. I reached out to Tango on his Patreon, but I think it is unlikely that he will provide his source code and I doubt he spent the time to make an API. I guess I will never get to make an addon to his mod. I'll have to wait and see until he responds.
  20. I am hoping to make an addon mod to Tango Tek's Tektopia mod. I have a google document containing all of the things I want to add to the mod, but I don't think it's necessary for you to read through it to answer my question. Essentially I would like to add onto the Tektopia mod and it is more difficult to add onto a mod because, unlike Minecraft, you don't have the source code. I've seen some forum topics about deobfuscating, but I'm not sure that wouldn't apply here because Tango is still actively working on his mod. If it does apply here, then is there a tutorial that you would recommend for deobfuscating a mod .jar file? I was able to decompile the TekTopia jar file, but when I used Minecraft Deobfuscator v3.0 the program outputted an empty zip file If it doesn't apply here, do you have any tips for adding an addon without source code? I'll send specific questions later. Thanks, Andrew Murdza
  21. The log statements in OnBlockBreak all run, while the log statement in the HarvestDropsEvent does not. This means that the if statement is not reached. How could I change the if statement so that it would work? (This is something I would have to deal with after I get the HarvestDropsEvent to fire) Thanks, Andrew Murdza
  22. I'm making a mod for 1.14.4 which affects the drops of blocks depending on the biome at the location where they were harvested. I think that the best way to do this is with the HarvestDropsEvent. The problem is that my HarvestDropEvent method does not get called when I mine a sand block with a diamond shovel in survival on a test world. I could use the OnBlockBreakEvent method (which does get called under the same situation) but I only want the additional drops to be added if the conditions of the harvest drops event are satisfied and the tool is not a silk-touch tool. Note that I have strange code inside of both methods because I first want to make sure I get the onEvent method to fire and then I will replace the inside code with things relevant to my mod. Please tell if there is a way to get the onEvent method to be called when I harvest blocks like wheat, melons, ores, etc. My code is below: Thanks, Andrew Murdza
  23. Thank you very much! I needed to create a JAVA_HOME environment variable and after I did it worked!!
  24. Thanks! I will try to fix that.
×
×
  • Create New...

Important Information

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