diff --git a/src/client/java/dev/tggamesyt/szar/client/NiggerEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/NiggerEntityRenderer.java new file mode 100644 index 0000000..882dd78 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/NiggerEntityRenderer.java @@ -0,0 +1,26 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.NiggerEntity; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.render.entity.MobEntityRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.util.Identifier; + +public class NiggerEntityRenderer + extends MobEntityRenderer> { + + public NiggerEntityRenderer(EntityRendererFactory.Context context) { + super( + context, + new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER)), + 0.5F + ); + } + + @Override + public Identifier getTexture(NiggerEntity entity) { + return new Identifier("szar", "textures/entity/nigg.png"); + } +} + diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index 0818dac..ac92f7e 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -1,10 +1,40 @@ package dev.tggamesyt.szar.client; +import dev.tggamesyt.szar.NiggerEntity; +import dev.tggamesyt.szar.Szar; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.item.ItemStack; public class SzarClient implements ClientModInitializer { @Override public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver( + Szar.NWORDPACKET, + (client, handler, buf, responseSender) -> { + + ItemStack stack = buf.readItemStack(); + + client.execute(() -> { + MinecraftClient.getInstance() + .gameRenderer.showFloatingItem(stack); + }); + } + ); + //EntityRendererRegistry.register( + // Szar.NI, + // NiggerEntityRenderer::new + //); + + //EntityModelLayerRegistry.registerModelLayer( + // EntityModelLayers.PLAYER, + // BipedEntityModel::getTexturedModelData + //); } } diff --git a/src/main/java/dev/tggamesyt/szar/NiggerEntity.java b/src/main/java/dev/tggamesyt/szar/NiggerEntity.java new file mode 100644 index 0000000..016eb59 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/NiggerEntity.java @@ -0,0 +1,36 @@ +package dev.tggamesyt.szar; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.ai.goal.LookAroundGoal; +import net.minecraft.entity.ai.goal.WanderAroundFarGoal; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.mob.PathAwareEntity; +import net.minecraft.item.Item; +import net.minecraft.world.World; + +public class NiggerEntity extends PathAwareEntity { + + public NiggerEntity(EntityType type, World world) { + super(type, world); + } + + @Override + protected void initGoals() { + this.goalSelector.add(1, new WanderAroundFarGoal(this, 1.0D)); + this.goalSelector.add(2, new LookAroundGoal(this)); + } + + public static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25); + } + + @Override + protected void dropLoot(DamageSource source, boolean causedByPlayer) { + this.dropItem(new NwordPassItem(new Item.Settings())); + } +} diff --git a/src/main/java/dev/tggamesyt/szar/NwordPassItem.java b/src/main/java/dev/tggamesyt/szar/NwordPassItem.java new file mode 100644 index 0000000..efbd962 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/NwordPassItem.java @@ -0,0 +1,68 @@ +package dev.tggamesyt.szar; + +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.AdvancementProgress; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.ServerAdvancementLoader; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; +import net.minecraft.util.TypedActionResult; +import net.minecraft.world.World; + +public class NwordPassItem extends Item { + + public NwordPassItem(Item.Settings settings) { + super(settings); + } + + @Override + public TypedActionResult use(World world, PlayerEntity user, Hand hand) { + ItemStack stack = user.getStackInHand(hand); + + if (!world.isClient) { + // Play totem animation + if (user instanceof ServerPlayerEntity serverPlayer) { + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeItemStack(stack); + + ServerPlayNetworking.send(serverPlayer, Szar.NWORDPACKET, buf); + } + //world.sendEntityStatus(user, (byte) 35); + + // Grant advancement + if (user instanceof ServerPlayerEntity serverPlayer) { + grantAdvancement(serverPlayer); + } + + // Consume item + stack.decrement(1); + } + + return TypedActionResult.success(stack, world.isClient); + } + + private void grantAdvancement(ServerPlayerEntity player) { + ServerAdvancementLoader loader = + player.getServer().getAdvancementLoader(); + + Advancement advancement = + loader.get(new Identifier("szar", "nwordpass")); + + if (advancement == null) return; + + AdvancementProgress progress = + player.getAdvancementTracker().getProgress(advancement); + + if (!progress.isDone()) { + for (String criterion : progress.getUnobtainedCriteria()) { + player.getAdvancementTracker().grantCriterion(advancement, criterion); + } + } + } +} diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 814591b..06baf4f 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -1,14 +1,28 @@ package dev.tggamesyt.szar; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; +import net.minecraft.advancement.Advancement; import net.minecraft.block.Block; import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Pattern; + public class Szar implements ModInitializer { public static final String MOD_ID = "szar"; @@ -17,6 +31,8 @@ public class Szar implements ModInitializer { new SzarBlock(); public static final Block FASZ_BLOCK = new FaszBlock(); + public static final Identifier NWORDPACKET = + new Identifier("szar", "nwordpacket"); @Override public void onInitialize() { @@ -47,5 +63,87 @@ public class Szar implements ModInitializer { new Identifier(MOD_ID, "fasz"), new FaszItem(FASZ_BLOCK, new Item.Settings()) ); + Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "nwordpass"), + new NwordPassItem(new Item.Settings()) + ); + + ServerMessageDecoratorEvent.EVENT.register((player, message) -> CompletableFuture.completedFuture( + filterMessage(player, message) + )); + + final EntityType NiggerEntityType = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier("yourmodid", "wandering_npc"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, NiggerEntity::new) + .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized + .build() + ); + FabricDefaultAttributeRegistry.register( + NiggerEntityType, + NiggerEntity.createAttributes() + ); } + + private static final List FORBIDDEN_WORDS = List.of( + "nigger", + "niger", + "niga" + ); + private static Text filterMessage(ServerPlayerEntity player, Text original) { + + // If player has the advancement, do nothing + if (hasAdvancement(player)) { + return original; + } + + String filtered = original.getString(); + + boolean censoredAnything = false; + + for (String word : FORBIDDEN_WORDS) { + + Pattern pattern = Pattern.compile( + "(?i)\\b" + Pattern.quote(word) + "\\b" + ); + + if (pattern.matcher(filtered).find()) { + filtered = pattern.matcher(filtered) + .replaceAll("******"); + censoredAnything = true; + } + } + + // Send warning once per message + if (censoredAnything) { + player.sendMessage( + Text.literal("Nincs N-Word Pass-ed!") + .formatted(Formatting.RED), + false + ); + } + + return Text.literal(filtered); + } + + + private static boolean hasAdvancement(ServerPlayerEntity player) { + + Advancement advancement = player + .getServer() + .getAdvancementLoader() + .get(new Identifier("szar", "nwordpass")); + + if (advancement == null) return false; + + return player + .getAdvancementTracker() + .getProgress(advancement) + .isDone(); + } + + } diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index 2002bfd..7aaec14 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -1,4 +1,5 @@ { "block.szar.cigany": "Cigány Block", - "block.szar.fasz": "Fasz" + "block.szar.fasz": "Fasz", + "item.szar.nwordpass": "N-Word Pass" } \ No newline at end of file diff --git a/src/main/resources/assets/szar/models/item/nwordpass.json b/src/main/resources/assets/szar/models/item/nwordpass.json new file mode 100644 index 0000000..9b961ca --- /dev/null +++ b/src/main/resources/assets/szar/models/item/nwordpass.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "szar:item/nwordpass" + } +} diff --git a/src/main/resources/assets/szar/textures/item/nwordpass.png b/src/main/resources/assets/szar/textures/item/nwordpass.png new file mode 100644 index 0000000..89a8c03 Binary files /dev/null and b/src/main/resources/assets/szar/textures/item/nwordpass.png differ diff --git a/src/main/resources/assets/szar/textures/textures/entity/nigg.png b/src/main/resources/assets/szar/textures/textures/entity/nigg.png new file mode 100644 index 0000000..69b2b40 Binary files /dev/null and b/src/main/resources/assets/szar/textures/textures/entity/nigg.png differ diff --git a/src/main/resources/data/szar/advancements/nwordpass.json b/src/main/resources/data/szar/advancements/nwordpass.json new file mode 100644 index 0000000..85de080 --- /dev/null +++ b/src/main/resources/data/szar/advancements/nwordpass.json @@ -0,0 +1,15 @@ +{ + "display": { + "icon": { + "item": "szar:nwordpass" + }, + "title": "Nig-", + "description": "Get an N-word pass", + "show_toast": true + }, + "criteria": { + "used_item": { + "trigger": "minecraft:impossible" + } + } +} \ No newline at end of file