Skip to content
Merged
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
61 changes: 28 additions & 33 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

1.20.1-1.5.1c
1.20.1-1.5.1d

[✅] Done and tested
[🟡] Partially done and/or needs testing
Expand All @@ -8,26 +8,8 @@

Balance
-------
[✅] Bee lifespan increased from 20s to 30s
[✅] Ice Wand mana cost reduced from 35 to 25 and duration increased from 12s to 15s
[✅] Totem of Shielding no longer deflects you or allies' projectiles

[✅] Hero's Armour healing changed from 10x12hp to 8x15hp
[🟡] Mace slam now deals full damage to buildings

[✅] Pumpkin farm cost increased from 175 wood to 200 wood
[✅] Raise Dead zombies now give experience on death
[✅] Raise Dead zombie lifespan increased from 60s to 75s, but now die instantly instead of decaying
[✅] Ice blocks created by Blizzard and Ice Wand no longer block line of sight or projectiles
[✅] Creeper movement speed reduced from 28 to 27
[✅] Creeper cost changed from (50 food, 100 ore) to (40 food, 120 ore)
[✅] Spiders now have +50% bonus damage to workers
[✅] Spider daytime slowness reduced from -36% to -20%
[✅] Spider daytime sight range reduced from 16 to 14 (night is still 20)

[✅] The Wildfire's passive now grants +0.1 health and mana regen per nearby unit that's on fire
[✅] The default piglin scout is now a Baby Hoglin, and is equivalent to Scout Cats & Dogs
- You can still switch to training Striders at any time



Quality of Life
---------------
Expand All @@ -43,21 +25,34 @@ Quality of Life
[❌] Commands to modify it in memory
[❌] Save as .dat file separately so we can retain modifications

[✅] You can now use Ctrl+QWER to level up a skill
[✅] Fixed bats not being able to use portals
[🟡] Stopped sending a lot of unnecessary data about entities in fog
[🟡] Spectators and defeated players can now see fog of war from the perspective of all match players
Map Pack 2.2a

Download: https://drive.google.com/file/d/1nST78mPb42F8TWFcDB_pcBLeeOM9Uyn6/view

- Summoner's Rift is now credited to Shrinkiroo
- Fixed sandbox mode being set for some maps
- Fixed the rtsmap.json version numbers and incorrect labels
- Throne's Path:
- Neutral armies no longer spawn until 10mins after match start
- Player units no longer get removed at the corners of the map

[✅] You can now set a rally point on iron golem buildings
[✅] Farms now have a button to assign the nearest idle worker to them
- Wheat farms prioritise farmers and non-profession villagers
[✅] Spectators can now toggle fog of war for themselves
[✅] Dead coral blocks now convert to basalt


Bugfixes
--------
[✅] Fixed the enchanter tether being rendered in fog
[✅] Fixed enchanter tether not reducing damage taken
[✅] Fixed neutral and enemy buildings not building at fast speeds in sandbox
[✅] FPV players and explosions can no longer break blocks of invulnerable buildings
[✅] Bats can now use transport portals
[✅] Fixed wraith snow from Strays sometimes affecting allies
[✅] Fixed chickens sometimes spawning inside walls
[✅] The Wretched Wraith's snow no longer breaks portal blocks
[✅] Spiders no longer get stuck on overhangs like on the spider cave structure
[✅] Reduced the occurrence of missing chunks in fog of war when render distance is low
[✅] Bees can now be produced in custom buildings
[✅] Food can now be sold at custom item shops
[✅] Chickens now render at much further distances while in RTS camera
[✅] Animals no longer path into water, swim much faster and will try to go back to land if they are in water


Languages
---------
[✅] fr_fr update by EnderBreaker
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ apply plugin: 'maven-publish'
apply plugin: 'org.spongepowered.mixin'
apply plugin: 'org.parchmentmc.librarian.forgegradle'

version = '1.5.1c'
version = '1.5.1d'
group = 'com.solegendary.reignofnether' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'reignofnether'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
public class ReignOfNether {
public static final Logger LOGGER = LogManager.getLogger();
public static final String MOD_ID = "reignofnether";
public static final String VERSION_STRING = "1.5.1c";
public static final String VERSION_STRING = "1.5.1d";

// Fields from ClientReset
public static final Field handshakeField;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.solegendary.reignofnether.ability.abilities;

import com.solegendary.reignofnether.ability.Ability;
import com.solegendary.reignofnether.building.BuildingClientEvents;
import com.solegendary.reignofnether.building.BuildingPlacement;
import com.solegendary.reignofnether.building.buildings.placements.FarmPlacement;
import com.solegendary.reignofnether.hud.HudClientEvents;
import com.solegendary.reignofnether.hud.HudClientboundPacket;
import com.solegendary.reignofnether.hud.buttons.AbilityButton;
import com.solegendary.reignofnether.keybinds.Keybinding;
import com.solegendary.reignofnether.keybinds.Keybindings;
import com.solegendary.reignofnether.unit.Relationship;
import com.solegendary.reignofnether.unit.UnitAction;
import com.solegendary.reignofnether.unit.UnitClientEvents;
import com.solegendary.reignofnether.util.LanguageUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;

import java.util.ArrayList;
import java.util.List;

import static com.solegendary.reignofnether.building.BuildingClientEvents.getPlayerToBuildingRelationship;
import static com.solegendary.reignofnether.unit.UnitClientEvents.sendUnitCommand;
import static com.solegendary.reignofnether.util.MiscUtil.fcs;

// assigns the nearest idle worker to each selected farm that has no worker (one worker per farm)
public class AssignWorker extends Ability {

public AssignWorker() {
super(
UnitAction.ASSIGN_WORKER,
0,
0,
0,
false,
false
);
this.defaultHotkey = Keybindings.abilitySlot1;
}

@Override
public AbilityButton getButton(Keybinding hotkey, BuildingPlacement placement) {
return new AbilityButton(
"Assign Worker",
ResourceLocation.fromNamespaceAndPath("minecraft", "textures/item/iron_hoe.png"),
hotkey,
() -> false,
() -> false,
() -> HudClientEvents.hudSelectedPlacement instanceof FarmPlacement farm && farm.isBuilt && !farm.hasWorker(),
() -> sendUnitCommand(UnitAction.ASSIGN_WORKER),
null,
List.of(
fcs(LanguageUtil.getTranslation("abilities.reignofnether.assign_worker"), true),
fcs(""),
fcs(LanguageUtil.getTranslation("abilities.reignofnether.assign_worker.tooltip1"))
),
this,
placement
);
}

// the worker is only picked serverside so that idleness and distances are authoritative (clients are synced via
// UnitSyncWorkerClientBoundPacket); clientside we just move the HUD on so the button can be pressed for the next farm
@Override
public void use(Level level, BuildingPlacement buildingUsing, BlockPos targetBp) {
if (level.isClientSide())
selectNextEmptyFarm(buildingUsing);
else if (buildingUsing instanceof FarmPlacement farm)
farm.assignNearestIdleWorker();
}

// next selected farm (in selection order, wrapping) without a worker, other than the one just used
private static void selectNextEmptyFarm(BuildingPlacement current) {
List<BuildingPlacement> selected = BuildingClientEvents.getSelectedBuildings();
int start = selected.indexOf(current);
for (int i = 1; i <= selected.size(); i++) {
BuildingPlacement bpl = selected.get(Math.floorMod(start + i, selected.size()));
if (bpl != current && bpl instanceof FarmPlacement farm && farm.isBuilt && !farm.hasWorker() &&
getPlayerToBuildingRelationship(farm) == Relationship.OWNED) {
HudClientEvents.hudSelectedPlacement = farm;
return;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public static boolean canPlaceSnow(Level level, BlockPos pos) {
!(bsBelow.getBlock() instanceof TrapDoorBlock) &&
!(bsBelow.getBlock() instanceof SculkSensorBlock) &&
!(bs.getBlock() instanceof SkullBlock) &&
!(bs.getBlock() instanceof NetherPortalBlock) &&
(!BuildingUtils.isPosInsideAnyBuilding(level.isClientSide(), pos.below()) || !(bs.getBlock() instanceof BushBlock)) &&
(!BuildingUtils.isPosInsideFarm(level.isClientSide(), pos.below()) || bsBelow.getBlock().getDescriptionId().contains("_log"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,20 @@
import com.solegendary.reignofnether.building.Building;
import com.solegendary.reignofnether.building.BuildingBlock;
import com.solegendary.reignofnether.building.BuildingPlacement;
import com.solegendary.reignofnether.building.buildings.monsters.PumpkinFarm;
import com.solegendary.reignofnether.building.buildings.piglins.NetherwartFarm;
import com.solegendary.reignofnether.building.buildings.villagers.WheatFarm;
import com.solegendary.reignofnether.resources.ResourceCost;
import com.solegendary.reignofnether.resources.ResourceName;
import com.solegendary.reignofnether.unit.UnitClientEvents;
import com.solegendary.reignofnether.unit.UnitServerEvents;
import com.solegendary.reignofnether.unit.goals.GatherResourcesGoal;
import com.solegendary.reignofnether.unit.interfaces.Unit;
import com.solegendary.reignofnether.unit.interfaces.WorkerUnit;
import com.solegendary.reignofnether.unit.units.monsters.ZombieVillagerUnit;
import com.solegendary.reignofnether.unit.units.piglins.GruntUnit;
import com.solegendary.reignofnether.unit.units.villagers.VillagerUnit;
import com.solegendary.reignofnether.unit.units.villagers.VillagerUnitProfession;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
Expand Down Expand Up @@ -61,14 +72,72 @@ public FarmPlacement(Building building, Level level, BlockPos originPos, Rotatio

@Nullable
private WorkerUnit getWorker() {
for (LivingEntity le : UnitServerEvents.getAllUnits()) {
List<LivingEntity> units = level.isClientSide() ?
new ArrayList<>(UnitClientEvents.getAllUnits()) : UnitServerEvents.getAllUnits();
for (LivingEntity le : units) {
if (le instanceof WorkerUnit workerUnit && workerUnit.getGatherResourceGoal().getTargetFarm() == this) {
return workerUnit;
}
}
return null;
}

public boolean hasWorker() {
return getWorker() != null;
}

// each farm type can only call for workers of its own faction
private boolean isWorkerOfFarmFaction(WorkerUnit worker) {
if (getBuilding() instanceof WheatFarm)
return worker instanceof VillagerUnit;
if (getBuilding() instanceof PumpkinFarm)
return worker instanceof ZombieVillagerUnit;
if (getBuilding() instanceof NetherwartFarm)
return worker instanceof GruntUnit;
return true;
}

// lower is better; wheat farms prefer veteran farmers, then farmers, then no profession, then any other profession
private int getWorkerPriority(WorkerUnit worker) {
if (!(worker instanceof VillagerUnit villager) || !(getBuilding() instanceof WheatFarm))
return 0;
VillagerUnitProfession profession = villager.getUnitProfession();
if (profession == VillagerUnitProfession.FARMER)
return villager.isVeteran() ? 0 : 1;
return profession == VillagerUnitProfession.NONE ? 2 : 3;
}

// serverside only: picks the best idle worker by priority, then by distance
public void assignNearestIdleWorker() {
if (level.isClientSide() || !isBuilt || hasWorker())
return;

WorkerUnit nearest = null;
int nearestPriority = Integer.MAX_VALUE;
double nearestDist = Double.MAX_VALUE;
for (LivingEntity le : UnitServerEvents.getAllUnits()) {
if (le instanceof WorkerUnit worker && le instanceof Unit unit && unit.getOwnerName().equals(ownerName) &&
le.level() == level && isWorkerOfFarmFaction(worker) && WorkerUnit.isIdle(worker)) {
int priority = getWorkerPriority(worker);
double dist = le.distanceToSqr(centrePos.getCenter());
if (priority < nearestPriority || (priority == nearestPriority && dist < nearestDist)) {
nearest = worker;
nearestPriority = priority;
nearestDist = dist;
}
}
}
if (nearest == null)
return;

GatherResourcesGoal goal = nearest.getGatherResourceGoal();
goal.setTargetResourceName(ResourceName.FOOD);
goal.setMoveTarget(centrePos);
goal.setTargetFarm(this);
if (Unit.atMaxResources((Unit) nearest))
goal.saveAndReturnResources();
}

// tick crop growth here to have precise control over growth speed with no RNG
private void tickCrops() {
for (FarmCropBlock farmBlock : farmBlocks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ else if (rallyPointEntity != null)
return entity;
}

protected void setDelayedRally(Unit unit) {
public void setDelayedRally(Unit unit) {
Entity entity = (Entity) unit;
LivingEntity rallyEntity = getRallyPointEntity();
BlockPos defaultRallyPoint = getDefaultOutdoorSpawnPoint();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import static com.solegendary.reignofnether.building.BuildingUtils.getAbsoluteBlockData;

import com.solegendary.reignofnether.ability.abilities.AssignWorker;
import com.solegendary.reignofnether.building.Building;
import com.solegendary.reignofnether.building.BuildingPlacement;
import com.solegendary.reignofnether.building.buildings.placements.FarmPlacement;
import com.solegendary.reignofnether.keybinds.Keybindings;
import com.solegendary.reignofnether.resources.ResourceCost;

import net.minecraft.core.BlockPos;
Expand All @@ -15,6 +17,8 @@ public abstract class AbstractFarm extends Building {
public AbstractFarm(String structureName, ResourceCost cost, boolean isCapitol) {
super(structureName, cost, isCapitol);
this.maxHealth = 65d;

this.abilities.add(new AssignWorker(), Keybindings.abilitySlot1);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@
import com.solegendary.reignofnether.building.BuildingPlaceButton;
import com.solegendary.reignofnether.building.BuildingPlacement;
import com.solegendary.reignofnether.building.Buildings;
import com.solegendary.reignofnether.building.buildings.placements.ProductionPlacement;
import com.solegendary.reignofnether.building.production.ProductionBuilding;
import com.solegendary.reignofnether.building.production.ProductionItems;
import com.solegendary.reignofnether.keybinds.Keybinding;
import com.solegendary.reignofnether.registrars.EntityRegistrar;
import com.solegendary.reignofnether.research.ResearchClient;
import com.solegendary.reignofnether.resources.ResourceCost;
import com.solegendary.reignofnether.resources.ResourceCosts;
import com.solegendary.reignofnether.tutorial.TutorialClientEvents;
import com.solegendary.reignofnether.unit.UnitAction;
import com.solegendary.reignofnether.unit.UnitServerEvents;
import com.solegendary.reignofnether.unit.interfaces.Unit;
import com.solegendary.reignofnether.unit.units.villagers.IronGolemProd;

import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
Expand All @@ -26,9 +31,12 @@
import net.minecraft.world.level.block.Blocks;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import static com.solegendary.reignofnether.util.MiscUtil.fcs;

public class IronGolemBuilding extends Building {
public class IronGolemBuilding extends ProductionBuilding {

public final static String buildingName = "Iron Golem";
public final static String structureName = "iron_golem";
Expand All @@ -45,8 +53,6 @@ public IronGolemBuilding() {
this.startingBlockTypes.add(Blocks.JUNGLE_FENCE);
}



public BuildingPlaceButton getBuildButton(Keybinding hotkey) {
ResourceLocation key = ReignOfNetherRegistries.BUILDING.getKey(this);
String name = key != null ? Component.translatable("buildings." + getFaction().getName() + "." + key.getNamespace() + "." + key.getPath()).getString() : buildingName;
Expand Down Expand Up @@ -85,6 +91,8 @@ public void onBuilt(BuildingPlacement placement) {
);
if (entity instanceof Unit unit) {
unit.setOwnerName(placement.ownerName);
if (placement instanceof ProductionPlacement pp)
pp.setDelayedRally(unit);
}
}
}
Expand Down
Loading
Loading