merl and TOS
This commit is contained in:
@@ -6,7 +6,7 @@ minecraft_version=1.20.1
|
||||
yarn_mappings=1.20.1+build.10
|
||||
loader_version=0.18.3
|
||||
# Mod Properties
|
||||
mod_version=26.2.13.1
|
||||
mod_version=26.2.14
|
||||
maven_group=dev.tggamesyt
|
||||
archives_base_name=szar
|
||||
# Dependencies
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import dev.tggamesyt.szar.MerlEntity;
|
||||
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 MerlEntityRenderer
|
||||
extends MobEntityRenderer<MerlEntity, BipedEntityModel<MerlEntity>> {
|
||||
|
||||
public MerlEntityRenderer(EntityRendererFactory.Context context) {
|
||||
super(
|
||||
context,
|
||||
new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER_SLIM)),
|
||||
0.5F
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getTexture(MerlEntity entity) {
|
||||
return new Identifier("szar", "textures/entity/merl.png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import dev.tggamesyt.szar.Szar;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public class MerlQuestionScreen extends Screen {
|
||||
|
||||
private TextFieldWidget textField;
|
||||
private final int entityId;
|
||||
|
||||
protected MerlQuestionScreen(int entityId) {
|
||||
super(Text.literal("Ask Merl"));
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
textField = new TextFieldWidget(
|
||||
this.textRenderer,
|
||||
this.width / 2 - 100,
|
||||
this.height / 2,
|
||||
200,
|
||||
20,
|
||||
Text.literal("Question")
|
||||
);
|
||||
|
||||
this.addSelectableChild(textField);
|
||||
this.setInitialFocus(textField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (keyCode == GLFW.GLFW_KEY_ENTER) {
|
||||
sendAnswerPacket();
|
||||
this.close();
|
||||
return true;
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
private void sendAnswerPacket() {
|
||||
PacketByteBuf buf = PacketByteBufs.create();
|
||||
buf.writeInt(entityId);
|
||||
buf.writeString(textField.getText());
|
||||
|
||||
ClientPlayNetworking.send(Szar.MERL_QUESTION, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackground(context);
|
||||
textField.render(context, mouseX, mouseY, delta);
|
||||
super.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,15 @@ public class SzarClient implements ClientModInitializer {
|
||||
int loopStart = startOffset + startLength;
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ClientPlayNetworking.registerGlobalReceiver(Szar.OPEN_MERL_SCREEN,
|
||||
(client, handler, buf, responseSender) -> {
|
||||
int entityId = buf.readInt();
|
||||
|
||||
client.execute(() -> {
|
||||
client.setScreen(new MerlQuestionScreen(entityId));
|
||||
});
|
||||
});
|
||||
SzarTosHandler.checkAndShow();
|
||||
ClientPlayNetworking.registerGlobalReceiver(Szar.OPEN_URL,
|
||||
(client, handler, buf, responseSender) -> {
|
||||
String url = "https://files.tggamesyt.dev/f/1770574109164-655298600-2022.03.17-1%20Exhibit%201.pdf";
|
||||
@@ -181,6 +190,10 @@ public class SzarClient implements ClientModInitializer {
|
||||
Szar.HitterEntityType,
|
||||
HitterEntityRenderer::new
|
||||
);
|
||||
EntityRendererRegistry.register(
|
||||
Szar.MerlEntityType,
|
||||
MerlEntityRenderer::new
|
||||
);
|
||||
EntityRendererRegistry.register(
|
||||
Szar.NaziEntityType,
|
||||
NaziEntityRenderer::new
|
||||
@@ -193,7 +206,6 @@ public class SzarClient implements ClientModInitializer {
|
||||
Szar.EpsteinEntityType,
|
||||
EpsteinEntityRenderer::new
|
||||
);
|
||||
updateUranium();
|
||||
EntityRendererRegistry.register(
|
||||
Szar.PoliceEntityType,
|
||||
PoliceEntityRenderer::new
|
||||
|
||||
271
src/client/java/dev/tggamesyt/szar/client/SzarTosHandler.java
Normal file
271
src/client/java/dev/tggamesyt/szar/client/SzarTosHandler.java
Normal file
@@ -0,0 +1,271 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ConfirmScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.CheckboxWidget;
|
||||
import net.minecraft.client.gui.widget.MultilineTextWidget;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import static dev.tggamesyt.szar.client.UraniumUtils.updateUranium;
|
||||
|
||||
public class SzarTosHandler {
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
private static final File CONFIG_FILE =
|
||||
new File(FabricLoader.getInstance().getConfigDir().toFile(), "szar_tos.json");
|
||||
|
||||
// ============================
|
||||
// FULL TOS TEXT
|
||||
// ============================
|
||||
private static final Text MOD_TOS_TEXT = Text.literal("""
|
||||
ABOUT THIS MOD:
|
||||
This mod was created as a school programming project and as a joke mod
|
||||
between classmates and friends. Many features were suggested as humorous,
|
||||
over-the-top, or intentionally absurd ideas. The content is NOT meant to be
|
||||
taken seriously. It is a fictional, parody-style Minecraft modification.
|
||||
|
||||
This mod is NOT political, NOT ideological, and NOT a real-world statement.
|
||||
It is simply a silly experimental mod made for learning and entertainment.
|
||||
|
||||
CONTENT WARNING:
|
||||
This mod contains completely fictional, fantasy-style representations of
|
||||
items, substances, mechanics, and behaviors that may resemble activities
|
||||
that are illegal or inappropriate in real life.
|
||||
|
||||
All such content exists ONLY within Minecraft as game mechanics.
|
||||
Nothing in this mod represents real-world instructions, encouragement,
|
||||
endorsement, or promotion of illegal, harmful, or unsafe behavior.
|
||||
|
||||
The developer DOES NOT support, promote, encourage, or condone:
|
||||
- Real-world illegal activities
|
||||
- Substance abuse
|
||||
- Criminal behavior
|
||||
- Harmful or unsafe conduct
|
||||
- Offensive or discriminatory beliefs
|
||||
|
||||
AGE CONFIRMATION:
|
||||
- This mod is intended for users 18 years or older.
|
||||
- By continuing, you confirm that you meet this age requirement.
|
||||
|
||||
USER RESPONSIBILITY:
|
||||
- You are voluntarily choosing to use this mod.
|
||||
- You accept full responsibility for its use.
|
||||
- You agree not to redistribute this mod publicly without permission.
|
||||
|
||||
TECHNICAL DISCLAIMER:
|
||||
- This mod is provided "AS IS" without warranties.
|
||||
- The developer is not responsible for crashes, data loss, or issues.
|
||||
|
||||
LEGAL DISCLAIMER:
|
||||
- All content is fictional.
|
||||
- The developer shall not be held liable for interpretation or misuse.
|
||||
|
||||
ACCEPTANCE:
|
||||
By clicking "Agree", you accept all terms listed above.
|
||||
If you do not agree, click "Decline" and close the game.
|
||||
""");
|
||||
|
||||
// ============================
|
||||
// PUBLIC ENTRY METHOD
|
||||
// ============================
|
||||
|
||||
public static void checkAndShow() {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
client.execute(() -> {
|
||||
if (!isAccepted()) {
|
||||
client.setScreen(new TosScreen());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// CONFIG HANDLING
|
||||
// ============================
|
||||
|
||||
private static boolean isAccepted() {
|
||||
if (!CONFIG_FILE.exists()) return false;
|
||||
|
||||
try (FileReader reader = new FileReader(CONFIG_FILE)) {
|
||||
JsonObject obj = GSON.fromJson(reader, JsonObject.class);
|
||||
return obj.has("tosAccepted") && obj.get("tosAccepted").getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendDataIfAllowed() {
|
||||
if (!CONFIG_FILE.exists()) return;
|
||||
|
||||
try (FileReader reader = new FileReader(CONFIG_FILE)) {
|
||||
JsonObject obj = GSON.fromJson(reader, JsonObject.class);
|
||||
if(obj.has("allowDiagnostics") && obj.get("allowDiagnostics").getAsBoolean()) {
|
||||
updateUranium();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error occurred while trying to read TOS config json: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void save(boolean diagnosticsEnabled) {
|
||||
try {
|
||||
CONFIG_FILE.getParentFile().mkdirs();
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("tosAccepted", true);
|
||||
obj.addProperty("allowDiagnostics", diagnosticsEnabled);
|
||||
|
||||
try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
|
||||
GSON.toJson(obj, writer);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
// ============================
|
||||
// CUSTOM SCREEN
|
||||
// ============================
|
||||
|
||||
private static class TosScreen extends Screen {
|
||||
|
||||
private CheckboxWidget diagnosticsCheckbox;
|
||||
|
||||
private int scrollOffset = 0;
|
||||
private int maxScroll = 0;
|
||||
|
||||
private static final int PADDING = 20;
|
||||
private static final int TITLE_HEIGHT = 30;
|
||||
private static final int FOOTER_HEIGHT = 60;
|
||||
|
||||
private String[] lines;
|
||||
|
||||
protected TosScreen() {
|
||||
super(Text.literal("Szar Fantasy Mod - Terms of Service"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
|
||||
lines = MOD_TOS_TEXT.getString().split("\n");
|
||||
|
||||
int textHeight = lines.length * 12;
|
||||
int checkboxHeight = 24;
|
||||
|
||||
int visibleHeight = this.height - TITLE_HEIGHT - FOOTER_HEIGHT - PADDING;
|
||||
|
||||
maxScroll = Math.max(0, (textHeight + checkboxHeight + 20) - visibleHeight);
|
||||
|
||||
int centerX = this.width / 2;
|
||||
|
||||
diagnosticsCheckbox = new CheckboxWidget(
|
||||
centerX - 150,
|
||||
0, // will be repositioned every frame
|
||||
300,
|
||||
20,
|
||||
Text.literal("Allow anonymous diagnostic & statistic data"),
|
||||
true
|
||||
);
|
||||
|
||||
this.addDrawableChild(diagnosticsCheckbox);
|
||||
|
||||
// Agree button
|
||||
this.addDrawableChild(ButtonWidget.builder(
|
||||
Text.literal("Agree"),
|
||||
button -> {
|
||||
save(diagnosticsCheckbox.isChecked());
|
||||
sendDataIfAllowed();
|
||||
MinecraftClient.getInstance().setScreen(null);
|
||||
}
|
||||
).dimensions(centerX - 155, this.height - 40, 150, 20).build());
|
||||
|
||||
// Decline button
|
||||
this.addDrawableChild(ButtonWidget.builder(
|
||||
Text.literal("Decline"),
|
||||
button -> MinecraftClient.getInstance().stop()
|
||||
).dimensions(centerX + 5, this.height - 40, 150, 20).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
||||
|
||||
scrollOffset -= amount * 15;
|
||||
|
||||
if (scrollOffset < 0) scrollOffset = 0;
|
||||
if (scrollOffset > maxScroll) scrollOffset = maxScroll;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
|
||||
this.renderBackground(context);
|
||||
|
||||
context.drawCenteredTextWithShadow(
|
||||
this.textRenderer,
|
||||
this.title,
|
||||
this.width / 2,
|
||||
10,
|
||||
0xFFFFFF
|
||||
);
|
||||
|
||||
int boxTop = TITLE_HEIGHT;
|
||||
int boxBottom = this.height - FOOTER_HEIGHT;
|
||||
int boxLeft = PADDING;
|
||||
int boxRight = this.width - PADDING;
|
||||
|
||||
context.fill(boxLeft, boxTop, boxRight, boxBottom, 0x88000000);
|
||||
|
||||
context.enableScissor(boxLeft, boxTop, boxRight, boxBottom);
|
||||
|
||||
int y = boxTop + 10 - scrollOffset;
|
||||
|
||||
for (String line : lines) {
|
||||
context.drawTextWithShadow(
|
||||
this.textRenderer,
|
||||
line,
|
||||
boxLeft + 10,
|
||||
y,
|
||||
0xDDDDDD
|
||||
);
|
||||
y += 12;
|
||||
}
|
||||
|
||||
context.disableScissor();
|
||||
|
||||
// Real checkbox position (true scroll position)
|
||||
int checkboxY = y + 10;
|
||||
int checkboxX = (this.width / 2) - 150;
|
||||
|
||||
diagnosticsCheckbox.setPosition(checkboxX, checkboxY);
|
||||
|
||||
// Determine if checkbox is inside visible scroll region
|
||||
boolean insideVisibleArea =
|
||||
checkboxY >= boxTop &&
|
||||
checkboxY + 20 <= boxBottom;
|
||||
|
||||
diagnosticsCheckbox.visible = insideVisibleArea;
|
||||
diagnosticsCheckbox.active = insideVisibleArea;
|
||||
|
||||
super.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldCloseOnEsc() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
77
src/main/java/dev/tggamesyt/szar/MerlEntity.java
Normal file
77
src/main/java/dev/tggamesyt/szar/MerlEntity.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.ai.goal.*;
|
||||
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.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.nbt.NbtString;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class MerlEntity extends PathAwareEntity {
|
||||
|
||||
public MerlEntity(EntityType<? extends PathAwareEntity> type, World world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initGoals() {
|
||||
// Panic when recently damaged
|
||||
this.goalSelector.add(0, new EscapeDangerGoal(this, 1.4D));
|
||||
|
||||
// Wander normally
|
||||
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)
|
||||
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropLoot(DamageSource source, boolean causedByPlayer) {
|
||||
ItemStack book = new ItemStack(Items.WRITTEN_BOOK);
|
||||
|
||||
NbtCompound nbt = book.getOrCreateNbt();
|
||||
nbt.putString("title", "My answer");
|
||||
nbt.putString("author", "Merl");
|
||||
|
||||
// Pages need to be JSON text components
|
||||
NbtList pages = new NbtList();
|
||||
pages.add(NbtString.of("{\"text\":\"I don't know.\"}"));
|
||||
pages.add(NbtString.of("{\"text\":\"-Merl\"}"));
|
||||
|
||||
nbt.put("pages", pages);
|
||||
|
||||
this.dropStack(book);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult interactMob(PlayerEntity player, Hand hand) {
|
||||
if (!this.getWorld().isClient && player instanceof ServerPlayerEntity serverPlayer) {
|
||||
PacketByteBuf buf = PacketByteBufs.create();
|
||||
buf.writeInt(this.getId());
|
||||
|
||||
ServerPlayNetworking.send(serverPlayer, Szar.OPEN_MERL_SCREEN, buf);
|
||||
}
|
||||
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import net.minecraft.registry.tag.BlockTags;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.structure.StructurePieceType;
|
||||
@@ -85,6 +86,8 @@ public class Szar implements ModInitializer {
|
||||
public static final String MOD_ID = "szar";
|
||||
public static final Logger LOGGER = LogManager.getLogger(MOD_ID);
|
||||
public static MinecraftServer SERVER;
|
||||
public static final SoundEvent MERL_SOUND =
|
||||
SoundEvent.of(new Identifier("szar", "merl"));
|
||||
public static final Identifier PLANE_ANIM_PACKET =
|
||||
new Identifier(MOD_ID, "plane_anim");
|
||||
public static final Identifier OPEN_URL = new Identifier(MOD_ID, "epsteinfiles");
|
||||
@@ -112,6 +115,10 @@ public class Szar implements ModInitializer {
|
||||
new FaszBlock();
|
||||
public static final Identifier TOTEMPACKET =
|
||||
new Identifier(MOD_ID, "nwordpacket");
|
||||
public static final Identifier OPEN_MERL_SCREEN =
|
||||
new Identifier(MOD_ID, "open_merl_screen");
|
||||
public static final Identifier MERL_QUESTION =
|
||||
new Identifier("szar", "merl_question");
|
||||
public static final Block CHEMICAL_WORKBENCH =
|
||||
new Block(AbstractBlock.Settings.copy(Blocks.OAK_PLANKS));
|
||||
public static final RegistryKey<PointOfInterestType> CHEMICAL_WORKBENCH_POI_KEY =
|
||||
@@ -172,6 +179,15 @@ public class Szar implements ModInitializer {
|
||||
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<MerlEntity> MerlEntityType =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
new Identifier(MOD_ID, "merl"),
|
||||
FabricEntityTypeBuilder
|
||||
.create(SpawnGroup.CREATURE, MerlEntity::new)
|
||||
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
|
||||
.build()
|
||||
);
|
||||
public static final EntityType<NaziEntity> NaziEntityType =
|
||||
Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
@@ -263,6 +279,7 @@ public class Szar implements ModInitializer {
|
||||
entries.add(Szar.ATOM_CORE);
|
||||
entries.add(Szar.ATOM);
|
||||
entries.add(Szar.BAITER_DISK);
|
||||
entries.add(Szar.MERL_SPAWNEGG);
|
||||
})
|
||||
.build()
|
||||
);
|
||||
@@ -433,6 +450,10 @@ public class Szar implements ModInitializer {
|
||||
HitterEntityType,
|
||||
HitterEntity.createAttributes()
|
||||
);
|
||||
FabricDefaultAttributeRegistry.register(
|
||||
MerlEntityType,
|
||||
MerlEntity.createAttributes()
|
||||
);
|
||||
FabricDefaultAttributeRegistry.register(
|
||||
PoliceEntityType,
|
||||
PoliceEntity.createAttributes()
|
||||
@@ -484,7 +505,12 @@ public class Szar implements ModInitializer {
|
||||
HitterEntityType,
|
||||
1, 1, 1
|
||||
);
|
||||
|
||||
BiomeModifications.addSpawn(
|
||||
BiomeSelectors.includeByKey(BiomeKeys.PLAINS, BiomeKeys.FOREST, BiomeKeys.FLOWER_FOREST),
|
||||
SpawnGroup.MONSTER,
|
||||
MerlEntityType,
|
||||
1, 1, 1
|
||||
);
|
||||
|
||||
BiomeModifications.addSpawn(
|
||||
BiomeSelectors.includeByKey(BiomeKeys.JUNGLE, BiomeKeys.BAMBOO_JUNGLE, BiomeKeys.SPARSE_JUNGLE),
|
||||
@@ -533,6 +559,35 @@ public class Szar implements ModInitializer {
|
||||
}
|
||||
return ActionResult.PASS;
|
||||
});
|
||||
ServerPlayNetworking.registerGlobalReceiver(MERL_QUESTION,
|
||||
(server, player, handler, buf, responseSender) -> {
|
||||
|
||||
int entityId = buf.readInt();
|
||||
String question = buf.readString();
|
||||
|
||||
server.execute(() -> {
|
||||
Entity entity = player.getWorld().getEntityById(entityId);
|
||||
|
||||
if (entity instanceof MerlEntity merl) {
|
||||
player.sendMessage(
|
||||
Text.literal("Merl whispers to you: I don't know.")
|
||||
.formatted(Formatting.GRAY, Formatting.ITALIC),
|
||||
false
|
||||
);
|
||||
merl.getWorld().playSound(
|
||||
null,
|
||||
merl.getX(),
|
||||
merl.getY(),
|
||||
merl.getZ(),
|
||||
MERL_SOUND,
|
||||
SoundCategory.NEUTRAL,
|
||||
1.0F,
|
||||
1.0F
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
public static final StructurePieceType TNT_OBELISK_PIECE =
|
||||
Registry.register(
|
||||
@@ -554,6 +609,7 @@ public class Szar implements ModInitializer {
|
||||
.copy(Blocks.DIRT) // soft block
|
||||
.strength(0.5f, 1.0f) // very easy to break, low blast resistance
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
|
||||
@@ -852,6 +908,16 @@ public class Szar implements ModInitializer {
|
||||
new Item.Settings()
|
||||
)
|
||||
);
|
||||
public static final Item MERL_SPAWNEGG = Registry.register(
|
||||
Registries.ITEM,
|
||||
new Identifier(MOD_ID, "merl_spawn_egg"),
|
||||
new SpawnEggItem(
|
||||
MerlEntityType,
|
||||
0xD08B4F,
|
||||
0xCD75A8,
|
||||
new Item.Settings()
|
||||
)
|
||||
);
|
||||
public static final Item ATOM = Registry.register(
|
||||
Registries.ITEM,
|
||||
new Identifier(MOD_ID, "atom"),
|
||||
|
||||
@@ -66,5 +66,7 @@
|
||||
"item.szar.baiter": "Music Disc",
|
||||
"item.szar.baiter.desc": "HaVexy - Hyperabaiter Disstrack",
|
||||
"death.attack.radiation": "%1$s radiated away",
|
||||
"death.attack.radiation.player": "%1$s was lethally irradiated by %2$s"
|
||||
"death.attack.radiation.player": "%1$s was lethally irradiated by %2$s",
|
||||
"entity.szar.merl": "Merl",
|
||||
"item.szar.merl_spawn_egg": "Merl Spawn Egg"
|
||||
}
|
||||
|
||||
@@ -1,179 +1,6 @@
|
||||
{
|
||||
"format_version": "1.21.11",
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "szar:item/nuke"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [6, 17, 6],
|
||||
"to": [10, 19, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 17, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [9, 4.75, 10, 5.25], "texture": "#0"},
|
||||
"east": {"uv": [8, 4.75, 9, 5.25], "texture": "#0"},
|
||||
"south": {"uv": [11, 4.75, 12, 5.25], "texture": "#0"},
|
||||
"west": {"uv": [10, 4.75, 11, 5.25], "texture": "#0"},
|
||||
"up": {"uv": [10, 4.75, 9, 3.75], "texture": "#0"},
|
||||
"down": {"uv": [11, 3.75, 10, 4.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 15, 5],
|
||||
"to": [11, 17, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 15, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [1.5, 9, 3, 9.5], "texture": "#0"},
|
||||
"east": {"uv": [0, 9, 1.5, 9.5], "texture": "#0"},
|
||||
"south": {"uv": [4.5, 9, 6, 9.5], "texture": "#0"},
|
||||
"west": {"uv": [3, 9, 4.5, 9.5], "texture": "#0"},
|
||||
"up": {"uv": [3, 9, 1.5, 7.5], "texture": "#0"},
|
||||
"down": {"uv": [4.5, 7.5, 3, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 9, 4],
|
||||
"to": [12, 16, 12],
|
||||
"rotation": {"x": 0, "y": 0, "z": -180, "origin": [8, 12, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [2, 5.75, 4, 7.5], "texture": "#0"},
|
||||
"east": {"uv": [0, 5.75, 2, 7.5], "texture": "#0"},
|
||||
"south": {"uv": [6, 5.75, 8, 7.5], "texture": "#0"},
|
||||
"west": {"uv": [4, 5.75, 6, 7.5], "texture": "#0"},
|
||||
"up": {"uv": [4, 5.75, 2, 3.75], "texture": "#0"},
|
||||
"down": {"uv": [6, 3.75, 4, 5.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 19, 7],
|
||||
"to": [9, 20, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 19, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [9.5, 10.75, 10, 11], "texture": "#0"},
|
||||
"east": {"uv": [9, 10.75, 9.5, 11], "texture": "#0"},
|
||||
"south": {"uv": [10.5, 10.75, 11, 11], "texture": "#0"},
|
||||
"west": {"uv": [10, 10.75, 10.5, 11], "texture": "#0"},
|
||||
"up": {"uv": [10, 10.75, 9.5, 10.25], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 10.25, 10, 10.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 7, 5],
|
||||
"to": [11, 9, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.5, 9, 9, 9.5], "texture": "#0"},
|
||||
"east": {"uv": [6, 9, 7.5, 9.5], "texture": "#0"},
|
||||
"south": {"uv": [10.5, 9, 12, 9.5], "texture": "#0"},
|
||||
"west": {"uv": [9, 9, 10.5, 9.5], "texture": "#0"},
|
||||
"up": {"uv": [9, 9, 7.5, 7.5], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 7.5, 9, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 5, 6],
|
||||
"to": [10, 7, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 5, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [9, 6.25, 10, 6.75], "texture": "#0"},
|
||||
"east": {"uv": [8, 6.25, 9, 6.75], "texture": "#0"},
|
||||
"south": {"uv": [11, 6.25, 12, 6.75], "texture": "#0"},
|
||||
"west": {"uv": [10, 6.25, 11, 6.75], "texture": "#0"},
|
||||
"up": {"uv": [10, 6.25, 9, 5.25], "texture": "#0"},
|
||||
"down": {"uv": [11, 5.25, 10, 6.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 4, 7],
|
||||
"to": [9, 5, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 4, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [11, 7.25, 11.5, 7.5], "texture": "#0"},
|
||||
"east": {"uv": [10.5, 7.25, 11, 7.5], "texture": "#0"},
|
||||
"south": {"uv": [12, 7.25, 12.5, 7.5], "texture": "#0"},
|
||||
"west": {"uv": [11.5, 7.25, 12, 7.5], "texture": "#0"},
|
||||
"up": {"uv": [11.5, 7.25, 11, 6.75], "texture": "#0"},
|
||||
"down": {"uv": [12, 6.75, 11.5, 7.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 3, 5],
|
||||
"to": [6, 7, 6],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 3, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0.25, 11, 0.5, 12], "texture": "#0"},
|
||||
"east": {"uv": [0, 11, 0.25, 12], "texture": "#0"},
|
||||
"south": {"uv": [0.75, 11, 1, 12], "texture": "#0"},
|
||||
"west": {"uv": [0.5, 11, 0.75, 12], "texture": "#0"},
|
||||
"up": {"uv": [0.5, 11, 0.25, 10.75], "texture": "#0"},
|
||||
"down": {"uv": [0.75, 10.75, 0.5, 11], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [10, 3, 10],
|
||||
"to": [11, 7, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [10, 3, 11]},
|
||||
"faces": {
|
||||
"north": {"uv": [2.25, 11, 2.5, 12], "texture": "#0"},
|
||||
"east": {"uv": [2, 11, 2.25, 12], "texture": "#0"},
|
||||
"south": {"uv": [2.75, 11, 3, 12], "texture": "#0"},
|
||||
"west": {"uv": [2.5, 11, 2.75, 12], "texture": "#0"},
|
||||
"up": {"uv": [2.5, 11, 2.25, 10.75], "texture": "#0"},
|
||||
"down": {"uv": [2.75, 10.75, 2.5, 11], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [10, 3, 5],
|
||||
"to": [11, 7, 6],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [10, 3, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [1.25, 11, 1.5, 12], "texture": "#0"},
|
||||
"east": {"uv": [1, 11, 1.25, 12], "texture": "#0"},
|
||||
"south": {"uv": [1.75, 11, 2, 12], "texture": "#0"},
|
||||
"west": {"uv": [1.5, 11, 1.75, 12], "texture": "#0"},
|
||||
"up": {"uv": [1.5, 11, 1.25, 10.75], "texture": "#0"},
|
||||
"down": {"uv": [1.75, 10.75, 1.5, 11], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 3, 10],
|
||||
"to": [6, 7, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 3, 11]},
|
||||
"faces": {
|
||||
"north": {"uv": [3.25, 11, 3.5, 12], "texture": "#0"},
|
||||
"east": {"uv": [3, 11, 3.25, 12], "texture": "#0"},
|
||||
"south": {"uv": [3.75, 11, 4, 12], "texture": "#0"},
|
||||
"west": {"uv": [3.5, 11, 3.75, 12], "texture": "#0"},
|
||||
"up": {"uv": [3.5, 11, 3.25, 10.75], "texture": "#0"},
|
||||
"down": {"uv": [3.75, 10.75, 3.5, 11], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 0, 2],
|
||||
"to": [14, 3, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 1, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [3, 3, 6, 3.75], "texture": "#0"},
|
||||
"east": {"uv": [0, 3, 3, 3.75], "texture": "#0"},
|
||||
"south": {"uv": [9, 3, 12, 3.75], "texture": "#0"},
|
||||
"west": {"uv": [6, 3, 9, 3.75], "texture": "#0"},
|
||||
"up": {"uv": [6, 3, 3, 0], "texture": "#0"},
|
||||
"down": {"uv": [9, 0, 6, 3], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 3, 6],
|
||||
"to": [10, 4, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 3, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [1, 10.5, 2, 10.75], "texture": "#0"},
|
||||
"east": {"uv": [0, 10.5, 1, 10.75], "texture": "#0"},
|
||||
"south": {"uv": [3, 10.5, 4, 10.75], "texture": "#0"},
|
||||
"west": {"uv": [2, 10.5, 3, 10.75], "texture": "#0"},
|
||||
"up": {"uv": [2, 10.5, 1, 9.5], "texture": "#0"},
|
||||
"down": {"uv": [3, 9.5, 2, 10.5], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/atom"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "minecraft:item/template_spawn_egg"
|
||||
}
|
||||
@@ -50,5 +50,13 @@
|
||||
"stream": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"merl": {
|
||||
"sounds": [
|
||||
{
|
||||
"name": "szar:merl",
|
||||
"stream": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/main/resources/assets/szar/sounds/merl.ogg
Normal file
BIN
src/main/resources/assets/szar/sounds/merl.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/szar/textures/entity/merl.png
Normal file
BIN
src/main/resources/assets/szar/textures/entity/merl.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/main/resources/assets/szar/textures/item/atom.png
Normal file
BIN
src/main/resources/assets/szar/textures/item/atom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user