Skip to content

Commit

Permalink
feat: Smelter upgrade (#1286)
Browse files Browse the repository at this point in the history
* solve #1276

* solve #1278

* removed outdated information

* more ae2 dust compat

* soul gem blacklist use bosses tag

* smelter upgrade

* smelter warning
  • Loading branch information
Eqis-Edu authored Jan 13, 2025
1 parent 54ad4b3 commit 44d8902
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/generated/resources/assets/occultism/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_otherworld_sapling_trader.intro.title": "Otherworld Sapling Trader",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_otherworld_sapling_trader.name": "Summon Otherworld Sapling Trader",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_otherworld_sapling_trader.trade.text": "To trade, drop your offered item next to the trader, he will pick it up and drop the exchanged item.\n",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_smelter_t1.about_smelters.text": "Smelter spirits are summoned to do furnace process, without using fuel. They will pick up appropriate items and drop the resulting into the world. A fire particle effect and a flame sound indicate the smelter is at work.\n",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_smelter_t1.about_smelters.text": "Smelter spirits are summoned to do furnace, blast furnace, smoker and campfire process, without using fuel. They will pick up appropriate items and drop the resulting into the world. A fire particle effect and a flame sound indicate the smelter is at work.\n",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_smelter_t1.about_smelters.title": "Smelter Spirits",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_smelter_t1.automation.text": "To ease automation, try summoning a [Transporter Spirit](entry://occultism:dictionary_of_spirits/summoning_rituals/summon_transport_items)\nto place items from chests in the smelter's inventory, and a [Janitor Spirit](entry://occultism:dictionary_of_spirits/summoning_rituals/summon_cleaner) to collect the processed items.\n",
"book.occultism.dictionary_of_spirits.summoning_rituals.summon_smelter_t1.automation.title": "Automation",
Expand Down
147 changes: 108 additions & 39 deletions src/main/java/com/klikli_dev/occultism/common/entity/job/SmelterJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class SmelterJob extends SpiritJob {

Expand All @@ -60,6 +59,9 @@ public class SmelterJob extends SpiritJob {
protected Supplier<Integer> tier;

protected Optional<RecipeHolder<SmeltingRecipe>> currentRecipe = Optional.empty();
protected Optional<RecipeHolder<BlastingRecipe>> currentRecipeBlast = Optional.empty();
protected Optional<RecipeHolder<SmokingRecipe>> currentRecipeSmoke = Optional.empty();
protected Optional<RecipeHolder<CampfireCookingRecipe>> currentRecipeCamp = Optional.empty();
protected PickupItemsGoal pickupItemsGoal;

protected List<Ingredient> itemsToPickUp = new ArrayList<>();
Expand All @@ -73,8 +75,14 @@ public SmelterJob(SpiritEntity entity, Supplier<Float> smeltingTimeMultiplier) {
@Override
public void onInit() {
this.entity.targetSelector.addGoal(1, this.pickupItemsGoal = new PickupItemsGoal(this.entity));
this.itemsToPickUp = this.entity.level().getRecipeManager().getAllRecipesFor(RecipeType.SMELTING).stream()
.flatMap(recipe -> recipe.value().getIngredients().stream()).collect(Collectors.toList());
this.itemsToPickUp.addAll(this.entity.level().getRecipeManager().getAllRecipesFor(RecipeType.SMELTING).stream()
.flatMap(recipe -> recipe.value().getIngredients().stream()).toList());
this.itemsToPickUp.addAll(this.entity.level().getRecipeManager().getAllRecipesFor(RecipeType.BLASTING).stream()
.flatMap(recipe -> recipe.value().getIngredients().stream()).toList());
this.itemsToPickUp.addAll(this.entity.level().getRecipeManager().getAllRecipesFor(RecipeType.SMOKING).stream()
.flatMap(recipe -> recipe.value().getIngredients().stream()).toList());
this.itemsToPickUp.addAll(this.entity.level().getRecipeManager().getAllRecipesFor(RecipeType.CAMPFIRE_COOKING).stream()
.flatMap(recipe -> recipe.value().getIngredients().stream()).toList());
}

@Override
Expand All @@ -87,12 +95,28 @@ public void update() {
ItemStack handHeld = this.entity.getItemInHand(InteractionHand.MAIN_HAND);
var recipeInput = new SingleRecipeInput(handHeld);

if (!this.currentRecipe.isPresent() && !handHeld.isEmpty()) {
if (!handHeld.isEmpty() && this.currentRecipe.isEmpty()
&& this.currentRecipeBlast.isEmpty()
&& this.currentRecipeSmoke.isEmpty()
&& this.currentRecipeCamp.isEmpty()) {

this.currentRecipe = this.entity.level().getRecipeManager().getRecipeFor(RecipeType.SMELTING,
recipeInput, this.entity.level());
if (this.currentRecipe.isEmpty()) {
this.currentRecipeBlast = this.entity.level().getRecipeManager().getRecipeFor(RecipeType.BLASTING,
recipeInput, this.entity.level());
if (this.currentRecipeBlast.isEmpty()) {
this.currentRecipeSmoke = this.entity.level().getRecipeManager().getRecipeFor(RecipeType.SMOKING,
recipeInput, this.entity.level());
if (this.currentRecipeSmoke.isEmpty()) {
this.currentRecipeCamp = this.entity.level().getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING,
recipeInput, this.entity.level());
}
}
}
this.smeltingTimer = 0;

if (this.currentRecipe.isPresent()) {
if (this.currentRecipe.isPresent() || this.currentRecipeBlast.isPresent() || this.currentRecipeSmoke.isPresent() || this.currentRecipeCamp.isPresent()) {
//play smelting sound
this.entity.level()
.playSound(null, this.entity.blockPosition(), SoundEvents.FIRE_AMBIENT, SoundSource.NEUTRAL, 1f,
Expand All @@ -111,50 +135,95 @@ public void update() {
//Reset cached recipe if it no longer matches
this.currentRecipe = Optional.empty();
} else {
//advance conversion
this.smeltingTimer++;

//show particle effect while smelting
if (this.entity.level().getGameTime() % 10 == 0) {
Vec3 pos = this.entity.position();
((ServerLevel) this.entity.level())
.sendParticles(ParticleTypes.FLAME, pos.x + this.entity.level().random.nextGaussian() / 3,
pos.y + 0.5, pos.z + this.entity.level().random.nextGaussian() / 3, 1, 0.0, 0.0, 0.0,
0.0);
}

//every two seconds, play another smelting sound
if (this.smeltingTimer % 40 == 0) {
this.entity.level().playSound(null, this.entity.blockPosition(), SoundEvents.FIRE_AMBIENT,
SoundSource.NEUTRAL, 1f,
1 + 0.5f * this.entity.getRandom().nextFloat());
}

commomTick();
if (this.smeltingTimer >= this.currentRecipe.get().value().getCookingTime() * this.smeltingTimeMultiplier.get()) {
this.smeltingTimer = 0;

ItemStack result = this.currentRecipe.get().value().assemble(recipeInput, this.entity.level().registryAccess());
result.setCount((int) (result.getCount()));
ItemStack inputCopy = handHeld.copy();
inputCopy.setCount(1);
handHeld.shrink(1);

this.onSmelt(inputCopy, result);
var event = new SmelterJobEvent(this.entity, inputCopy, result);
NeoForge.EVENT_BUS.post(event);
if(!event.getResult().isEmpty()) {
ItemEntity droppedItem = this.entity.spawnAtLocation(event.getResult());
if (droppedItem != null) {
droppedItem.addTag(DROPPED_BY_SMELTER);
}
}
commonFinish(handHeld, result);
//Don't reset recipe here, keep it cached
}
}
} else if (this.currentRecipeBlast.isPresent()) {
if (handHeld.isEmpty() || !this.currentRecipeBlast.get().value().matches(recipeInput, this.entity.level())) {
//Reset cached recipe if it no longer matches
this.currentRecipeBlast = Optional.empty();
} else {
commomTick();
if (this.smeltingTimer >= this.currentRecipeBlast.get().value().getCookingTime() * this.smeltingTimeMultiplier.get()) {
this.smeltingTimer = 0;
ItemStack result = this.currentRecipeBlast.get().value().assemble(recipeInput, this.entity.level().registryAccess());
commonFinish(handHeld, result);
//Don't reset recipe here, keep it cached
}
}
} else if (this.currentRecipeSmoke.isPresent()) {
if (handHeld.isEmpty() || !this.currentRecipeSmoke.get().value().matches(recipeInput, this.entity.level())) {
//Reset cached recipe if it no longer matches
this.currentRecipeSmoke = Optional.empty();
} else {
commomTick();
if (this.smeltingTimer >= this.currentRecipeSmoke.get().value().getCookingTime() * this.smeltingTimeMultiplier.get()) {
this.smeltingTimer = 0;
ItemStack result = this.currentRecipeSmoke.get().value().assemble(recipeInput, this.entity.level().registryAccess());
commonFinish(handHeld, result);
//Don't reset recipe here, keep it cached
}
}
} else if (this.currentRecipeCamp.isPresent()) {
if (handHeld.isEmpty() || !this.currentRecipeCamp.get().value().matches(recipeInput, this.entity.level())) {
//Reset cached recipe if it no longer matches
this.currentRecipeCamp = Optional.empty();
} else {
commomTick();
if (this.smeltingTimer >= this.currentRecipeCamp.get().value().getCookingTime() * this.smeltingTimeMultiplier.get()) {
this.smeltingTimer = 0;
ItemStack result = this.currentRecipeCamp.get().value().assemble(recipeInput, this.entity.level().registryAccess());
commonFinish(handHeld, result);
//Don't reset recipe here, keep it cached
}
}
}
super.update();
}

private void commomTick(){
//advance conversion
this.smeltingTimer++;

//show particle effect while smelting
if (this.entity.level().getGameTime() % 10 == 0) {
Vec3 pos = this.entity.position();
((ServerLevel) this.entity.level())
.sendParticles(ParticleTypes.FLAME, pos.x + this.entity.level().random.nextGaussian() / 3,
pos.y + 0.5, pos.z + this.entity.level().random.nextGaussian() / 3, 1, 0.0, 0.0, 0.0,
0.0);
}

//every two seconds, play another smelting sound
if (this.smeltingTimer % 40 == 0) {
this.entity.level().playSound(null, this.entity.blockPosition(), SoundEvents.FIRE_AMBIENT,
SoundSource.NEUTRAL, 1f,
1 + 0.5f * this.entity.getRandom().nextFloat());
}
}

private void commonFinish(ItemStack handHeld, ItemStack result){
result.setCount((result.getCount()));
ItemStack inputCopy = handHeld.copy();
inputCopy.setCount(1);
handHeld.shrink(1);

this.onSmelt(inputCopy, result);
var event = new SmelterJobEvent(this.entity, inputCopy, result);
NeoForge.EVENT_BUS.post(event);
if(!event.getResult().isEmpty()) {
ItemEntity droppedItem = this.entity.spawnAtLocation(event.getResult());
if (droppedItem != null) {
droppedItem.addTag(DROPPED_BY_SMELTER);
}
}
}

@Override
public CompoundTag writeJobToNBT(CompoundTag compound, HolderLookup.Provider provider) {
compound.putInt("conversionTimer", this.smeltingTimer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ private BookEntryModel makeSummonSmelterT1Entry(CategoryEntryMap entryMap, char
this.lang().add(this.context().pageTitle(), "Smelter Spirits");
this.lang().add(this.context().pageText(),
"""
Smelter spirits are summoned to do furnace process, without using fuel. They will pick up appropriate items and drop the resulting into the world. A fire particle effect and a flame sound indicate the smelter is at work.
Smelter spirits are summoned to do furnace, blast furnace, smoker and campfire process, without using fuel. They will pick up appropriate items and drop the resulting into the world. A fire particle effect and a flame sound indicate the smelter is at work.
""");

this.context().page("automation");
Expand Down

0 comments on commit 44d8902

Please sign in to comment.