other features
This commit is contained in:
1 parent
39727cb524
commit
b257e6f984
19 files changed
+501
-18
No files matched your search
@@ -55,6 +55,7 @@ public class CarpetSettings
|
||||
//those don't have to mimic defaults - defaults will be '
|
||||
//static store
|
||||
public static int n_pushLimit = 12;
|
||||
public static int n_maxEntityCollisions = 0;
|
||||
public static boolean b_hopperCounters = false;
|
||||
public static boolean b_shulkerSpawningInEndCities = false;
|
||||
public static boolean b_fastRedstoneDust = false;
|
||||
@@ -64,6 +65,7 @@ public class CarpetSettings
|
||||
public static boolean b_huskSpawningInTemples = false;
|
||||
public static boolean b_stackableShulkerBoxes = false;
|
||||
public static boolean b_fillUpdates = true;
|
||||
public static boolean b_lagFreeSpawning = false;
|
||||
|
||||
private static CarpetSettingEntry rule(String s1, String s2, String s3) { return CarpetSettingEntry.create(s1,s2,s3);}
|
||||
|
||||
@@ -143,16 +145,14 @@ public class CarpetSettings
|
||||
rule("fillLimit", "creative","Customizable fill/clone volume limit")
|
||||
.choices("32768","32768 250000 1000000").setNotStrict(),
|
||||
rule("maxEntityCollisions", "optimizations", "Customizable maximal entity collision limits, 0 for no limits")
|
||||
.choices("0","0 1 20").setNotStrict(),
|
||||
.choices("0","0 1 20").setNotStrict().numAccelerate(),
|
||||
//???rule("pistonGhostBlocksFix", "fix", "Fix for piston ghost blocks")
|
||||
// .extraInfo("true(serverOnly) option works with all clients, including vanilla",
|
||||
// "clientAndServer option requires compatible carpet clients and messes up flying machines")
|
||||
// .choices("false","false true clientAndServer"),
|
||||
//???rule("waterFlow", "optimizations", "fixes water flowing issues")
|
||||
// .choices("vanilla","vanilla optimized correct"),
|
||||
rule("sleepingThreshold", "experimental", "The percentage of required sleeping players to skip the night")
|
||||
.extraInfo("Use values from 0 to 100, 100 for default (all players needed)")
|
||||
.choices("100","0 10 50 100").setNotStrict(),
|
||||
rule("onePlayerSleeping", "survival", "One player is required on the server to cause night to pass"),
|
||||
rule("customMOTD", "creative","Sets a different motd message on client trying to connect to the server")
|
||||
.extraInfo("use '_' to use the startup setting from server.properties")
|
||||
.choices("_","_").setNotStrict().validate((s) ->
|
||||
@@ -196,6 +196,7 @@ public class CarpetSettings
|
||||
rule("placementRotationFix", "fix", "fixes block placement rotation issue when player rotates quickly while placing blocks"),
|
||||
rule("leadFix", "fix", "Fixes leads breaking/becoming invisible in unloaded chunks")
|
||||
.extraInfo("You may still get visibly broken leash links on the client side, but server side the link is still there."),
|
||||
rule("lagFreeSpawning", "optimizations", "Spawning requires much less CPU and Memory").boolAccelerate()
|
||||
};
|
||||
for (CarpetSettingEntry rule: RuleList)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package carpet.fakes;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public interface CoralFeatureInterface
|
||||
{
|
||||
boolean growSpecific(World worldIn, Random random, BlockPos pos, BlockState blockUnder);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package carpet.fakes;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface WorldInterface
|
||||
{
|
||||
Map<EntityType, Entity> getPrecookedMobs();
|
||||
}
|
||||
@@ -7,8 +7,9 @@ import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class TNTLogHelper
|
||||
{
|
||||
public boolean initialized;
|
||||
private double primedX, primedY, primedZ;
|
||||
Vec3d primedAngle;
|
||||
private Vec3d primedAngle;
|
||||
/**
|
||||
* Runs when the TNT is primed. Expects the position and motion angle of the TNT.
|
||||
*/
|
||||
@@ -18,6 +19,7 @@ public class TNTLogHelper
|
||||
primedY = y;
|
||||
primedZ = z;
|
||||
primedAngle = motion;
|
||||
initialized = true;
|
||||
}
|
||||
/**
|
||||
* Runs when the TNT explodes. Expects the position of the TNT.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.utils.WoolTool;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.CarpetBlock;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(CarpetBlock.class)
|
||||
public abstract class CarpetBlockMixin extends Block
|
||||
{
|
||||
|
||||
public CarpetBlockMixin(Settings block$Settings_1)
|
||||
{
|
||||
super(block$Settings_1);
|
||||
}
|
||||
|
||||
public BlockState getPlacementState(ItemPlacementContext context)
|
||||
{
|
||||
BlockState state = super.getPlacementState(context);
|
||||
if (context.getPlayer() != null && !context.getWorld().isClient)
|
||||
{
|
||||
WoolTool.carpetPlacedAction(((CarpetBlock)(Object)this).getColor(), context.getPlayer(), context.getBlockPos(), context.getWorld());
|
||||
}
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.fakes.CoralFeatureInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.CoralBlock;
|
||||
import net.minecraft.block.CoralParentBlock;
|
||||
import net.minecraft.block.Fertilizable;
|
||||
import net.minecraft.block.MaterialColor;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.tag.FluidTags;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.CoralClawFeature;
|
||||
import net.minecraft.world.gen.feature.CoralFeature;
|
||||
import net.minecraft.world.gen.feature.CoralMushroomFeature;
|
||||
import net.minecraft.world.gen.feature.CoralTreeFeature;
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import org.spongepowered.asm.mixin.Interface;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@Mixin(CoralBlock.class)
|
||||
@Interface(iface = Fertilizable.class, prefix = "fert$")
|
||||
public abstract class CoralBlockMixin implements Fertilizable
|
||||
{
|
||||
public boolean isFertilizable(BlockView var1, BlockPos var2, BlockState var3, boolean var4)
|
||||
{
|
||||
return CarpetSettings.getBool("renewableCoral") && var3.get(CoralParentBlock.WATERLOGGED) && var1.getFluidState(var2.up()).matches(FluidTags.WATER);
|
||||
}
|
||||
|
||||
public boolean canGrow(World var1, Random var2, BlockPos var3, BlockState var4)
|
||||
{
|
||||
return (double)var1.random.nextFloat() < 0.15D;
|
||||
}
|
||||
|
||||
public void grow(World worldIn, Random random, BlockPos pos, BlockState blockUnder)
|
||||
{
|
||||
|
||||
CoralFeature coral;
|
||||
int variant = random.nextInt(3);
|
||||
if (variant == 0)
|
||||
coral = new CoralClawFeature(DefaultFeatureConfig::deserialize);
|
||||
else if (variant == 1)
|
||||
coral = new CoralTreeFeature(DefaultFeatureConfig::deserialize);
|
||||
else
|
||||
coral = new CoralMushroomFeature(DefaultFeatureConfig::deserialize);
|
||||
|
||||
MaterialColor color = blockUnder.getTopMaterialColor(worldIn, pos);
|
||||
BlockState proper_block = blockUnder;
|
||||
for (Block block: BlockTags.CORAL_BLOCKS.values())
|
||||
{
|
||||
proper_block = block.getDefaultState();
|
||||
if (proper_block.getTopMaterialColor(worldIn,pos) == color)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
worldIn.setBlockState(pos, Blocks.WATER.getDefaultState(), 4);
|
||||
|
||||
if (!((CoralFeatureInterface)coral).growSpecific(worldIn, random, pos, proper_block))
|
||||
{
|
||||
worldIn.setBlockState(pos, blockUnder, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (worldIn.random.nextInt(10)==0)
|
||||
{
|
||||
BlockPos randomPos = pos.add(worldIn.random.nextInt(16)-8,worldIn.random.nextInt(8),worldIn.random.nextInt(16)-8 );
|
||||
if (BlockTags.CORAL_BLOCKS.contains(worldIn.getBlockState(randomPos).getBlock()))
|
||||
{
|
||||
worldIn.setBlockState(randomPos, Blocks.WET_SPONGE.getDefaultState(), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.fakes.CoralFeatureInterface;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.CoralFeature;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@Mixin(CoralFeature.class)
|
||||
public abstract class CoralFeatureMixin implements CoralFeatureInterface
|
||||
{
|
||||
|
||||
@Shadow protected abstract boolean spawnCoral(IWorld var1, Random var2, BlockPos var3, BlockState var4);
|
||||
|
||||
@Override
|
||||
public boolean growSpecific(World worldIn, Random random, BlockPos pos, BlockState blockUnder)
|
||||
{
|
||||
return spawnCoral(worldIn, random, pos, blockUnder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.world.gen.feature.KelpFeature;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@Mixin(KelpFeature.class)
|
||||
public class KelpFeatureMixin
|
||||
{
|
||||
@Redirect(method = "method_13460", at = @At(value = "INVOKE", target = "Ljava/util/Random;nextInt(I)I"))
|
||||
private int getRandom(Random random, int bound)
|
||||
{
|
||||
if (bound==10)
|
||||
return random.nextInt(bound);
|
||||
int limit = CarpetSettings.getInt("kelpGenerationGrowLimit");
|
||||
if (limit == 0)
|
||||
return random.nextInt(bound);
|
||||
return 25-limit+random.nextInt(Math.min(23,limit+1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class LivingEntity_maxCollisionsMixin extends Entity
|
||||
{
|
||||
|
||||
public LivingEntity_maxCollisionsMixin(EntityType<?> entityType_1, World world_1)
|
||||
{
|
||||
super(entityType_1, world_1);
|
||||
}
|
||||
|
||||
@Shadow protected abstract void pushAway(Entity entity_1);
|
||||
|
||||
@Inject(method = "tickPushing", cancellable = true, at = @At("HEAD"))
|
||||
private void tickPushingReplacement(CallbackInfo ci)
|
||||
{
|
||||
List<Entity> list_1 = this.world.getEntities((Entity)this, this.getBoundingBox(), EntityPredicates.canBePushedBy(this));
|
||||
if (!list_1.isEmpty()) {
|
||||
int int_1 = this.world.getGameRules().getInteger("maxEntityCramming");
|
||||
int int_2;
|
||||
if (int_1 > 0 && list_1.size() > int_1 - 1 && this.random.nextInt(4) == 0) {
|
||||
int_2 = 0;
|
||||
|
||||
for(int int_3 = 0; int_3 < list_1.size(); ++int_3) {
|
||||
if (!((Entity)list_1.get(int_3)).hasVehicle()) {
|
||||
++int_2;
|
||||
}
|
||||
}
|
||||
|
||||
if (int_2 > int_1 - 1) {
|
||||
this.damage(DamageSource.CRAMMING, 6.0F);
|
||||
}
|
||||
}
|
||||
|
||||
int limit = list_1.size();
|
||||
if (CarpetSettings.n_maxEntityCollisions > 0)
|
||||
limit = Math.min(limit, CarpetSettings.n_maxEntityCollisions);
|
||||
|
||||
for(int_2 = 0; int_2 < limit; ++int_2) {
|
||||
Entity entity_1 = (Entity)list_1.get(int_2);
|
||||
this.pushAway(entity_1);
|
||||
}
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.block.piston.PistonHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
|
||||
@Mixin(PistonHandler.class)
|
||||
public class PistonHandler_pushLimitMixin
|
||||
{
|
||||
@ModifyConstant(method = "tryMove", constant = @Constant(intValue = 12), expect = 3)
|
||||
private int pushLimit(int original)
|
||||
{
|
||||
return CarpetSettings.n_pushLimit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.block.PoweredRailBlock;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
|
||||
@Mixin(PoweredRailBlock.class)
|
||||
public class PoweredRailBlock_powerLimitMixin
|
||||
{
|
||||
@ModifyConstant(method = "isPoweredByOtherRails(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;ZI)Z",
|
||||
constant = @Constant(intValue = 8))
|
||||
private int powerLimit(int original)
|
||||
{
|
||||
return CarpetSettings.railPowerLimitAdjusted;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.PrimedTntEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -24,6 +25,25 @@ public abstract class PrimedTntEntityMixin extends Entity
|
||||
super(entityType_1, world_1);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>(Lnet/minecraft/entity/EntityType;Lnet/minecraft/world/World;)V", at = @At("RETURN"))
|
||||
private void initTNTLoggerPrime(EntityType<? extends PrimedTntEntity> entityType_1, World world_1, CallbackInfo ci)
|
||||
{
|
||||
if (LoggerRegistry.__tnt && !world_1.isClient)
|
||||
{
|
||||
logHelper = new TNTLogHelper();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void initTracker(CallbackInfo ci)
|
||||
{
|
||||
if (LoggerRegistry.__tnt && logHelper != null && !logHelper.initialized)
|
||||
{
|
||||
logHelper.onPrimed(x, y, z, getVelocity());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Inject(method = "<init>(Lnet/minecraft/world/World;DDDLnet/minecraft/entity/LivingEntity;)V",
|
||||
at = @At(value = "RETURN"))
|
||||
private void initTNTLogger(World world_1, double double_1, double double_2, double double_3,
|
||||
@@ -31,12 +51,6 @@ public abstract class PrimedTntEntityMixin extends Entity
|
||||
{
|
||||
if(CarpetSettings.getBool("tntPrimerMomentumRemoved"))
|
||||
this.setVelocity(new Vec3d(0.0, 0.20000000298023224D, 0.0));
|
||||
if (LoggerRegistry.__tnt)
|
||||
{
|
||||
logHelper = new TNTLogHelper();
|
||||
|
||||
logHelper.onPrimed(double_1, double_2, double_3, getVelocity());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "explode", at = @At(value = "HEAD"))
|
||||
|
||||
@@ -25,7 +25,7 @@ public abstract class ProjectileEntityMixin extends Entity
|
||||
logHelper = new TrajectoryLogHelper("projectiles");
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("RETURN"))
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void tickCheck(CallbackInfo ci)
|
||||
{
|
||||
if (LoggerRegistry.__projectiles && logHelper != null)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.fakes.WorldInterface;
|
||||
import carpet.utils.SpawnReporter;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.entity.EntityCategory;
|
||||
@@ -56,6 +57,7 @@ public abstract class ServerChunkManagerMixin
|
||||
Object2IntMap object2IntMap_1)
|
||||
{
|
||||
DimensionType dim = this.world.dimension.getType();
|
||||
((WorldInterface)world).getPrecookedMobs().clear();
|
||||
SpawnReporter.mobCounts.put(dim, (Object2IntMap<EntityCategory>)object2IntMap_1);
|
||||
SpawnReporter.chunkCounts.put(dim, int_2);
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mixin(ServerWorld.class)
|
||||
public class ServerWorld_onePlayerSleepingMixin
|
||||
{
|
||||
@Shadow @Final private List<ServerPlayerEntity> players;
|
||||
|
||||
@Shadow private boolean allPlayersSleeping;
|
||||
|
||||
@Inject(method = "updatePlayersSleeping", cancellable = true, at = @At("HEAD"))
|
||||
private void updateOnePlayerSleeping(CallbackInfo ci)
|
||||
{
|
||||
if(CarpetSettings.getBool("onePlayerSleeping"))
|
||||
{
|
||||
allPlayersSleeping = false;
|
||||
for (ServerPlayerEntity p : players)
|
||||
if (!p.isSpectator() && p.isSleeping())
|
||||
{
|
||||
allPlayersSleeping = true;
|
||||
ci.cancel();
|
||||
return;
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "tick", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Ljava/util/stream/Stream;noneMatch(Ljava/util/function/Predicate;)Z"
|
||||
))
|
||||
private boolean noneMatchSleep(Stream<ServerPlayerEntity> stream, Predicate<ServerPlayerEntity> predicate)
|
||||
{
|
||||
if (CarpetSettings.getBool("onePlayerSleeping"))
|
||||
return stream.anyMatch((p) -> !p.isSpectator() && p.isSleepingLongEnough());
|
||||
return stream.noneMatch(predicate);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +1,82 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.fakes.WorldInterface;
|
||||
import carpet.utils.SpawnReporter;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BoundingBox;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.SpawnHelper;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(SpawnHelper.class)
|
||||
public abstract class SpawnHelperMixin
|
||||
public class SpawnHelperMixin
|
||||
{
|
||||
// in World: private static Map<EntityType, Entity> precookedMobs= new HashMap<>();
|
||||
|
||||
@Redirect(method = "spawnEntitiesInChunk", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/World;doesNotCollide(Lnet/minecraft/util/math/BoundingBox;)Z"
|
||||
))
|
||||
private static boolean doesNotCollide(World world, BoundingBox bb)
|
||||
{
|
||||
//.doesNotCollide is VERY expensive. On the other side - most worlds are not made of trapdoors in
|
||||
// various configurations, but solid and 'passable' blocks, like air, water grass, etc.
|
||||
// checking if in the BB of the entity are only passable blocks is very cheap and covers most cases
|
||||
// in case something more complex happens - we default to full block collision check
|
||||
if (CarpetSettings.b_lagFreeSpawning)
|
||||
{
|
||||
BlockPos.Mutable blockpos = new BlockPos.Mutable();
|
||||
for (int x = (int)bb.minX, maxx = (int)Math.ceil(bb.maxX); x < maxx; x++)
|
||||
for (int z = (int)bb.minZ, maxz = (int)Math.ceil(bb.maxZ); z < maxz; z++)
|
||||
for (int y = (int)bb.minY, maxy = (int)Math.ceil(bb.maxY); y < maxy; y++)
|
||||
{
|
||||
blockpos.set(x, y, z);
|
||||
if (world.getBlockState(blockpos).getCollisionShape(world, blockpos) != VoxelShapes.empty())
|
||||
return world.doesNotCollide(bb);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return world.doesNotCollide(bb);
|
||||
}
|
||||
|
||||
@Redirect(method = "spawnEntitiesInChunk", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/entity/EntityType;create(Lnet/minecraft/world/World;)Lnet/minecraft/entity/Entity;"
|
||||
))
|
||||
private static Entity create(EntityType<?> entityType, World world_1)
|
||||
{
|
||||
if (CarpetSettings.b_lagFreeSpawning)
|
||||
{
|
||||
Map<EntityType, Entity> precookedMobs = ((WorldInterface)world_1).getPrecookedMobs();
|
||||
if (precookedMobs.containsKey(entityType))
|
||||
//this mob has been <init>'s but not used yet
|
||||
return precookedMobs.get(entityType);
|
||||
Entity e = entityType.create(world_1);
|
||||
precookedMobs.put(entityType, e);
|
||||
return e;
|
||||
}
|
||||
return entityType.create(world_1);
|
||||
}
|
||||
|
||||
@Redirect(method = "spawnEntitiesInChunk", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"
|
||||
))
|
||||
private static boolean catchEntitySpawn(World world, Entity entity_1)
|
||||
private static boolean spawnEntity(World world, Entity entity_1)
|
||||
{
|
||||
if (CarpetSettings.b_lagFreeSpawning)
|
||||
// we used the mob - next time we will create a new one when needed
|
||||
((WorldInterface) world).getPrecookedMobs().remove(entity_1.getType());
|
||||
|
||||
if (SpawnReporter.track_spawns > 0L && SpawnReporter.local_spawns != null)
|
||||
{
|
||||
SpawnReporter.registerSpawn(
|
||||
@@ -31,6 +89,4 @@ public abstract class SpawnHelperMixin
|
||||
return world.spawnEntity(entity_1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LightningEntity;
|
||||
import net.minecraft.entity.mob.SkeletonHorseEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.command.SummonCommand;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.LocalDifficulty;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(SummonCommand.class)
|
||||
public class SummonCommandMixin
|
||||
{
|
||||
@Inject(method = "execute", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/server/world/ServerWorld;addLightning(Lnet/minecraft/entity/LightningEntity;)V",
|
||||
shift = At.Shift.BEFORE
|
||||
))
|
||||
private static void addRiders(ServerCommandSource source, Identifier identifier_1, Vec3d vec3d_1, CompoundTag compoundTag_1, boolean arg4, CallbackInfoReturnable<Integer> cir, CompoundTag compoundTag_2, LightningEntity lightningEntity_1)
|
||||
{
|
||||
// [CM] SummonNaturalLightning - if statement around
|
||||
if (CarpetSettings.getBool("summonNaturalLightning") && !source.getWorld().isClient)
|
||||
{
|
||||
ServerWorld world = source.getWorld();
|
||||
BlockPos at = new BlockPos(vec3d_1);
|
||||
LocalDifficulty localDifficulty_1 = source.getWorld().getLocalDifficulty(at);
|
||||
boolean boolean_2 = world.getGameRules().getBoolean("doMobSpawning") && world.random.nextDouble() < (double)localDifficulty_1.getLocalDifficulty() * 0.01D;
|
||||
if (boolean_2) {
|
||||
SkeletonHorseEntity skeletonHorseEntity_1 = (SkeletonHorseEntity) EntityType.SKELETON_HORSE.create(world);
|
||||
skeletonHorseEntity_1.setTrapped(true);
|
||||
skeletonHorseEntity_1.setBreedingAge(0);
|
||||
skeletonHorseEntity_1.setPosition(vec3d_1.x, vec3d_1.y, vec3d_1.z);
|
||||
world.spawnEntity(skeletonHorseEntity_1);
|
||||
}
|
||||
world.addLightning(lightningEntity_1);
|
||||
source.sendFeedback(new TranslatableComponent("commands.summon.success", new Object[]{lightningEntity_1.getDisplayName()}), true);
|
||||
cir.setReturnValue(1);
|
||||
cir.cancel();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package carpet.mixins;
|
||||
|
||||
import carpet.fakes.WorldInterface;
|
||||
import carpet.helpers.TickSpeed;
|
||||
import carpet.utils.CarpetProfiler;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
import net.minecraft.world.World;
|
||||
@@ -14,15 +16,24 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mixin(World.class)
|
||||
public abstract class World_tickMixin
|
||||
public abstract class World_tickMixin implements WorldInterface
|
||||
{
|
||||
CarpetProfiler.ProfilerToken currentSection;
|
||||
CarpetProfiler.ProfilerToken entitySection;
|
||||
|
||||
Map<EntityType, Entity> precookedMobs = new HashMap<>();
|
||||
|
||||
public Map<EntityType, Entity> getPrecookedMobs()
|
||||
{
|
||||
return precookedMobs;
|
||||
}
|
||||
|
||||
@Inject(method = "tickBlockEntities", at = @At("HEAD"))
|
||||
private void startBlockEntities(CallbackInfo ci) {
|
||||
currentSection = CarpetProfiler.start_section((World) (Object) this, "Tile Entities", CarpetProfiler.TYPE.GENERAL);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"mixins": [
|
||||
"CommandManagerMixin",
|
||||
|
||||
|
||||
"FillCommandMixin",
|
||||
"CloneCommandMixin",
|
||||
"SetBlockCommandMixin",
|
||||
@@ -32,6 +31,15 @@
|
||||
"PlayerActionC2SPacketMixin",
|
||||
"ServerPlayerEntityMixin",
|
||||
"PlayerManagerMixin",
|
||||
"CarpetBlockMixin",
|
||||
"SummonCommandMixin",
|
||||
"PistonHandler_pushLimitMixin",
|
||||
"PoweredRailBlock_powerLimitMixin",
|
||||
"LivingEntity_maxCollisionsMixin",
|
||||
"ServerWorld_onePlayerSleepingMixin",
|
||||
"KelpFeatureMixin",
|
||||
"CoralBlockMixin",
|
||||
"CoralFeatureMixin",
|
||||
|
||||
"ServerChunkManagerMixin",
|
||||
"SpawnHelperMixin",
|
||||
|
||||
Reference in new issue
Block a user