mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 11:36:43 +01:00
Incorporate the player's luck and allow it to turn back if left unattended
This commit is contained in:
parent
22d6874102
commit
19f67c23c6
5 changed files with 116 additions and 52 deletions
|
@ -104,6 +104,7 @@ public interface UTags {
|
|||
TagKey<Block> KICKS_UP_DUST = block("kicks_up_dust");
|
||||
|
||||
TagKey<Block> POLEARM_MINEABLE = block("mineable/polearm");
|
||||
TagKey<Block> MIMIC_CHESTS = block("mimic_chests");
|
||||
|
||||
TagKey<Block> BUTTERFLIES_SPAWNABLE_ON = block("butterflies_spawn_on");
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ public class MimicEntityRenderer extends MobEntityRenderer<MimicEntity, MimicEnt
|
|||
public void render(MimicEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
|
||||
matrices.push();
|
||||
matrices.translate(0, 0.3F * entity.getPeekAmount(), 0);
|
||||
|
||||
float legAngle = entity.limbAnimator.getPos(tickDelta);
|
||||
float legSpeed = entity.limbAnimator.getSpeed(tickDelta);
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.cos(legAngle * 0.6662F) * 1.4F * legSpeed * 10 * entity.getPeekAmount()));
|
||||
super.render(entity, yaw, tickDelta, matrices,
|
||||
FloatingArtefactEntityRenderer.getDestructionOverlayProvider(
|
||||
matrices,
|
||||
|
|
|
@ -81,6 +81,10 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
|
|||
.forceAddTag(UTags.Blocks.JARS)
|
||||
.add(Blocks.VINE, Blocks.LILY_PAD);
|
||||
|
||||
getOrCreateTagBuilder(UTags.Blocks.MIMIC_CHESTS).add(
|
||||
Blocks.CHEST, Blocks.TRAPPED_CHEST, UBlocks.CLOUD_CHEST
|
||||
);
|
||||
|
||||
getOrCreateTagBuilder(UTags.Blocks.INTERESTING).add(
|
||||
Blocks.SEA_LANTERN, Blocks.ENDER_CHEST, Blocks.END_PORTAL_FRAME,
|
||||
Blocks.JUKEBOX, Blocks.SPAWNER
|
||||
|
|
|
@ -5,6 +5,8 @@ import java.util.Set;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
|
||||
import com.minelittlepony.unicopia.mixin.MixinBlockEntity;
|
||||
import com.minelittlepony.unicopia.util.InventoryUtil;
|
||||
|
||||
|
@ -40,8 +42,8 @@ import net.minecraft.sound.SoundEvents;
|
|||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.ItemScatterer;
|
||||
import net.minecraft.util.TypedActionResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
@ -59,28 +61,29 @@ public class MimicEntity extends PathAwareEntity {
|
|||
private int openTicks;
|
||||
private final Set<PlayerEntity> observingPlayers = new HashSet<>();
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static TypedActionResult<MimicEntity> spawnFromChest(World world, BlockPos pos, PlayerEntity player) {
|
||||
if (world.getBlockState(pos).isOf(Blocks.CHEST) && world.getBlockEntity(pos) instanceof ChestBlockEntity be) {
|
||||
public static boolean shouldConvert(World world, BlockPos pos, PlayerEntity player, Identifier lootTable) {
|
||||
if (!shouldGenerateMimic(lootTable)
|
||||
|| !world.getBlockState(pos).isIn(UTags.Blocks.MIMIC_CHESTS)
|
||||
|| !(world.getBlockEntity(pos) instanceof ChestBlockEntity be)
|
||||
|| be.getCachedState().getOrEmpty(ChestBlock.CHEST_TYPE).orElse(ChestType.SINGLE) != ChestType.SINGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int difficulty = world.getDifficulty().ordinal() - 1;
|
||||
if (difficulty < 0) {
|
||||
return TypedActionResult.pass(null);
|
||||
}
|
||||
float spawnChance = (difficulty / 3F) * 0.25F;
|
||||
float roll = world.random.nextFloat();
|
||||
|
||||
if (roll >= spawnChance) {
|
||||
return TypedActionResult.pass(null);
|
||||
float threshold = 0.35F * ((EnchantmentUtil.getLuck(0, player) / 20F) + 0.5F);
|
||||
return difficulty > 0 && world.random.nextFloat() < (difficulty / 3F) * threshold;
|
||||
}
|
||||
|
||||
BlockState state = be.getCachedState();
|
||||
if (state.getOrEmpty(ChestBlock.CHEST_TYPE).orElse(ChestType.SINGLE) != ChestType.SINGLE) {
|
||||
return TypedActionResult.fail(null);
|
||||
@SuppressWarnings("deprecation")
|
||||
@Nullable
|
||||
public static MimicEntity spawnFromChest(World world, BlockPos pos) {
|
||||
if (!(world.getBlockEntity(pos) instanceof ChestBlockEntity be)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
world.removeBlockEntity(pos);
|
||||
world.setBlockState(pos, Blocks.AIR.getDefaultState());
|
||||
MimicEntity mimic = UEntities.MIMIC.create(world);
|
||||
BlockState state = be.getCachedState();
|
||||
Direction facing = state.getOrEmpty(ChestBlock.FACING).orElse(null);
|
||||
float yaw = facing.asRotation();
|
||||
be.setCachedState(be.getCachedState().getBlock().getDefaultState());
|
||||
|
@ -90,9 +93,15 @@ public class MimicEntity extends PathAwareEntity {
|
|||
mimic.setYaw(yaw);
|
||||
mimic.setChest(be);
|
||||
world.spawnEntity(mimic);
|
||||
return TypedActionResult.success(mimic);
|
||||
return mimic;
|
||||
}
|
||||
return TypedActionResult.fail(null);
|
||||
|
||||
public static boolean shouldGenerateMimic(@Nullable Identifier lootTable) {
|
||||
return lootTable != null
|
||||
&& lootTable.getPath().indexOf("village") == -1
|
||||
&& lootTable.getPath().indexOf("bastion") == -1
|
||||
&& lootTable.getPath().indexOf("underwater") == -1
|
||||
&& lootTable.getPath().indexOf("shipwreck") == -1;
|
||||
}
|
||||
|
||||
MimicEntity(EntityType<? extends MimicEntity> type, World world) {
|
||||
|
@ -141,6 +150,7 @@ public class MimicEntity extends PathAwareEntity {
|
|||
|
||||
public void setChest(ChestBlockEntity chestData) {
|
||||
this.chestData = chestData;
|
||||
((MimicGeneratable)chestData).setAllowMimics(false);
|
||||
chestData.setWorld(getWorld());
|
||||
if (!getWorld().isClient) {
|
||||
dataTracker.set(CHEST_DATA, writeChestData(chestData));
|
||||
|
@ -194,9 +204,22 @@ public class MimicEntity extends PathAwareEntity {
|
|||
setHeadYaw(MathHelper.floor(getHeadYaw() / 90) * 90);
|
||||
if (getHealth() < getMaxHealth() && getWorld().random.nextInt(20) == 0) {
|
||||
heal(1);
|
||||
} else if (age % 150 == 0 && chestData != null && !isMouthOpen()) {
|
||||
if (getWorld().getClosestPlayer(this, 15) == null) {
|
||||
getWorld().setBlockState(getBlockPos(), chestData.getCachedState().withIfExists(ChestBlock.FACING, getHorizontalFacing()));
|
||||
if (getWorld().getBlockEntity(getBlockPos()) instanceof ChestBlockEntity be) {
|
||||
InventoryUtil.copyInto(chestData, be);
|
||||
((MimicGeneratable)be).setMimic(true);
|
||||
discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!observingPlayers.isEmpty()) {
|
||||
setMouthOpen(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (chestData == null) {
|
||||
setChest((ChestBlock)Blocks.CHEST);
|
||||
|
@ -245,7 +268,7 @@ public class MimicEntity extends PathAwareEntity {
|
|||
@Override
|
||||
public void onOpen(PlayerEntity player) {
|
||||
observingPlayers.add(player);
|
||||
setMouthOpen(true);
|
||||
//setMouthOpen(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -311,6 +334,7 @@ public class MimicEntity extends PathAwareEntity {
|
|||
BlockState state = BlockState.CODEC.decode(NbtOps.INSTANCE, nbt.getCompound("state")).result().get().getFirst();
|
||||
if (BlockEntity.createFromNbt(getBlockPos(), state, nbt.getCompound("data")) instanceof ChestBlockEntity data) {
|
||||
data.setWorld(getWorld());
|
||||
((MimicGeneratable)data).setAllowMimics(false);
|
||||
return data;
|
||||
}
|
||||
return null;
|
||||
|
@ -370,4 +394,10 @@ public class MimicEntity extends PathAwareEntity {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface MimicGeneratable {
|
||||
void setAllowMimics(boolean allowMimics);
|
||||
|
||||
void setMimic(boolean mimic);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,25 +14,49 @@ import net.minecraft.block.entity.LockableContainerBlockEntity;
|
|||
import net.minecraft.block.entity.LootableContainerBlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
@Mixin(LootableContainerBlockEntity.class)
|
||||
abstract class MixinLootableContainerBlockEntity extends LockableContainerBlockEntity {
|
||||
private boolean generateMimic;
|
||||
abstract class MixinLootableContainerBlockEntity extends LockableContainerBlockEntity implements MimicEntity.MimicGeneratable {
|
||||
private Identifier mimicLootTable;
|
||||
private boolean allowMimics = true;
|
||||
private boolean isMimic;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
private Identifier lootTableId;
|
||||
|
||||
MixinLootableContainerBlockEntity() { super(null, null, null); }
|
||||
|
||||
@Inject(
|
||||
method = "checkLootInteraction",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/loot/LootTable.supplyInventory(Lnet/minecraft/inventory/Inventory;Lnet/minecraft/loot/context/LootContextParameterSet;J)V",
|
||||
shift = Shift.AFTER
|
||||
))
|
||||
@Inject(method = "deserializeLootTable", at = @At("HEAD"))
|
||||
private void deserializeMimic(NbtCompound nbt, CallbackInfoReturnable<Boolean> info) {
|
||||
isMimic = nbt.getBoolean("mimic");
|
||||
}
|
||||
|
||||
@Inject(method = "serializeLootTable", at = @At("HEAD"))
|
||||
private void serializeMimic(NbtCompound nbt, CallbackInfoReturnable<Boolean> info) {
|
||||
nbt.putBoolean("mimic", isMimic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowMimics(boolean allowMimics) {
|
||||
this.allowMimics = allowMimics;
|
||||
this.isMimic &= allowMimics;
|
||||
markDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMimic(boolean mimic) {
|
||||
isMimic = mimic;
|
||||
markDirty();
|
||||
}
|
||||
|
||||
@Inject(method = "checkLootInteraction", at = @At("HEAD"))
|
||||
private void onCheckLootInteraction(@Nullable PlayerEntity player, CallbackInfo info) {
|
||||
if (player != null) {
|
||||
generateMimic = true;
|
||||
if (player != null && allowMimics && lootTableId != null) {
|
||||
mimicLootTable = lootTableId;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,12 +68,12 @@ abstract class MixinLootableContainerBlockEntity extends LockableContainerBlockE
|
|||
shift = Shift.AFTER
|
||||
), cancellable = true)
|
||||
private void onCreateMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player, CallbackInfoReturnable<ScreenHandler> info) {
|
||||
if (generateMimic) {
|
||||
generateMimic = false;
|
||||
var mimic = MimicEntity.spawnFromChest(player.getWorld(), getPos(), player);
|
||||
if (mimic.getResult() == ActionResult.SUCCESS) {
|
||||
info.setReturnValue(mimic.getValue().createScreenHandler(syncId, playerInventory, player));
|
||||
}
|
||||
if (player != null && (isMimic || (allowMimics && MimicEntity.shouldConvert(player.getWorld(), getPos(), player, mimicLootTable)))) {
|
||||
var mimic = MimicEntity.spawnFromChest(player.getWorld(), getPos());
|
||||
if (mimic != null) {
|
||||
info.setReturnValue(mimic.createScreenHandler(syncId, playerInventory, player));
|
||||
}
|
||||
mimicLootTable = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue