Skip to content

Commit

Permalink
WIP: Basic UI for villager advancement
Browse files Browse the repository at this point in the history
Done:
- Added fisher
- Fixed bug in time-based jobs

TODO:
- Indicate "dining" and "seeking work" in UI
- Remove dirt cheat to open advancement UI
- 3 tiers of gatherer advancement
- Experience and blocks of progress
  • Loading branch information
bradsk88 committed Mar 8, 2024
1 parent c3629fe commit 5f4a15c
Show file tree
Hide file tree
Showing 17 changed files with 359 additions and 15 deletions.
6 changes: 5 additions & 1 deletion src/main/java/ca/bradj/questown/core/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class Config {
public static final ForgeConfigSpec.ConfigValue<Integer> FLAG_SUB_BLOCK_DETECTION_TICKS;
public static final ForgeConfigSpec.ConfigValue<Integer> META_ROOM_DIAMETER;
public static final ForgeConfigSpec.ConfigValue<Integer> GATHERER_TIME_REQUIRED_BASELINE;
public static final ForgeConfigSpec.ConfigValue<Boolean> JOB_BOARD_ENABLED;
public static final ForgeConfigSpec.ConfigValue<Boolean> CRASH_ON_FAILED_WARP;
public static final ForgeConfigSpec.ConfigValue<Integer> TIME_WARP_MAX_TICKS;
public static final ForgeConfigSpec.ConfigValue<Integer> BASE_MAX_LOOP;
Expand Down Expand Up @@ -139,7 +140,10 @@ public class Config {
).defineInRange("SmelterWorkRequired", 10, 1, 10);
GATHERER_TIME_REQUIRED_BASELINE = BUILDER.comment(
"The number of ticks the gatherer/explorer will spend outside of town collecting items. All villagers will start with this baseline, but it might get altered by villager or town modifiers."
).defineInRange("GathererTimeRequiredBaseline", 2000, 1, 24000);
).defineInRange("GathererTimeRequiredBaseline", 200, 1, 24000);
JOB_BOARD_ENABLED = BUILDER.comment(
"Experimental: Villagers will choose work based on the items the player has selected at a \"job board\" registered in the town."
).define("JobBoardEnabled", true);
BUILDER.pop();

// Villagers Config
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ca/bradj/questown/jobs/DeclarativeJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ public boolean hasSpace() {
}

if (wrappingUp && !hasAnyLootToDrop()) {
town.changeJobForVisitor(ownerUUID, WorkSeekerJob.getIDForRoot(jobId));
town.getVillagerHandle().changeJobForVisitor(ownerUUID, WorkSeekerJob.getIDForRoot(jobId), false);
return;
}

Expand Down
1 change: 0 additions & 1 deletion src/main/java/ca/bradj/questown/jobs/JobsRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ public static boolean isDining(JobID jobID) {
return DinerWork.isDining(jobID) || DinerNoTableWork.isDining(jobID);
}


private record Jerb(
ImmutableList<JobID> preferredWork,
ImmutableList<JobID> defaultWork
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/ca/bradj/questown/jobs/Works.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ public static void staticInitialize() {
b.put(ExplorerWork.ID, ExplorerWork::asWork);
b.put(GathererMappedAxeWork.ID, GathererMappedAxeWork::asWork);
b.put(GathererUnmappedAxeWork.ID, GathererUnmappedAxeWork::asWork);
b.put(GathererUnmappedHalfDayAxeWork.ID, GathererUnmappedHalfDayAxeWork::asWork);
b.put(GathererUnmappedFullDayAxeWork.ID, GathererUnmappedFullDayAxeWork::asWork);
b.put(GathererUnmappedPickaxeWork.ID, GathererUnmappedPickaxeWork::asWork);
b.put(GathererUnmappedNoToolWork.ID, GathererUnmappedNoToolWork::asWork);
b.put(GathererUnmappedShovelWork.ID, GathererUnmappedShovelWork::asWork);
b.put(GathererUnmappedRodQuarterDayWork.ID, GathererUnmappedRodQuarterDayWork::asWork);
works = b.build();

works.forEach((id, work) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ protected abstract ImmutableWorkStateContainer<POS, TOWN> getWorkStatuses(

if (workSpot.action() == maxState) {
if (jobBlockState != null && jobBlockState.workLeft() == 0) {
return new WorkOutput<>(tryExtractOre(extra, workSpot.position()), workSpot);
return new WorkOutput<>(tryExtractProduct(extra, workSpot.position()), workSpot);
}
}

Expand Down Expand Up @@ -246,7 +246,7 @@ public Map<Integer, Function<HELD_ITEM, Boolean>> ingredientsRequiredAtStates()
return ingredientsRequiredAtStates;
}

protected TOWN tryExtractOre(
protected TOWN tryExtractProduct(
@NotNull EXTRA inputs,
POS position
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ca.bradj.questown.jobs.declarative;

import ca.bradj.questown.core.Config;
import ca.bradj.questown.integration.minecraft.MCHeldItem;
import ca.bradj.questown.jobs.DeclarativeJob;
import ca.bradj.questown.jobs.ExpirationRules;
Expand Down Expand Up @@ -74,7 +75,10 @@ public static boolean isSeekingWork(JobID s) {
}

public static JobID getIDForRoot(JobID j) {
return newIDForRoot(j.rootId());
if (Config.JOB_BOARD_ENABLED.get()) {
return newIDForRoot(j.rootId());
}
return j;
}

public static JobID newIDForRoot(String jobName) {
Expand Down Expand Up @@ -109,7 +113,7 @@ public static JobID newIDForRoot(String jobName) {
) {

@Override
protected Boolean tryExtractOre(
protected Boolean tryExtractProduct(
MCExtra extra,
BlockPos position
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public GathererMappedAxeWork(
public static Work asWork() {
return NewLeaverWork.asWork(
ID,
GathererUnmappedAxeWork.ID,
GathererUnmappedFullDayAxeWork.ID,
Items.DIAMOND_AXE.getDefaultInstance(),
GathererTools.AXE_LOOT_TABLE_PREFIX,
Items.OAK_WOOD.getDefaultInstance(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ public class GathererUnmappedAxeWork extends NewLeaverWork {
public static final ImmutableMap<Integer, Integer> WORK_REQUIRED_AT_STATES = ImmutableMap.of(
// No work required
);
private static final boolean TIMER_SHARING = false;
public static final ImmutableMap<ProductionStatus, String> SPECIAL_RULES = ImmutableMap.of(
ProductionStatus.fromJobBlockStatus(BLOCK_STATE_NEED_ROAM), SpecialRules.REMOVE_FROM_WORLD,
ProductionStatus.FACTORY.waitingForTimedState(), SpecialRules.REMOVE_FROM_WORLD
Expand All @@ -60,7 +59,7 @@ public GathererUnmappedAxeWork() {
public static Work asWork() {
return NewLeaverWork.asWork(
ID,
GathererUnmappedNoToolWork.ID,
GathererUnmappedNoToolWork.ID, // Parent
Items.STONE_AXE.getDefaultInstance(),
GathererTools.AXE_LOOT_TABLE_PREFIX,
Items.OAK_WOOD.getDefaultInstance(),
Expand All @@ -85,8 +84,13 @@ private static Iterable<MCHeldItem> getFromLootTables(
ServerLevel level,
Collection<MCHeldItem> items
) {
return Loots.getFromLootTables(level, items, new GathererTools.LootTableParameters(
GathererTools.AXE_LOOT_TABLE_PREFIX, GathererTools.AXE_LOOT_TABLE_DEFAULT
));
return Loots.getFromLootTables(
level,
items,
1,
new GathererTools.LootTableParameters(
GathererTools.AXE_LOOT_TABLE_PREFIX, GathererTools.AXE_LOOT_TABLE_DEFAULT
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package ca.bradj.questown.jobs.gatherer;

import ca.bradj.questown.core.Config;
import ca.bradj.questown.core.init.TagsInit;
import ca.bradj.questown.integration.minecraft.MCHeldItem;
import ca.bradj.questown.jobs.JobID;
import ca.bradj.questown.jobs.SpecialRules;
import ca.bradj.questown.jobs.Work;
import ca.bradj.questown.jobs.production.ProductionStatus;
import ca.bradj.questown.mc.Util;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;

import java.util.Collection;

public class GathererUnmappedFullDayAxeWork extends NewLeaverWork {

private static final GathererTools.LootTableParameters PARAMS = new GathererTools.LootTableParameters(
GathererTools.AXE_LOOT_TABLE_PREFIX,
GathererTools.AXE_LOOT_TABLE_DEFAULT
);

static {
allParameters.add(PARAMS);
}

public static final JobID ID = new JobID("gatherer", "axe_full_day");

public static final int BLOCK_STATE_NEED_FOOD = 0;
public static final int BLOCK_STATE_NEED_TOOL = 1;
public static final int BLOCK_STATE_NEED_ROAM = 2;
public static final int BLOCK_STATE_DONE = 3;

public static final int MAX_STATE = BLOCK_STATE_DONE;

public static final ImmutableMap<Integer, Ingredient> INGREDIENTS_REQUIRED_AT_STATES = ImmutableMap.of(
BLOCK_STATE_NEED_FOOD, Ingredient.of(TagsInit.Items.VILLAGER_FOOD)
);
public static final ImmutableMap<Integer, Integer> INGREDIENT_QTY_REQUIRED_AT_STATES = ImmutableMap.of(
BLOCK_STATE_NEED_FOOD, 3
);
public static final ImmutableMap<Integer, Ingredient> TOOLS_REQUIRED_AT_STATES = ImmutableMap.of(
BLOCK_STATE_NEED_TOOL, Ingredient.of(TagsInit.Items.AXES)
);
public static final ImmutableMap<Integer, Integer> WORK_REQUIRED_AT_STATES = ImmutableMap.of(
// No work required
);
public static final ImmutableMap<ProductionStatus, String> SPECIAL_RULES = ImmutableMap.of(
ProductionStatus.fromJobBlockStatus(BLOCK_STATE_NEED_ROAM), SpecialRules.REMOVE_FROM_WORLD,
ProductionStatus.FACTORY.waitingForTimedState(), SpecialRules.REMOVE_FROM_WORLD
);

public GathererUnmappedFullDayAxeWork() {
super(PARAMS);
}

public static Work asWork() {
return NewLeaverWork.asWork(
ID,
GathererUnmappedHalfDayAxeWork.ID, // Parent
Items.GOLDEN_AXE.getDefaultInstance(),
GathererTools.AXE_LOOT_TABLE_PREFIX,
Items.OAK_WOOD.getDefaultInstance(),
MAX_STATE,
Util.constant(INGREDIENTS_REQUIRED_AT_STATES),
Util.constant(INGREDIENT_QTY_REQUIRED_AT_STATES),
Util.constant(TOOLS_REQUIRED_AT_STATES),
Util.constant(WORK_REQUIRED_AT_STATES),
ImmutableMap.of(
BLOCK_STATE_NEED_ROAM, () -> Config.GATHERER_TIME_REQUIRED_BASELINE.get() * 3
),
SPECIAL_RULES,
GathererUnmappedFullDayAxeWork::getFromLootTables
);
}

// Note: this is still declarative. In a file, we would just specify something like:
// - Strategy: "loot_tables"
// - Prefix: "jobs/axe"
// - Default "jobs/axe/default"
private static Iterable<MCHeldItem> getFromLootTables(
ServerLevel level,
Collection<MCHeldItem> items
) {
return Loots.getFromLootTables(
level,
items,
6,
new GathererTools.LootTableParameters(
GathererTools.AXE_LOOT_TABLE_PREFIX, GathererTools.AXE_LOOT_TABLE_DEFAULT
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package ca.bradj.questown.jobs.gatherer;

import ca.bradj.questown.core.Config;
import ca.bradj.questown.core.init.TagsInit;
import ca.bradj.questown.integration.minecraft.MCHeldItem;
import ca.bradj.questown.jobs.JobID;
import ca.bradj.questown.jobs.SpecialRules;
import ca.bradj.questown.jobs.Work;
import ca.bradj.questown.jobs.production.ProductionStatus;
import ca.bradj.questown.mc.Util;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;

import java.util.Collection;

public class GathererUnmappedHalfDayAxeWork extends NewLeaverWork {

private static final GathererTools.LootTableParameters PARAMS = new GathererTools.LootTableParameters(
GathererTools.AXE_LOOT_TABLE_PREFIX,
GathererTools.AXE_LOOT_TABLE_DEFAULT
);

static {
allParameters.add(PARAMS);
}

public static final JobID ID = new JobID("gatherer", "axe_half_day");

public static final int BLOCK_STATE_NEED_FOOD = 0;
public static final int BLOCK_STATE_NEED_TOOL = 1;
public static final int BLOCK_STATE_NEED_ROAM = 2;
public static final int BLOCK_STATE_DONE = 3;

public static final int MAX_STATE = BLOCK_STATE_DONE;

public static final ImmutableMap<Integer, Ingredient> INGREDIENTS_REQUIRED_AT_STATES = ImmutableMap.of(
BLOCK_STATE_NEED_FOOD, Ingredient.of(TagsInit.Items.VILLAGER_FOOD)
);
public static final ImmutableMap<Integer, Integer> INGREDIENT_QTY_REQUIRED_AT_STATES = ImmutableMap.of(
BLOCK_STATE_NEED_FOOD, 2
);
public static final ImmutableMap<Integer, Ingredient> TOOLS_REQUIRED_AT_STATES = ImmutableMap.of(
BLOCK_STATE_NEED_TOOL, Ingredient.of(TagsInit.Items.AXES)
);
public static final ImmutableMap<Integer, Integer> WORK_REQUIRED_AT_STATES = ImmutableMap.of(
// No work required
);
public static final ImmutableMap<ProductionStatus, String> SPECIAL_RULES = ImmutableMap.of(
ProductionStatus.fromJobBlockStatus(BLOCK_STATE_NEED_ROAM), SpecialRules.REMOVE_FROM_WORLD,
ProductionStatus.FACTORY.waitingForTimedState(), SpecialRules.REMOVE_FROM_WORLD
);

public GathererUnmappedHalfDayAxeWork() {
super(PARAMS);
}

public static Work asWork() {
return NewLeaverWork.asWork(
ID,
GathererUnmappedAxeWork.ID, // Parent
Items.IRON_AXE.getDefaultInstance(),
GathererTools.AXE_LOOT_TABLE_PREFIX,
Items.OAK_WOOD.getDefaultInstance(),
MAX_STATE,
Util.constant(INGREDIENTS_REQUIRED_AT_STATES),
Util.constant(INGREDIENT_QTY_REQUIRED_AT_STATES),
Util.constant(TOOLS_REQUIRED_AT_STATES),
Util.constant(WORK_REQUIRED_AT_STATES),
ImmutableMap.of(
BLOCK_STATE_NEED_ROAM, () -> Config.GATHERER_TIME_REQUIRED_BASELINE.get() * 2
),
SPECIAL_RULES,
GathererUnmappedHalfDayAxeWork::getFromLootTables
);
}

// Note: this is still declarative. In a file, we would just specify something like:
// - Strategy: "loot_tables"
// - Prefix: "jobs/axe"
// - Default "jobs/axe/default"
private static Iterable<MCHeldItem> getFromLootTables(
ServerLevel level,
Collection<MCHeldItem> items
) {
return Loots.getFromLootTables(
level,
items,
3,
new GathererTools.LootTableParameters(
GathererTools.AXE_LOOT_TABLE_PREFIX, GathererTools.AXE_LOOT_TABLE_DEFAULT
)
);
}
}
Loading

0 comments on commit 5f4a15c

Please sign in to comment.