Make bat ponies nocturnal. #108

This commit is contained in:
Sollace 2023-04-30 01:41:21 +01:00
parent 1d13b5c04a
commit ffae9b96a7
7 changed files with 40 additions and 38 deletions

View file

@ -22,18 +22,18 @@ import net.minecraft.util.Identifier;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
public final class Race implements Affine { public record Race (boolean canCast, FlightType flightType, boolean canUseEarth, boolean isNocturnal) implements Affine {
public static final String DEFAULT_ID = "unicopia:unset"; public static final String DEFAULT_ID = "unicopia:unset";
public static final Registry<Race> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race"), DEFAULT_ID); public static final Registry<Race> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race"), DEFAULT_ID);
public static final RegistryKey<? extends Registry<Race>> REGISTRY_KEY = REGISTRY.getKey(); public static final RegistryKey<? extends Registry<Race>> REGISTRY_KEY = REGISTRY.getKey();
private static final DynamicCommandExceptionType UNKNOWN_RACE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("race.unknown", id)); private static final DynamicCommandExceptionType UNKNOWN_RACE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("race.unknown", id));
public static Race register(String name, boolean magic, FlightType flight, boolean earth) { public static Race register(String name, boolean magic, FlightType flight, boolean earth, boolean nocturnal) {
return register(Unicopia.id(name), magic, flight, earth); return register(Unicopia.id(name), magic, flight, earth, false);
} }
public static Race register(Identifier id, boolean magic, FlightType flight, boolean earth) { public static Race register(Identifier id, boolean magic, FlightType flight, boolean earth, boolean nocturnal) {
return Registry.register(REGISTRY, id, new Race(magic, flight, earth)); return Registry.register(REGISTRY, id, new Race(magic, flight, earth, nocturnal));
} }
public static RegistryKeyArgumentType<Race> argument() { public static RegistryKeyArgumentType<Race> argument() {
@ -44,27 +44,17 @@ public final class Race implements Affine {
* The default, unset race. * The default, unset race.
* This is used if there are no other races. * This is used if there are no other races.
*/ */
public static final Race UNSET = register("unset", false, FlightType.NONE, false); public static final Race UNSET = register("unset", false, FlightType.NONE, false, false);
public static final Race HUMAN = register("human", false, FlightType.NONE, false); public static final Race HUMAN = register("human", false, FlightType.NONE, false, false);
public static final Race EARTH = register("earth", false, FlightType.NONE, true); public static final Race EARTH = register("earth", false, FlightType.NONE, true, false);
public static final Race UNICORN = register("unicorn", true, FlightType.NONE, false); public static final Race UNICORN = register("unicorn", true, FlightType.NONE, false, false);
public static final Race PEGASUS = register("pegasus", false, FlightType.AVIAN, false); public static final Race PEGASUS = register("pegasus", false, FlightType.AVIAN, false, false);
public static final Race BAT = register("bat", false, FlightType.AVIAN, false); public static final Race BAT = register("bat", false, FlightType.AVIAN, false, true);
public static final Race ALICORN = register("alicorn", true, FlightType.AVIAN, true); public static final Race ALICORN = register("alicorn", true, FlightType.AVIAN, true, false);
public static final Race CHANGELING = register("changeling", false, FlightType.INSECTOID, false); public static final Race CHANGELING = register("changeling", false, FlightType.INSECTOID, false, false);
public static void bootstrap() {} public static void bootstrap() {}
private final boolean magic;
private final FlightType flight;
private final boolean earth;
Race(boolean magic, FlightType flight, boolean earth) {
this.magic = magic;
this.flight = flight;
this.earth = earth;
}
@Override @Override
public Affinity getAffinity() { public Affinity getAffinity() {
return this == CHANGELING ? Affinity.BAD : Affinity.NEUTRAL; return this == CHANGELING ? Affinity.BAD : Affinity.NEUTRAL;
@ -90,20 +80,8 @@ public final class Race implements Affine {
return this == ALICORN; return this == ALICORN;
} }
public FlightType getFlightType() {
return flight;
}
public boolean canFly() { public boolean canFly() {
return !getFlightType().isGrounded(); return !flightType().isGrounded();
}
public boolean canCast() {
return magic;
}
public boolean canUseEarth() {
return earth;
} }
public boolean canInteractWithClouds() { public boolean canInteractWithClouds() {

View file

@ -7,6 +7,7 @@ import net.minecraft.world.GameRules.IntRule;
public interface UGameRules { public interface UGameRules {
GameRules.Key<BooleanRule> SWAP_TRIBE_ON_DEATH = GameRules.register("swapTribeOnDeath", GameRules.Category.SPAWNING, BooleanRule.create(false)); GameRules.Key<BooleanRule> SWAP_TRIBE_ON_DEATH = GameRules.register("swapTribeOnDeath", GameRules.Category.SPAWNING, BooleanRule.create(false));
GameRules.Key<BooleanRule> ANNOUNCE_TRIBE_JOINS = GameRules.register("announceTribeJoins", GameRules.Category.SPAWNING, BooleanRule.create(false)); GameRules.Key<BooleanRule> ANNOUNCE_TRIBE_JOINS = GameRules.register("announceTribeJoins", GameRules.Category.SPAWNING, BooleanRule.create(false));
GameRules.Key<BooleanRule> DO_NOCTURNAL_BAT_PONIES = GameRules.register("doNocturnalBatPonies", GameRules.Category.PLAYER, BooleanRule.create(true));
GameRules.Key<IntRule> WEATHER_EFFECTS_STRENGTH = GameRules.register("weatherEffectsStrength", GameRules.Category.MISC, IntRule.create(100)); GameRules.Key<IntRule> WEATHER_EFFECTS_STRENGTH = GameRules.register("weatherEffectsStrength", GameRules.Category.MISC, IntRule.create(100));
static void bootstrap() { } static void bootstrap() { }

View file

@ -220,7 +220,7 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Pony iplayer = Pony.of(((Owned<PlayerEntity>)entity).getMaster()); Pony iplayer = Pony.of(((Owned<PlayerEntity>)entity).getMaster());
return iplayer == null ? FlightType.NONE : iplayer.getSpecies().getFlightType(); return iplayer == null ? FlightType.NONE : iplayer.getSpecies().flightType();
} }
if (entity instanceof FlyingEntity if (entity instanceof FlyingEntity

View file

@ -158,7 +158,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
.filter(effect -> !effect.isDead() && effect instanceof FlightType.Provider) .filter(effect -> !effect.isDead() && effect instanceof FlightType.Provider)
.map(effect -> ((FlightType.Provider)effect).getFlightType()) .map(effect -> ((FlightType.Provider)effect).getFlightType())
.filter(FlightType::isPresent) .filter(FlightType::isPresent)
.orElse(pony.getSpecies().getFlightType()); .orElse(pony.getSpecies().flightType());
} }
public void cancelFlight(boolean force) { public void cancelFlight(boolean force) {

View file

@ -570,6 +570,10 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
.map(p -> Text.translatable("block.unicopia.bed.not_safe")); .map(p -> Text.translatable("block.unicopia.bed.not_safe"));
} }
public boolean isDaytime() {
return asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES) && getActualSpecies().isNocturnal() ? !asWorld().isDay() : asWorld().isDay();
}
@Override @Override
public boolean isEnemy(Affine other) { public boolean isEnemy(Affine other) {
return getArmour().contains(UItems.ALICORN_AMULET) || super.isEnemy(other); return getArmour().contains(UItems.ALICORN_AMULET) || super.isEnemy(other);

View file

@ -5,6 +5,7 @@ import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.entity.duck.PlayerEntityDuck; import com.minelittlepony.unicopia.entity.duck.PlayerEntityDuck;
@ -24,6 +25,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.stat.Stats; import net.minecraft.stat.Stats;
import net.minecraft.util.Unit; import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@Mixin(PlayerEntity.class) @Mixin(PlayerEntity.class)
abstract class MixinPlayerEntity extends LivingEntity implements Equine.Container<Pony>, PlayerEntityDuck { abstract class MixinPlayerEntity extends LivingEntity implements Equine.Container<Pony>, PlayerEntityDuck {
@ -99,4 +101,12 @@ abstract class MixinPlayerEntity extends LivingEntity implements Equine.Containe
private void onGetBlockBreakingSpeed(BlockState state, CallbackInfoReturnable<Float> info) { private void onGetBlockBreakingSpeed(BlockState state, CallbackInfoReturnable<Float> info) {
info.setReturnValue(info.getReturnValue() * get().getBlockBreakingSpeed()); info.setReturnValue(info.getReturnValue() * get().getBlockBreakingSpeed());
} }
@Redirect(method = "tick", at = @At(
value = "INVOKE",
target = "net/minecraft/world/World.isDay()Z"
))
private boolean redirectIsDay(World world) {
return get().isDaytime();
}
} }

View file

@ -4,6 +4,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.entity.Equine; import com.minelittlepony.unicopia.entity.Equine;
@ -12,6 +13,7 @@ import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.ScreenHandlerListener; import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.World;
@Mixin(ServerPlayerEntity.class) @Mixin(ServerPlayerEntity.class)
abstract class MixinServerPlayerEntity extends PlayerEntity implements ScreenHandlerListener, Equine.Container<Pony>, ServerPlayerEntityDuck { abstract class MixinServerPlayerEntity extends PlayerEntity implements ScreenHandlerListener, Equine.Container<Pony>, ServerPlayerEntityDuck {
@ -27,4 +29,11 @@ abstract class MixinServerPlayerEntity extends PlayerEntity implements ScreenHan
get().copyFrom(((Equine.Container<Pony>)oldPlayer).get(), alive); get().copyFrom(((Equine.Container<Pony>)oldPlayer).get(), alive);
} }
@Redirect(method = "trySleep", at = @At(
value = "INVOKE",
target = "net/minecraft/world/World.isDay()Z"
))
private boolean redirectIsDay(World world) {
return get().isDaytime();
}
} }