Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
project.ext.modID = "fair.examplemod" // The unique id of your mod. Must be all lowercase and cannot use special characters.
project.ext.modName = "Example Mod" // The display name of your mod.
project.ext.modVersion = "1.0" // Your current builds version. Must follow the xx.xx... format.
project.ext.gameVersion = "1.0.2" // The target game version.
project.ext.gameVersion = "1.1.1" // The target game version.
project.ext.modDescription = "Just an example mod" // Short description of what your mod is.
project.ext.author = "Fair" // Your name

Expand Down Expand Up @@ -157,4 +157,4 @@ task buildModJar(type: Jar) {

archiveName "${jarName}.jar"
destinationDir file(buildLocation)
}
}
29 changes: 28 additions & 1 deletion src/main/java/examplemod/ExampleMod.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package examplemod;


import examplemod.examples.*;
import necesse.engine.commands.CommandsManager;
import necesse.engine.modLoader.annotations.ModEntry;
Expand All @@ -9,13 +10,21 @@
import necesse.inventory.recipe.Recipe;
import necesse.inventory.recipe.Recipes;
import necesse.level.maps.biomes.Biome;
import examplemod.examples.items.*;

@ModEntry
public class ExampleMod {

public void init() {
System.out.println("Hello world from my example mod!");

// Register a simple biome that will not appear in natural world gen.
BiomeRegistry.registerBiome("exampleincursion", new ExampleBiome(), false);
// Register the incursion biome with tier requirement 1.
IncursionBiomeRegistry.registerBiome("exampleincursion", new ExampleIncursionBiome(), 1);
// Register the level class used for the incursion.
LevelRegistry.registerLevel("exampleincursionlevel", ExampleIncursionLevel.class);

// Register our tiles
TileRegistry.registerTile("exampletile", new ExampleTile(), 1, true);

Expand All @@ -24,8 +33,12 @@ public void init() {

// Register our items
ItemRegistry.registerItem("exampleitem", new ExampleMaterialItem(), 10, true);
ItemRegistry.registerItem("examplehuntincursionitem", new ExampleHuntIncursionMaterialItem(), 50, true);
ItemRegistry.registerItem("examplesword", new ExampleSwordItem(), 20, true);
ItemRegistry.registerItem("examplestaff", new ExampleProjectileWeapon(), 30, true);
ItemRegistry.registerItem("examplepotionitem", new ExamplePotionItem(), 10, true);

ItemRegistry.registerItem("examplefooditem", new ExampleFoodItem(),15, true);

// Register our mob
MobRegistry.registerMob("examplemob", ExampleMob.class, true);
Expand All @@ -37,6 +50,8 @@ public void init() {
BuffRegistry.registerBuff("examplebuff", new ExampleBuff());

PacketRegistry.registerPacket(ExamplePacket.class);


}

public void initResources() {
Expand Down Expand Up @@ -80,7 +95,19 @@ public void postInit() {
}
).showAfter("exampleitem")); // Show the recipe after example item recipe

// Add out example mob to default cave mobs.
// Example food item recipe
Recipes.registerModRecipe(new Recipe(
"examplefooditem",
1,
RecipeTechRegistry.COOKING_POT,
new Ingredient[]{
new Ingredient("bread", 1),
new Ingredient("strawberry", 2),
new Ingredient("sugar", 1)
}
));

// Add our example mob to default cave mobs.
// Spawn tables use a ticket/weight system. In general, common mobs have about 100 tickets.
Biome.defaultCaveMobs
.add(100, "examplemob");
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/examplemod/examples/ExampleBiome.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package examplemod.examples;

import necesse.engine.AbstractMusicList;
import necesse.engine.MusicList;
import necesse.engine.registries.MusicRegistry;
import necesse.entity.mobs.PlayerMob;
import necesse.level.maps.Level;
import necesse.level.maps.biomes.Biome;
import necesse.level.maps.biomes.MobSpawnTable;

// A minimalist biome used solely for the ExampleIncursion
// the Example Mob is used here as the spawn
public class ExampleBiome extends Biome {
public static MobSpawnTable critters = (new MobSpawnTable())
.include(Biome.defaultCaveCritters);
public static MobSpawnTable mobs = new MobSpawnTable()
.add(100,"examplemob");

@Override
public AbstractMusicList getLevelMusic(Level level, PlayerMob perspective) {
return new MusicList(MusicRegistry.ForestPath);
}

@Override
public MobSpawnTable getCritterSpawnTable(Level level) {
return critters;
}

@Override
public MobSpawnTable getMobSpawnTable(Level level) {

return mobs;
}
}
98 changes: 98 additions & 0 deletions src/main/java/examplemod/examples/ExampleIncursionBiome.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package examplemod.examples;

import necesse.engine.network.server.Server;
import necesse.engine.registries.ItemRegistry;
import necesse.engine.util.LevelIdentifier;
import necesse.engine.util.TicketSystemList;
import necesse.engine.world.WorldEntity;
import necesse.entity.objectEntity.FallenAltarObjectEntity;
import necesse.inventory.item.Item;
import necesse.inventory.lootTable.LootItemInterface;
import necesse.inventory.lootTable.lootItem.ChanceLootItem;
import necesse.level.maps.IncursionLevel;
import necesse.level.maps.incursion.*;
import necesse.inventory.lootTable.LootTable;

import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
import java.awt.Color;
import java.util.ArrayList;

/**
* An example incursion biome.
* This class defines how the incursion behaves: rewards, available objectives,
* altar appearance, and which level class is used.
*/
public class ExampleIncursionBiome extends IncursionBiome {

// String ID passed to the IncursionBiome base class
public ExampleIncursionBiome() {
super("reaper");
}

// Items required to be obtained when completing an extraction objective in this incursion
@Override
public Collection<Item> getExtractionItems(IncursionData data) {
return Collections.singleton(ItemRegistry.getItem("tungstenore"));
}

/**
* Loot dropped from mobs during hunt-type incursion objectives.
* This example returns a custom item to demonstrate adding new drops.
*/
@Override
public LootTable getHuntDrop(IncursionData incursionData) {
return new LootTable(new LootItemInterface[] {
(LootItemInterface) new ChanceLootItem(0.66F, "examplehuntincursionitem")
});
}

// Defines which incursion types are available and their relative chances
@Override
public TicketSystemList<Supplier<IncursionData>> getAvailableIncursions(int tabletTier, IncursionData incursionData) {
TicketSystemList<Supplier<IncursionData>> system = new TicketSystemList();

// Base ticket weights for each incursion type
int huntTickets = 100;
int extractionTickets = 100;

// Apply modifiers from the previous incursion, if present
if (incursionData != null) {
huntTickets = (int)(huntTickets * ((Float)incursionData.nextIncursionModifiers
.getModifier(IncursionDataModifiers.MODIFIER_HUNT_DROPS)).floatValue());
extractionTickets = (int)(extractionTickets * ((Float)incursionData.nextIncursionModifiers
.getModifier(IncursionDataModifiers.MODIFIER_EXTRACTION_DROPS)).floatValue());
}

// Register hunt and extraction incursions with their calculated weights
system.addObject(huntTickets, () -> new BiomeHuntIncursionData(1.0F, this, tabletTier));
system.addObject(extractionTickets, () -> new BiomeExtractionIncursionData(1.0F, this, tabletTier));
return system;
}

// Creates a new incursion level instance when players enter through the fallen altar
@Override
public IncursionLevel getNewIncursionLevel(FallenAltarObjectEntity altar, LevelIdentifier identifier,
BiomeMissionIncursionData incursion, Server server,
WorldEntity world, AltarData altarData) {
return new ExampleIncursionLevel(identifier, incursion, world, altarData);
}

/**
* Colors used for the glowing gateway lights on the fallen altar.
* IncursionBiome requires this method; at least 4 colors are needed.
*/
@Override
public ArrayList<Color> getFallenAltarGatewayColorsForBiome() {
ArrayList<Color> colors = new ArrayList<>();
// Repeat colors to satisfy the altar rendering requirements
colors.add(new Color(181, 80, 120));
colors.add(new Color(215, 42, 52));
colors.add(new Color(181, 92, 59));
colors.add(new Color(181, 80, 120));
colors.add(new Color(215, 42, 52));
colors.add(new Color(181, 92, 59));
return colors;
}
}
87 changes: 87 additions & 0 deletions src/main/java/examplemod/examples/ExampleIncursionLevel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package examplemod.examples;

import necesse.engine.GameEvents;
import necesse.engine.events.GameEvent;
import necesse.engine.events.PreventableGameEvent;
import necesse.engine.events.worldGeneration.GenerateCaveLayoutEvent;
import necesse.engine.events.worldGeneration.GeneratedCaveOresEvent;
import necesse.engine.registries.BiomeRegistry;
import necesse.engine.registries.ObjectRegistry;
import necesse.engine.util.LevelIdentifier;
import necesse.engine.world.WorldEntity;
import necesse.level.maps.IncursionLevel;
import necesse.level.maps.Level;
import necesse.level.maps.generationModules.CaveGeneration;
import necesse.level.maps.generationModules.PresetGeneration;
import necesse.level.maps.incursion.AltarData;
import necesse.level.maps.incursion.BiomeExtractionIncursionData;
import necesse.level.maps.incursion.BiomeMissionIncursionData;
import necesse.level.maps.incursion.IncursionBiome;

/**
* Example incursion level.
* Demonstrates what is required for a working incursion:
* cave generation, entrance creation, and ore placement.
*/
public class ExampleIncursionLevel extends IncursionLevel {

/**
* this constructor has to be formed in this way and present otherwise the game wont register the level to the registry
*/
public ExampleIncursionLevel(LevelIdentifier identifier, int width, int height, WorldEntity worldEntity) {
super(identifier, width, height, worldEntity);
this.baseBiome = BiomeRegistry.getBiome("exampleincursion");
this.isCave = true;
}

/**
* Constructor used when an incursion is entered.
* Creates a fixed-size level and immediately generates its contents.
*/
public ExampleIncursionLevel(LevelIdentifier identifier, BiomeMissionIncursionData incursionData, WorldEntity worldEntity, AltarData altarData) {
super(identifier, 150, 150, incursionData, worldEntity);
this.baseBiome = BiomeRegistry.getBiome("exampleincursion");
this.isCave = true;
generateLevel(incursionData, altarData);
}

public void generateLevel(BiomeMissionIncursionData incursionData, AltarData altarData) {

// Create the cave generator using deep rock tiles for floors and walls
CaveGeneration cg = new CaveGeneration(this, "deeprocktile", "deeprock");

// Seed the generator so this incursion layout is deterministic per mission
cg.random.setSeed(incursionData.getUniqueID());

// Fire the cave layout generation event, allowing mods or perks to modify
// or cancel cave generation before the default logic runs
GameEvents.triggerEvent(
(PreventableGameEvent) new GenerateCaveLayoutEvent(this, cg),
e -> cg.generateLevel(0.38F, 4, 3, 6)
);

// Used to reserve space so later generation steps avoid overwriting the entrance
PresetGeneration entranceAndPerkPresets = new PresetGeneration(this);

// Generate a incursion entrance that clears terrain,
// blends edges, reserves space, and places the return portal
IncursionBiome.generateEntrance(
this,
entranceAndPerkPresets,
cg.random,
32,
cg.rockTile,
"exampletile",
"exampletile",
"exampleobject"
);

// For extraction incursions, guarantee tungsten ore veins for objectives
if (incursionData instanceof BiomeExtractionIncursionData) {
cg.generateGuaranteedOreVeins(40, 4, 8, ObjectRegistry.getObjectID("tungstenoredeeprock"));
}

// Notify listeners that cave ore generation has completed
GameEvents.triggerEvent((GameEvent) new GeneratedCaveOresEvent((Level) this, cg));
}
}
25 changes: 25 additions & 0 deletions src/main/java/examplemod/examples/items/ExampleFoodItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package examplemod.examples.items;

import necesse.engine.modifiers.ModifierValue;
import necesse.entity.mobs.buffs.BuffModifiers;
import necesse.inventory.item.Item;
import necesse.inventory.item.placeableItem.consumableItem.food.FoodConsumableItem;
import necesse.level.maps.levelData.settlementData.settler.Settler;

public class ExampleFoodItem extends FoodConsumableItem {
public ExampleFoodItem() {
super(
250, // stack size
Item.Rarity.COMMON, // rarity
Settler.FOOD_FINE, // food tier
20, // nutrition
480, // buff duration in seconds
new ModifierValue<>(BuffModifiers.MAX_HEALTH_FLAT, 10),
new ModifierValue<>(BuffModifiers.SPEED, 0.05f)
);

// Configure additional properties after super()
this.spoilDuration(480); // spoil duration in minutes
this.addGlobalIngredient("anycookedfood");// NOTE: returns Item
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package examplemod.examples.items;

import necesse.inventory.item.matItem.MatItem;

public class ExampleHuntIncursionMaterialItem extends MatItem {

public ExampleHuntIncursionMaterialItem() {
super(100, Rarity.RARE);
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package examplemod.examples;
package examplemod.examples.items;

import necesse.inventory.item.matItem.MatItem;

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/examplemod/examples/items/ExamplePotionItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package examplemod.examples.items;
import necesse.inventory.item.Item;
import necesse.inventory.item.placeableItem.consumableItem.potionConsumableItem.SimplePotionItem;
import examplemod.examples.ExampleBuff;

public class ExamplePotionItem extends SimplePotionItem {
public ExamplePotionItem() {
super(100,Rarity.COMMON,"examplebuff",100, new String[] { "examplepotionitemtip" });
}

}
Binary file added src/main/resources/items/examplefooditem.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/resources/items/exampleincursiontablet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/resources/items/examplepotionitem.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 11 additions & 1 deletion src/main/resources/locale/en.lang
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ exampleobject=Example Object

[item]
exampleitem=Example Item
examplehuntincursionitem=Example Hunt Incursion Item
examplepotionitem=Example Potion
examplesword=Example Sword
examplestaff=Example Staff
examplefooditem=Example Food

[itemtooltip]
examplestafftip=Shoots a homing, piercing projectile
examplepotionitemtip= An example potion

[mob]
examplemob=Example Mob

[buff]
examplebuff=Example Buff
examplebuff=Example Buff

[biome]
exampleincursion=Example Incursion

[incursion]
exampleincursion=Example Incursion