-
Posts
3284 -
Joined
-
Last visited
-
Days Won
62
Everything posted by ChampionAsh5357
-
(1.16.1) How to add another texture layer to chestplate
ChampionAsh5357 replied to iSyriux's topic in Modder Support
Wherever you want. I structure files in places for organizational purposes. Put it where you please. I feel as though Novârch said it best: -
[1.15.2] Different game screen and window size
ChampionAsh5357 replied to Mr_Zylr's topic in Modder Support
Um. So you're basically asking for F3 except with no rendering behind it? Why don't you just draw a more opaque box behind the text so you can show the information better. If you could give more context as to why you are trying to accomplish this, it would be helpful. -
(1.16.1) How to add another texture layer to chestplate
ChampionAsh5357 replied to iSyriux's topic in Modder Support
Well assuming its a modded entity, it would be in File -> Export -> Export Java Entity -
".Effect" is StrikeThrough in My food Class - 1.15.2
ChampionAsh5357 replied to thepillager's topic in Modder Support
No. Food specifically has a method for applying effects. Use the supplier version of the it. Do not override a method for an already implemented purpose. -
[1.16] Removing Brewing Recipes From The Registry
ChampionAsh5357 replied to OberonPuck's topic in Modder Support
I agree. Trying to set something as accessible when ObfuscationReflectionHelper::findField already does that for you makes no sense. Also casting an object to another with no relation also is bonkers. Just remove you trying to set accessible. Also, if you want to remove individual vanilla brewing recipes, you will need to access the data in PotionBrewing. -
I want to do a verification check on my two custom providers before I go and write a tutorial on their implementation. The first one is an advancements provider that takes in a FinishedAdvancement (basically an advancement still as a builder and its location. It's almost exactly similar to the Minecraft implementation. public abstract class AdvancementsProvider implements IDataProvider { private static final Logger LOGGER = LogManager.getLogger(); private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); private final DataGenerator generator; public AdvancementsProvider(DataGenerator generatorIn) { this.generator = generatorIn; } @Override public void act(DirectoryCache cache) throws IOException { Path path = this.generator.getOutputFolder(); Set<ResourceLocation> set = Sets.newHashSet(); Consumer<FinishedAdvancement> consumer = (advancementIn) -> { if (!set.add(advancementIn.getId())) { throw new IllegalStateException("Duplicate advancement " + advancementIn.getId()); } else { Path path1 = getPath(path, advancementIn); try { IDataProvider.save(GSON, cache, advancementIn.serialize(), path1); } catch (IOException ioexception) { LOGGER.error("Couldn't save advancement {}", path1, ioexception); } } }; for(Consumer<Consumer<FinishedAdvancement>> consumer1 : this.getAdvancements()) { consumer1.accept(consumer); } } public abstract List<Consumer<Consumer<FinishedAdvancement>>> getAdvancements(); private static Path getPath(Path pathIn, FinishedAdvancement advancementIn) { return pathIn.resolve("data/" + advancementIn.getId().getNamespace() + "/advancements/" + advancementIn.getId().getPath() + ".json"); } @Override public String getName() { return "Advancements"; } } public class FinishedAdvancement { private final ResourceLocation id; private final Advancement.Builder builder; private FinishedAdvancement(ResourceLocation idIn, Advancement.Builder builderIn) { this.id = idIn; this.builder = builderIn; } public JsonObject serialize() { return this.builder.serialize(); } public ResourceLocation getId() { return id; } public static class Builder { private Advancement.Builder builder; private Builder() {} public static FinishedAdvancement.Builder builder() { return new FinishedAdvancement.Builder(); } public FinishedAdvancement.Builder advancement(Advancement.Builder builderIn) { this.builder = builderIn; return this; } public FinishedAdvancement build(Consumer<FinishedAdvancement> consumer, ResourceLocation id) { FinishedAdvancement advancement = new FinishedAdvancement(id, builder); consumer.accept(advancement); return advancement; } } } The second one is a basic provider for a sounds.json file. The only parameter it doesn't take into account is its type since that is automatically set for its usage. public abstract class SoundsProvider implements IDataProvider { private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create(); private final DataGenerator gen; private final String modid; public SoundsProvider(DataGenerator gen, String modid) { this.gen = gen; this.modid = modid; } protected abstract void addSounds(Consumer<SoundBuilder> consumer); @Override public void act(DirectoryCache cache) throws IOException { JsonObject object = new JsonObject(); addSounds(builder -> builder.serialize(object)); IDataProvider.save(GSON, cache, object, this.gen.getOutputFolder().resolve("assets/" + modid + "/sounds.json")); } @Override public String getName() { return "Sounds"; } } public class SoundBuilder { private ResourceLocation name; private boolean replace; @Nullable private String subtitleTranslationKey; private final List<SoundExtension> sounds = new ArrayList<>(); private SoundBuilder(ResourceLocation location) { this.name = location; } public static SoundBuilder builder(SoundEvent sound) { return builder(sound.getRegistryName()); } public static SoundBuilder builder(Supplier<? extends SoundEvent> soundSupplier) { return builder(soundSupplier.get()); } public static SoundBuilder builder(ResourceLocation location) { return new SoundBuilder(location); } public SoundBuilder replace() { this.replace = true; return this; } public SoundBuilder subtitle() { return subtitle("subtitle." + name.getNamespace() + "." + name.getPath()); } public SoundBuilder subtitle(String translationKey) { this.subtitleTranslationKey = translationKey; return this; } private SoundBuilder defaultSound() { return sound(this.name); } public SoundBuilder sound(ResourceLocation name) { this.sounds.add(new SoundExtension(name)); return this; } public SoundBuilder sound(SoundExtension soundIn) { this.sounds.add(soundIn); return this; } public void build(Consumer<SoundBuilder> consumer) { this.validate(); consumer.accept(this); } private void validate() { if(this.sounds.isEmpty()) { this.defaultSound(); } this.sounds.forEach(SoundExtension::validate); } public void serialize(JsonObject parentObject) { JsonObject object = new JsonObject(); object.addProperty("replace", this.replace); if(subtitleTranslationKey != null) { object.addProperty("subtitle", this.subtitleTranslationKey); } JsonArray array = new JsonArray(); this.sounds.forEach(sound -> array.add(sound.serialize())); object.add("sounds", array); parentObject.add(this.name.getPath(), object); } public static class SoundExtension { private final String name; private float volume = 1.0f, pitch = 1.0f; private int weight = 1, attenuation_distance = 16; private boolean stream, preload; private SoundExtension(ResourceLocation name) { this.name = name.toString().replaceAll("[.]", "/"); } public static SoundExtension builder(ResourceLocation name) { return new SoundExtension(name); } public SoundExtension volume(float volumeIn) { this.volume = volumeIn; return this; } public SoundExtension pitch(float pitchIn) { this.pitch = pitchIn; return this; } public SoundExtension weight(int weightIn) { this.weight = weightIn; return this; } public SoundExtension stream() { this.stream = true; return this; } public SoundExtension attenuationDistance(int attenuationDistanceIn) { this.attenuation_distance = attenuationDistanceIn; return this; } public SoundExtension preload() { this.preload = true; return this; } private void validate() { if(this.volume != MathHelper.clamp(this.volume, 0, 1.0)) { throw new IllegalArgumentException("Sound " + name + " has a volume not between 0 and 1."); } else if(this.pitch != MathHelper.clamp(this.pitch, 0, 2.0)) { throw new IllegalArgumentException("Sound " + name + " has a pitch not between 0 and 2."); } else if(this.weight <= 0) { throw new IllegalArgumentException("Sound " + name + " has a negative or zero weight."); } else if(this.attenuation_distance <= 0) { throw new IllegalArgumentException("Sound " + name + " has a negative or zero attenuation distance."); } } private JsonObject serialize() { JsonObject object = new JsonObject(); object.addProperty("name", this.name); object.addProperty("volume", this.volume); object.addProperty("pitch", this.pitch); object.addProperty("weight", this.weight); object.addProperty("weight", this.weight); object.addProperty("stream", this.stream); object.addProperty("attenuation_distance", this.attenuation_distance); object.addProperty("preload", this.preload); return object; } } } Please let me know if there is anything I can do to improve the quality of this code.
-
Gravity is a myth for the basic Entity class. Give it some velocity and it'll start moving in the direction you want. Probably should use Entity::setMotion and some Vector3d::add. You also might want to override the tick method.
-
(1.16.1) How to add another texture layer to chestplate
ChampionAsh5357 replied to iSyriux's topic in Modder Support
You've already asked that in a different post and I already gave you a reference in that one. -
(1.16.1) How to add another texture layer to chestplate
ChampionAsh5357 replied to iSyriux's topic in Modder Support
There is an overlay layer however that is used specifically for dyeable armor. You'll probably have to create a custom armor model. -
Custom Potion Recipes Return Noncraftable Potions
ChampionAsh5357 replied to OberonPuck's topic in Modder Support
Brewing recipes are hooked in via BrewingRecipeRegistry::addRecipe. Also, are you seriously calling the brewing recipes in your constructor before the potions are even registered? This should be done within FMLCommonSetupEvent surrounded by a DeferredWorkQueue. -
(1.15.2-1.16.1) How to update mod from 1.15 to 1.16
ChampionAsh5357 replied to iSyriux's topic in Modder Support
Ahem. I absolutely hate having to watch a youtube video to find out a mistake. And I mean wow. Its the mistake I guessed it would be. You should probably check out the mods.toml and correctly update it to the loader version and dependencies inside. Next time just give us your code. -
Yes, calling the method to add particles on the server would be pointless as the method does nothing. So it should be checked and called on the client.
-
You should really read the source information provided with it. Pass in a TileEntityType and a Function that takes in a dispatcher and returns a TER (double colon operators are helpful). You can call it within FMLClientSetupEvent. If it doesn't work, then you probably haven't specified any blocks that can use your tileentity in the builder.
-
You would need to call a event that is handled in Minecraft's constructor. Do note that forge's event bus doesn't start until mod loading is completed meaning that it has to be called from somewhere on the mod event bus. The Lifecycle Events for creating and loading registries would work, but then we have to deal with it being fired specifically for the client. The easiest event to use is actually ParticleFactoryRegisterEvent. Do remember this is on your mod's event bus and only on the client side.
-
https://mcforge.readthedocs.io/en/latest/blocks/interaction/#onblockactivated
- 1 reply
-
- 1
-
-
WorldSavedData in the docs is ridiculously outdated due to a lack of information and just pure complexity. As for capabilities, I'm not sure if they fixed world capabilities yet due to the rework of the world and dimension system.
-
Ok, just wanted to make sure.
-
Currently, the way to implement a custom spawner is to tick a custom spawning class via WorldTickEvent on the logical server. Minecraft has 5 spawners that are marked as 'special' meaning they extend ISpecialSpawner. These are first passed into an immutable list within MinecraftServer::func_240787_a_ and then stored as a variable within server world to be called when a chunk is ticked. I suggest a new hook that takes in a list of these 5 existing spawners along with a parameter for IServerWorldInfo. This could then be past into a new event which allows the user to add a spawner. As an option, a user might also be able to remove the other 'special' spawners as well to replace with their own. Afterwards, the hook would return an immutable list containing the special spawners. The event should not be cancelable and should not have a result. It would also be fired on the MinecraftForge::EVENT_BUS. This hook would only be called once during the initialization of the logical server as opposed to being called every tick as an alternative. If this seems like a valid event to be implemented, I will get started on creating a PR for 1.16.
-
As prior amateur, I can attest to this. Currently, I am trying to improve my skills and knowledge by being active on these forms and verifying all of what I want to say. I believe the only tutorials currently recommended are those by McJty. If you need help on a problem that you cannot deconstruct by yourself, you should always turn to the forms or the forge discord.
-
minecraft 1.15 numbre of collision boxes
ChampionAsh5357 replied to blinky000's topic in Modder Support
It's not necessarily how many collision boxes there are, its more of how complex the shape is. The most complex shape a collision box could have 2048 boxes. These would not intersect and create new boxes. This many boxes would probably drop the speed yes, but more in specific circumstances. The collision boxes mostly matter when constructing and destroying the block. This is when the collision boxes get updated so breaking many in succession quickly would cause lag. However, a bunch of them existing in the world wouldn't really cause a slow down. As a person who's generated complex collision boxes in large quantities, here is my take on collision boxes. You want to try and reduce the complexity as much as possible. Also, they should be initialized only once using a variable so that the calculations aren't done every time the block is created/destroyed. You can have as many generate as you want. Just realize that you have to balance the complexity of your shape with the efficiency of harvesting and placement in the world.