This commit is contained in:
2026-01-20 09:36:59 +01:00
parent 44c5f0b839
commit 83870fc397
39 changed files with 538 additions and 3 deletions

View File

@@ -0,0 +1,26 @@
package dev.tggamesyt.szar.client;
import dev.tggamesyt.szar.GypsyEntity;
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 GypsyEntityRenderer
extends MobEntityRenderer<GypsyEntity, BipedEntityModel<GypsyEntity>> {
public GypsyEntityRenderer(EntityRendererFactory.Context context) {
super(
context,
new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER)),
0.5F
);
}
@Override
public Identifier getTexture(GypsyEntity entity) {
return new Identifier("szar", "textures/entity/gypsy.png");
}
}

View File

@@ -43,6 +43,11 @@ public class SzarClient implements ClientModInitializer {
Szar.NiggerEntityType, Szar.NiggerEntityType,
NiggerEntityRenderer::new NiggerEntityRenderer::new
); );
EntityRendererRegistry.register(
Szar.GYPSY_ENTITY_TYPE,
GypsyEntityRenderer::new
);
BlockRenderLayerMap.INSTANCE.putBlock( BlockRenderLayerMap.INSTANCE.putBlock(
Szar.CANNABIS_BLOCK, Szar.CANNABIS_BLOCK,
RenderLayer.getCutout() RenderLayer.getCutout()

View File

@@ -0,0 +1,217 @@
package dev.tggamesyt.szar;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ai.goal.Goal;
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.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import java.util.EnumSet;
import java.util.List;
public class GypsyEntity extends PathAwareEntity {
private final DefaultedList<ItemStack> stolenItems = DefaultedList.of();
private int stealCooldown = 0;
private boolean fleeing = false;
private static final double FLEE_DISTANCE = 15.0;
public GypsyEntity(EntityType<? extends PathAwareEntity> type, World world) {
super(type, world);
}
// ================= ATTRIBUTES =================
public static DefaultAttributeContainer.Builder createAttributes() {
return MobEntity.createMobAttributes()
.add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0)
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25);
}
// ================= GOALS =================
@Override
protected void initGoals() {
this.goalSelector.add(0, new FleeWhenSeenGoal(this));
this.goalSelector.add(1, new SneakBehindPlayerGoal(this));
this.goalSelector.add(2, new WanderAroundFarGoal(this, 0.8));
this.goalSelector.add(3, new LookAroundGoal(this));
}
// ================= TICK =================
@Override
public void tick() {
super.tick();
if (stealCooldown > 0) {
stealCooldown--;
}
}
// ================= VISIBILITY CHECK =================
/**
* True if the entity is anywhere on the player's screen (FOV-based)
*/
private boolean isOnPlayerScreen(PlayerEntity player) {
if (player.isCreative()) return false;
Vec3d look = player.getRotationVec(1.0F).normalize();
Vec3d toEntity = this.getPos().subtract(player.getEyePos()).normalize();
// Rough FOV check (~120° total)
return look.dotProduct(toEntity) > 0.3;
}
// ================= STEALING =================
private void trySteal(PlayerEntity player) {
if (stealCooldown > 0 || player.isCreative() || this.getWorld().isClient) return;
List<ItemStack> nonEmpty = player.getInventory().main.stream()
.filter(stack -> !stack.isEmpty())
.toList();
if (nonEmpty.isEmpty()) return;
ItemStack chosen = nonEmpty.get(this.random.nextInt(nonEmpty.size()));
ItemStack stolen = chosen.split(1);
stolenItems.add(stolen);
stealCooldown = 20 * 20; // 20 seconds
fleeing = true;
this.getNavigation().stop();
}
// ================= DAMAGE & LOOT =================
@Override
public boolean damage(DamageSource source, float amount) {
boolean result = super.damage(source, amount);
if (!this.getWorld().isClient && !stolenItems.isEmpty()) {
this.dropStack(stolenItems.remove(0));
}
return result;
}
@Override
protected void dropLoot(DamageSource source, boolean causedByPlayer) {
for (ItemStack stack : stolenItems) {
this.dropStack(stack);
}
stolenItems.clear();
}
// ================= GOALS =================
/**
* Runs away when visible OR after stealing,
* stops once far enough away.
*/
private static class FleeWhenSeenGoal extends Goal {
private final GypsyEntity GypsyEntity;
private PlayerEntity target;
public FleeWhenSeenGoal(GypsyEntity GypsyEntity) {
this.GypsyEntity = GypsyEntity;
this.setControls(EnumSet.of(Control.MOVE));
}
@Override
public boolean canStart() {
this.target = GypsyEntity.getWorld().getClosestPlayer(GypsyEntity, 20);
if (target == null || target.isCreative()) return false;
if (GypsyEntity.fleeing) return true;
return GypsyEntity.isOnPlayerScreen(target);
}
@Override
public boolean shouldContinue() {
return GypsyEntity.fleeing
&& target != null
&& GypsyEntity.squaredDistanceTo(target) < FLEE_DISTANCE * FLEE_DISTANCE;
}
@Override
public void start() {
GypsyEntity.fleeing = true;
moveAway();
}
@Override
public void tick() {
moveAway();
if (GypsyEntity.squaredDistanceTo(target) >= FLEE_DISTANCE * FLEE_DISTANCE) {
GypsyEntity.fleeing = false;
}
}
private void moveAway() {
Vec3d away = GypsyEntity.getPos()
.subtract(target.getPos())
.normalize()
.multiply(10);
Vec3d dest = GypsyEntity.getPos().add(away);
GypsyEntity.getNavigation().startMovingTo(dest.x, dest.y, dest.z, 1.35);
}
}
/**
* Sneaks behind players ONLY when unseen and not fleeing
*/
private static class SneakBehindPlayerGoal extends Goal {
private final GypsyEntity GypsyEntity;
private PlayerEntity target;
public SneakBehindPlayerGoal(GypsyEntity GypsyEntity) {
this.GypsyEntity = GypsyEntity;
this.setControls(EnumSet.of(Control.MOVE));
}
@Override
public boolean canStart() {
this.target = GypsyEntity.getWorld().getClosestPlayer(GypsyEntity, 12);
return target != null
&& !target.isCreative()
&& !GypsyEntity.isOnPlayerScreen(target)
&& GypsyEntity.stealCooldown == 0
&& !GypsyEntity.fleeing;
}
@Override
public void tick() {
Vec3d behind = target.getPos()
.subtract(target.getRotationVec(1.0F).normalize().multiply(2));
GypsyEntity.getNavigation().startMovingTo(
behind.x, behind.y, behind.z, 1.0
);
if (GypsyEntity.distanceTo(target) < 1.5) {
GypsyEntity.trySteal(target);
}
}
}
}

View File

@@ -32,6 +32,6 @@ public class NiggerEntity extends PathAwareEntity {
@Override @Override
protected void dropLoot(DamageSource source, boolean causedByPlayer) { protected void dropLoot(DamageSource source, boolean causedByPlayer) {
this.dropItem(Szar.NWORD_PASS); this.dropItem(Szar.NIGGERITE_INGOT);
} }
} }

View File

@@ -5,6 +5,9 @@ import net.minecraft.item.ArmorMaterial;
import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.Ingredient;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier;
import static dev.tggamesyt.szar.Szar.MOD_ID;
public class NiggeriteArmorMaterial implements ArmorMaterial { public class NiggeriteArmorMaterial implements ArmorMaterial {
@@ -40,7 +43,7 @@ public class NiggeriteArmorMaterial implements ArmorMaterial {
@Override @Override
public String getName() { public String getName() {
return "mythril"; return MOD_ID + ":niggerite";
} }
@Override @Override

View File

@@ -9,6 +9,7 @@ import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
import net.minecraft.advancement.Advancement; import net.minecraft.advancement.Advancement;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.TallPlantBlock; import net.minecraft.block.TallPlantBlock;
@@ -34,6 +35,8 @@ public class Szar implements ModInitializer {
public static final Block SZAR_BLOCK = public static final Block SZAR_BLOCK =
new SzarBlock(); new SzarBlock();
public static final Block NIGGERITEBLOCK =
new Block(AbstractBlock.Settings.copy(Blocks.NETHERITE_BLOCK));
public static final Block FASZ_BLOCK = public static final Block FASZ_BLOCK =
new FaszBlock(); new FaszBlock();
public static final Identifier NWORDPACKET = public static final Identifier NWORDPACKET =
@@ -49,6 +52,7 @@ public class Szar implements ModInitializer {
entries.add(Szar.FASZITEM); entries.add(Szar.FASZITEM);
entries.add(Szar.NWORD_PASS); entries.add(Szar.NWORD_PASS);
entries.add(Szar.NIGGER_SPAWNEGG); entries.add(Szar.NIGGER_SPAWNEGG);
entries.add(Szar.GYPSY_SPAWNEGG);
entries.add(Szar.CANNABIS_ITEM); entries.add(Szar.CANNABIS_ITEM);
entries.add(Szar.WEED_ITEM); entries.add(Szar.WEED_ITEM);
entries.add(Szar.WEED_JOINT_ITEM); entries.add(Szar.WEED_JOINT_ITEM);
@@ -62,6 +66,7 @@ public class Szar implements ModInitializer {
entries.add(Szar.NIGGERITE_CHESTPLATE); entries.add(Szar.NIGGERITE_CHESTPLATE);
entries.add(Szar.NIGGERITE_LEGGINGS); entries.add(Szar.NIGGERITE_LEGGINGS);
entries.add(Szar.NIGGERITE_BOOTS); entries.add(Szar.NIGGERITE_BOOTS);
entries.add(Szar.NIGGERITE_BLOCK);
}) })
.build() .build()
); );
@@ -74,6 +79,11 @@ public class Szar implements ModInitializer {
new Identifier(MOD_ID, "cigany"), new Identifier(MOD_ID, "cigany"),
SZAR_BLOCK SZAR_BLOCK
); );
Registry.register(
Registries.BLOCK,
new Identifier(MOD_ID, "niggerite_block"),
NIGGERITEBLOCK
);
Registry.register( Registry.register(
@@ -90,6 +100,10 @@ public class Szar implements ModInitializer {
NiggerEntityType, NiggerEntityType,
NiggerEntity.createAttributes() NiggerEntity.createAttributes()
); );
FabricDefaultAttributeRegistry.register(
GYPSY_ENTITY_TYPE,
GypsyEntity.createAttributes()
);
} }
public static final StatusEffect DROG_EFFECT = Registry.register( public static final StatusEffect DROG_EFFECT = Registry.register(
Registries.STATUS_EFFECT, Registries.STATUS_EFFECT,
@@ -217,6 +231,11 @@ public class Szar implements ModInitializer {
new Identifier(MOD_ID, "cigany"), new Identifier(MOD_ID, "cigany"),
new BlockItem(SZAR_BLOCK, new Item.Settings()) new BlockItem(SZAR_BLOCK, new Item.Settings())
); );
public static final Item NIGGERITE_BLOCK = Registry.register(
Registries.ITEM,
new Identifier(MOD_ID, "niggerite_block"),
new BlockItem(NIGGERITEBLOCK, new Item.Settings())
);
public static final Item FASZITEM = Registry.register( public static final Item FASZITEM = Registry.register(
Registries.ITEM, Registries.ITEM,
new Identifier(MOD_ID, "fasz"), new Identifier(MOD_ID, "fasz"),
@@ -236,6 +255,15 @@ public class Szar implements ModInitializer {
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
.build() .build()
); );
public static final EntityType<GypsyEntity> GYPSY_ENTITY_TYPE =
Registry.register(
Registries.ENTITY_TYPE,
new Identifier(MOD_ID, "gypsy"),
FabricEntityTypeBuilder
.create(SpawnGroup.CREATURE, GypsyEntity::new)
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
.build()
);
public static final Item NIGGER_SPAWNEGG = Registry.register( public static final Item NIGGER_SPAWNEGG = Registry.register(
Registries.ITEM, Registries.ITEM,
new Identifier(MOD_ID, "nigger_spawn_egg"), new Identifier(MOD_ID, "nigger_spawn_egg"),
@@ -246,6 +274,16 @@ public class Szar implements ModInitializer {
new Item.Settings() new Item.Settings()
) )
); );
public static final Item GYPSY_SPAWNEGG = Registry.register(
Registries.ITEM,
new Identifier(MOD_ID, "gypsy_spawn_egg"),
new SpawnEggItem(
GYPSY_ENTITY_TYPE,
0x964B00,
0xF1C27D,
new Item.Settings()
)
);
private static final List<String> FORBIDDEN_WORDS = List.of( private static final List<String> FORBIDDEN_WORDS = List.of(
"nigger", "nigger",

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "szar:block/niggerite_block"
}
}
}

View File

@@ -4,9 +4,21 @@
"item.szar.nwordpass": "N-Word Pass", "item.szar.nwordpass": "N-Word Pass",
"entity.szar.nigger": "Nigger", "entity.szar.nigger": "Nigger",
"item.szar.nigger_spawn_egg":"Nigger Spawn Egg", "item.szar.nigger_spawn_egg":"Nigger Spawn Egg",
"item.szar.gypsy_spawn_egg":"Gypsy Spawn Egg",
"itemgroup.szar_group": "Szar", "itemgroup.szar_group": "Szar",
"block.szar.cannabis": "Cannabis", "block.szar.cannabis": "Cannabis",
"item.szar.weed": "Weed", "item.szar.weed": "Weed",
"effect.szar.drog": "Drog", "effect.szar.drog": "Drog",
"item.szar.weed_joint": "Weed Joint" "item.szar.weed_joint": "Weed Joint",
"item.szar.niggerite_ingot": "Niggerite Ingot",
"block.szar.niggerite_block": "Niggerite Block",
"item.szar.niggerite_sword": "Niggerite Sword",
"item.szar.niggerite_axe": "Niggerite Axe",
"item.szar.niggerite_pickaxe": "Niggerite Pickaxe",
"item.szar.niggerite_shovel": "Niggerite Shovel",
"item.szar.niggerite_hoe": "Niggerite Hoe",
"item.szar.niggerite_chestplate": "Niggerite Chestplate",
"item.szar.niggerite_leggings": "Niggerite Leggings",
"item.szar.niggerite_boots": "Niggerite Boots",
"item.szar.niggerite_helmet": "Niggerite Helmet"
} }

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "szar:block/niggerite_block"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "minecraft:item/template_spawn_egg"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "szar:block/niggerite_block"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 B

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 B

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 B

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 B

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 B

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"II ",
"IS ",
" S "
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
},
"S": {
"item": "minecraft:stick"
}
},
"result": {
"item": "szar:niggerite_axe",
"count": 1
}
}

View File

@@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"III",
"III",
"III"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
}
},
"result": {
"item": "szar:niggerite_block",
"count": 1
}
}

View File

@@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"I I",
"I I"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
}
},
"result": {
"item": "szar:niggerite_boots",
"count": 1
}
}

View File

@@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"I I",
"III",
"III"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
}
},
"result": {
"item": "szar:niggerite_chestplate",
"count": 1
}
}

View File

@@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"III",
"I I"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
}
},
"result": {
"item": "szar:niggerite_helmet",
"count": 1
}
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"II ",
" S ",
" S "
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
},
"S": {
"item": "minecraft:stick"
}
},
"result": {
"item": "szar:niggerite_hoe",
"count": 1
}
}

View File

@@ -0,0 +1,12 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "szar:niggerite_block"
}
],
"result": {
"item": "szar:niggerite_ingot",
"count": 9
}
}

View File

@@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"III",
"I I",
"I I"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
}
},
"result": {
"item": "szar:niggerite_leggings",
"count": 1
}
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"III",
" S ",
" S "
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
},
"S": {
"item": "minecraft:stick"
}
},
"result": {
"item": "szar:niggerite_pickaxe",
"count": 1
}
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"I",
"S",
"S"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
},
"S": {
"item": "minecraft:stick"
}
},
"result": {
"item": "szar:niggerite_shovel",
"count": 1
}
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"I",
"I",
"S"
],
"key": {
"I": {
"item": "szar:niggerite_ingot"
},
"S": {
"item": "minecraft:stick"
}
},
"result": {
"item": "szar:niggerite_sword",
"count": 1
}
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" G ",
"GNG",
" G "
],
"key": {
"G": {
"item": "minecraft:gold_ingot"
},
"N": {
"item": "szar:niggerite_ingot"
}
},
"result": {
"item": "szar:nwordpass",
"count": 1
}
}