Andrew Murdza
Members-
Posts
35 -
Joined
-
Last visited
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
Andrew Murdza's Achievements
Tree Puncher (2/8)
0
Reputation
-
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.
-
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
-
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.
-
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.
-
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?
-
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.
-
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!!! } } }
-
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!
-
HarvestDropsEvent not working as expected.
Andrew Murdza replied to Andrew Murdza's topic in Modder Support
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. -
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
-
Thanks for replying! I ended up using Minecraft Deobfuscator v3.0 which deobfuscated the majority of the functions.
-
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.
-
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.