-
Notifications
You must be signed in to change notification settings - Fork 0
Creating Missions
If you wish to create a storyline for creatures added in your own or someone else's mod, please read this article and follow the indicates to implement your own missions and stories.
We do not recommend you to create tasks for Minecraft vanilla hostiles (and even including passive and neutral mobs), because we will soon update them - if necessary, you can directly create PR to the repository to contribute.
But we highly recommend you to create quests and stories, and make datapacks and additional mods for creatures added by other mods.
This mod is open-sourced under the MIT license, so you can choose any license for your datapacks and mods.
If you have added loot tables, recipes or advancement in your mod or datapack, it will be easier for you to understand this section. There are only datapack operations in this section, so it doesn't matter if you are not able to code.
You are supposed to add JSON files in data/<modid>/rpm/missions
directory. Pay attention to where you place your JSON file - the path will be the id of your mission, and it will be used in mission triggering. For example, here's a legal datapack with 4 missions:
+ data
|---+ your_mod_id
| |---+ advancements
| | |--- ...
| |---+ loot_tables
| | |--- ...
| |---+ rpm
| | |---+ missions
| | |---* lumine1.json
| | |---* lumine2.json
| | |---+ wraith
| | |---* entrenchment.json
| | |---* outside.json
| |---+ recipes
| | |--- ...
| |---+ tags
| | |--- ...
| |--- ...
|---+ minecraft
|---+ tags
| |--- ...
|--- ...
The ids of the missions are:
your_mod_id:lumine1
your_mod_id:lumine2
your_mod_id:wraith/entrenchment
your_mod_id:wraith/outside
The JSON files above should follow the following format:
{
"requires": [
<multiple resource locations, stands for the former mission. this mission will never be triggered if the player haven't finished all the former missions>
],
"reward": <optional. the resource location of a entity_type. if this field is presented, all monsters of this entity_type will never attack the player who complete this mission>,
"messages": [
<dialogues when a player receive this mission. each entry should be the object according the following format>
{
"key": <key of i18n>,
"speaker": <"player" or "npc", who says this sentence>
}
],
"messagesAfter": [
<dialogues when a player finish this mission. each entry should be the object according the following format>
{
"key": <key of i18n>,
"speaker": <"player" or "npc", who says this sentence>
}
],
"loot_table": <optional. the id of a loot table. if present, player will obtain loots when receive or finish the mission>,
"loot_before": <optional. true or false (default false). true for obtaining the loots when receive the mission, while false when finish the mission>
}
The only limitation of our mission system is that a player can only talk with one NPC at the same time, or talk to himself/herself. But if you want to make a more complex dialogue, you can make more missions and trigger them at the same place in order.
You can find the JSON files of the original mod here, and i18n of dialogues here.
The original mod provides you two ways to trigger a mission - using summon blocks and calling the APIs in your code. Obviously, datapack developers may only use the first way while mod developers are able to use one or both of them.
First, the player who has already triggered and even finished the mission can not trigger the same mission repeatly. For example, a player under "Zombie Fort" mission enters another Zombie Fort, the same mission will not be triggered; a player who has already finished "Crack the Glowing Crystal" enters another skeleton palace or cracks another glowing crystal, the same mission will not be triggered or finished.
Second, only a player under a mission can trigger the finishing mission dialogue. For example, a player who has not received "Fight for Zombies" mission kills Zombie Tyrant, he/she will not finish "Fight for Zombies" mission - actually, the mod does not allow players to do so in survival mode because of the high resistance and regeneration of Zombie Tyrant before players finish mission "Senior Zombie and Villager".
Finally, players in creative mode cannot trigger any mission - you can build your structure with technical blocks without triggering missions. If you want to debug the mission quickly, try spectator mode. And players in adventure mode and survival mode can obviously trigger the missions.
All missions is triggered under the rules above - you don't need to check it manually because the original mod has already checked them if you use summon blocks or call APIs to trigger missions.
If you use summon blocks to trigger a mission, you probably need to add structures or features to the worldgen. When players enter the structure, walk into the effective sensing range of the summon block, it will turn into air block and trigger missions for nearby players.
You can get a summon block item from creative mode tab and place it - it looks just like an air block. You should modify the NBT of its block entity by /data modify block <x> <y> <z> <nbt>
to set the details for triggering missions.
The NBT should look like this:
{
summon: <optional, NBT of the enity it summons. if present, must contains `id` to indicate the entity_type of the entity>,
distance: <radius of the effective sensing range, default 16>,
id: "real_peaceful_mode:summon_block",
mission_type: <"receive" or "finish", indicate receive mission or finish mission when trigger>,
mission: <optional, mission id. if absent, no mission will be triggered but entity will be summoned>
}
For example, in mission "real_peaceful_mode:skeleton1" (an archer skeleton wants player to crack a glowing crystal block), the summon block is two blocks away from the glowing crystal, and the NBT of its block entity is:
{
summon: {
ArmorItems: [{}, {}, {}, {id: "minecraft:chainmail_helmet", Count: 1b}]
id: "minecraft:skeleton"
NoAI: 1b
HandItems: [{id: "minecraft:air", Count: 1b}]
}
mission: "real_peaceful_mode:skeleton1"
distance: 8
id: "real_peaceful_mode:summon_block"
mission_type: "receive"
}
Remember to edit the NBT in creative mode or NBT Editor (for example, NBT Explorer and other development tools) because player in other modes may trigger the mission directly.
Summon blocks will turn into air blocks after triggering. So players should stay close and walk into the area together to trigger the same mission at the same time.
Class MissionHelper
in com.hexagram2021.real_peaceful_mode.api
encapsulates two APIs: triggerMissionForPlayers
and triggerMissionForPlayer
. One is for more than one players while the other one is for only one player. Let's see the signature of the two functions:
void triggerMissionForPlayers(ResourceLocation missionId, SummonBlockEntity.SummonMissionType summonMissionType, ServerLevel serverLevel, Predicate<ServerPlayer> predicate, @Nullable LivingEntity npc, Consumer<ServerPlayer> additionWork);
void triggerMissionForPlayer(ResourceLocation missionId, SummonBlockEntity.SummonMissionType summonMissionType, ServerPlayer player, @Nullable LivingEntity npc, Consumer<ServerPlayer> additionWork);
missionId: id of mission to trigger.
summonMissionType: receive or finish mission.
serverLevel (first): the world that the mission is triggered in.
predicate (first): other conditions of player to trigger the mission, for example, holding items, distance with another entity... and you do NOT need to check the three rules above because it will be checked by the original mod.
player (second): the player who triggers the mission.
npc: NPC who talks with the player, null if player talks to himself/herself.
additionWork: Additional operation for players after trigger the mission.
These two APIs can only be called in server, not client. Here are some examples of the original mods:
- If a player kill a Zombie Tyrant, players not far away from 32 blocks will trigger to finish the mission "Fight for Zombies". It called the first API and override the
die
function of entity Zombie Tyrant:
@Override
public void die(DamageSource damageSource) {
if(this.level() instanceof ServerLevel serverLevel) {
MissionHelper.triggerMissionForPlayers(
new ResourceLocation(MODID, "zombie3"), SummonBlockEntity.SummonMissionType.FINISH, serverLevel,
player -> player.closerThan(this, 32.0D), this, player -> {}
);
}
super.die(damageSource);
}
- If a player holding 64 soul soil blocks and right click a Skeleton King, the player will lose 64 soul soil and the king's scepter will disappear. It called the second API and use the callback function:
if (itemInHand.is(Items.SOUL_SOIL) && itemInHand.getCount() >= 64) {
MissionHelper.triggerMissionForPlayer(
new ResourceLocation(MODID, "skeleton3"), SummonBlockEntity.SummonMissionType.FINISH, serverPlayer,
this, player1 -> {
player1.getItemInHand(hand).shrink(64);
this.getMainHandItem().setCount(0);
}
);
}
Thanks for reading and choosing our Real Peaceful Mode mod and develop dependent datapacks and mods. Best wishes to your success.