Skip to content

Instantly share code, notes, and snippets.

View TelepathicGrunt's full-sized avatar
🦎
Just chilling around!

TelepathicGrunt TelepathicGrunt

🦎
Just chilling around!
View GitHub Profile
public static List<BlockPos> matchingBlocksOfKindInRange(Level level, BlockPos centerPos, int radius, Predicate<BlockState> predicate) {
List<BlockPos> validPos = new ObjectArrayList<>();
// Figure out how many chunk radius we need to search outward to encompass the radius properly
ChunkPos maxChunkPos = new ChunkPos(
SectionPos.blockToSectionCoord(centerPos.getX() + radius),
SectionPos.blockToSectionCoord(centerPos.getZ() + radius)
);
ChunkPos minChunkPos = new ChunkPos(
@TelepathicGrunt
TelepathicGrunt / NetowrkingComparison.md
Last active October 10, 2023 01:12
Forge 1.19.2 networking vs Fabric 1.19.2 networking

Forge

Packet class

public record CrystallineFlowerEnchantmentPacket(int containerId, List<EnchantmentSkeleton> enchantmentSkeletons) {
    public static Gson gson = new GsonBuilder().create();

    public static void sendToClient(ServerPlayer entity, int containerId, List<EnchantmentSkeleton> enchantmentSkeletons) {
        MessageHandler.DEFAULT_CHANNEL.send(PacketDistributor.PLAYER.with(() -> entity),

Biome Tags are awesome!

As a result of 1.18.2 changes, all worldgen registries can now have tags. Including biomes! As a result of this, Mojang has deprecated the biome category which means that sooner or later, this enum will be deleted. To better protect yourself and your mod/datapack from relying on these categories, you should instead, switch to using biome tags.

The existing biome tags from vanilla do not cover all usecases which means that many modders have started banding together to decide on common biome tags to use. These common biome tags are under the forge: namespace and the c: namespace.

For best compatibility with any mod or datapack, you should have a custom tag that pulls entries from minecraft:, forge:, and c: tags. Yes, datapacks too should be adding their biomes to the forge: and c: namespaced tags. And mods can "datagen" the tag json files automatically but that is outside the scope of this gist. See the Fabric wiki or [Forge Comm

// FORGE
@Mod(Test.MODID)
public class Test {
public static final String MODID = "test";
// A Feature + Config to say how the feature should generate.
public static ConfiguredFeature<?, ?> CUSTOM_ORE_CF;
// A ConfiguredFeature + 0 or more Placement Modifiers that tells the
// ConfiguredFeature where and how often it should generate in chunks.
public static PlacedFeature CUSTOM_ORE_PF;
@TelepathicGrunt
TelepathicGrunt / addNewBuildingsVillages.java
Last active March 15, 2023 10:57
How to add new buildings to villages and other jigsaw structures
// This gist code is public domain. Take it! Steal it! AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!!!!!!!!!!!
// 1.18.2 code at top. 1.16.5 version farther down
private static final ResourceKey<StructureProcessorList> EMPTY_PROCESSOR_LIST_KEY = ResourceKey.create(
Registry.PROCESSOR_LIST_REGISTRY, new ResourceLocation("minecraft", "empty"));
public ExampleMod() {
MinecraftForge.EVENT_BUS.addListener(this::addNewVillageBuilding);
}

Forge PRs can be quite tricky to understand and get working but if you can get your new event or hook or fix into Forge, you benefit a ton of modders! Don't let the idea of a Forge PR scare you or seem too daunting! Just follow this gist and hopefully you'll get the hang of it!


The first step is check out gigaherz's gist for creating a PR:
https://gist.github.com/gigaherz/ca256fea517cb925dfc31d7cd48c487e


Forge's doc on making PRs with extra into and styling rules:
https://github.com/MinecraftForge/MinecraftForge/wiki/If-you-want-to-contribute-to-Forge

@TelepathicGrunt
TelepathicGrunt / outerclassinstance.md
Last active June 10, 2021 14:05
How-to-get outer class instance from inner class with mixin

When you mixin into a non-static inner class, the inner class has a hidden field that stores the instance of the outer class. It is a bit tricky to get it but it can be done.

Forge:

Step one, go to the Forge jar and find the class in question. Open it in Intellij

https://i.imgur.com/Dnrv3Kv.png

https://i.imgur.com/F1bPHRG.png

@TelepathicGrunt
TelepathicGrunt / addModdedCropsToVillageFarms.java
Last active January 4, 2024 18:31
how to add to village farms in a mod/datapack compatible way that can stack without overwriting each other.
// This gist code is public domain. Take it! Steal it! AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!!!!!!!!!!!
// 1.18.2+
public ExampleMod() {
MinecraftForge.EVENT_BUS.addListener(this::addNewVillageCrop);
}
public void addNewVillageCrop(final ServerAboutToStartEvent event) {
// Dynamic registry of processor lists. We will edit the processor lists from here as this is what the world will actually use.
Registry<StructureProcessorList> processorListRegistry = event.getServer().registryAccess().registry(Registry.PROCESSOR_LIST_REGISTRY).orElseThrow();

What are mixins?

Mixins are a way to inject code or change the minecraft source code directly and should be use with caution. If you can do a PR to Forge or use an event, try those first. If all else fails, then mixins may be a good option to look into. Here are some resources for mixins:

Now, I'll be honest, the official mixin doc is kind of terrible to learn from for most people. It's extremely dense and and really only helps people who already knows in-depth bytecode and stuff. But most modders aren't like that and just wants to do small stuff lol. But I'll give you the run-down here. There's a few kinds of mixins that you will encounter quite often.

Gson gson = new GsonBuilder().setPrettyPrinting().create();
// Will print the stuff into the runs/config folder
try {
for(Map.Entry<RegistryKey<StructureProcessorList>, StructureProcessorList> processorListEntry : BuiltinRegistries.STRUCTURE_PROCESSOR_LIST.getEntries()){
if(!processorListEntry.getKey().getValue().getNamespace().equals(RepurposedStructures.MODID)) continue;
for(StructureProcessor processorEntry : processorListEntry.getValue().getList()) {
String filePath = FabricLoader.getInstance().getConfigDir()+"\\processor_list\\"+processorListEntry.getKey().getValue().getPath()+".json";