This commit is contained in:
gnembon committed 2020-05-04 19:54:11 -03:00
commit 18ecc4ec4f
11 files changed
+203 -50

No files matched your search

+19 -7
View File
@@ -689,15 +689,22 @@ number('3bar') => null
number('2')+number('2') => 4
</pre>
### `str(expr, params? ... ), str(expr, param_list)`
### `str(expr)`,`str(expr, params? ... )`, `str(expr, param_list)`
Returns a formatted string representing expression. Accepts formatting style accepted by `String.format`.
Supported types (with `"%?"` syntax):
If called with one argument, returns string representation of such value.
Otherwise, returns a formatted string representing the expression. Arguments for formatting can either be provided as
each consecutive parameter, or as a list which then would be the only extra parameter. To format one list argument
, you can use `str(list)`, or `str('foo %s', l(list))`.
Accepts formatting style accepted by `String.format`.
Supported types (with `"%<?>"` syntax):
* `d`, `o`, `x`: integers, octal, hex
* `a`, `e`, `f`, `g`: floats
* `b`: booleans
* `s`: strings
* `%%`: '%' character
<pre>
str(null) => null
@@ -2069,13 +2076,17 @@ Returns spawn potential at a location (1.16+ only)
Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check
for all structures. If bounding box of the structures is also requested, it will compute size of potential
structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
making it preferred for scoping ungenerated terrain.
making it preferred for scoping ungenerated terrain, but it takes some compute money to calculate the structure.
Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent
actual structure from forming.
If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or
a pair of coordinates indicating bounding box of the structure.
a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for
list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece.
If structure is not specified, it will return a set of structure names that are eligible, or a map with structures
as keys, and pair of bounding box coordinates as values. An empty set or an empty map would indicate that nothing
as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
should be generated there.
@@ -2085,7 +2096,8 @@ Returns structure information for a given block position. Note that structure in
blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In
the first case it returns a map of structures at a given position, keyed by structure name, with values indicating
the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure
name, returns list of components for that structure, with their name, direction and two sets of coordinates
name, returns a map with two values, `'box'` for bounding box of the structure, and `'pieces'` for a list of
components for that structure, with their name, direction and two sets of coordinates
indicating the bounding box of the structure piece.
### `structure_references(pos), structure_references(pos, structure_name)`
+9 -4
View File
@@ -532,13 +532,17 @@ Returns spawn potential at a location (1.16+ only)
Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check
for all structures. If bounding box of the structures is also requested, it will compute size of potential
structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
making it preferred for scoping ungenerated terrain.
making it preferred for scoping ungenerated terrain, but it takes some compute money to calculate the structure.
Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent
actual structure from forming.
If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or
a pair of coordinates indicating bounding box of the structure.
a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for
list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece.
If structure is not specified, it will return a set of structure names that are eligible, or a map with structures
as keys, and pair of bounding box coordinates as values. An empty set or an empty map would indicate that nothing
as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
should be generated there.
@@ -548,7 +552,8 @@ Returns structure information for a given block position. Note that structure in
blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In
the first case it returns a map of structures at a given position, keyed by structure name, with values indicating
the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure
name, returns list of components for that structure, with their name, direction and two sets of coordinates
name, returns a map with two values, `'box'` for bounding box of the structure, and `'pieces'` for a list of
components for that structure, with their name, direction and two sets of coordinates
indicating the bounding box of the structure piece.
### `structure_references(pos), structure_references(pos, structure_name)`
+6
View File
@@ -583,4 +583,10 @@ public class CarpetSettings
category = CLIENT
)
public static boolean fogOff = false;
@Rule(
desc = "Creative No Clip",
category = {CREATIVE, CLIENT}
)
public static boolean creativeNoClip = false;
}
@@ -154,10 +154,9 @@ public class FeatureGenerator
return null;
}
public static BlockBox DEFAULT_BOX = new BlockBox(0,0,0,1,1,1);
public static BlockBox shouldStructureStartAt(ServerWorld world, BlockPos pos, StructureFeature<?> structure, boolean computeBox)
public static StructureStart shouldStructureStartAt(ServerWorld world, BlockPos pos, StructureFeature<?> structure, boolean computeBox)
{
ChunkGenerator generator = world.getChunkManager().getChunkGenerator();
ChunkGenerator<?> generator = world.getChunkManager().getChunkGenerator();
if (!generator.getBiomeSource().hasStructureFeature(structure))
return null;
BiomeAccess biomeAccess = world.getBiomeAccess().withSource(generator.getBiomeSource());
@@ -166,12 +165,12 @@ public class FeatureGenerator
Biome biome = biomeAccess.getBiome(new BlockPos(chunkPos.getStartX() + 9, 0, chunkPos.getStartZ() + 9));
if (structure.method_27217(biomeAccess, generator, chunkRandom, chunkPos.x, chunkPos.z, biome)) // should start at
{
if (!computeBox) return DEFAULT_BOX;
if (!computeBox) return StructureStart.DEFAULT;
StructureManager manager = world.getStructureManager();
StructureStart structureStart3 = structure.getStructureStartFactory().create(structure, chunkPos.x, chunkPos.z, BlockBox.empty(), 0, generator.getSeed());
structureStart3.init(generator, manager, chunkPos.x, chunkPos.z, biome);
if (!structureStart3.hasChildren()) return null;
return structureStart3.getBoundingBox();
return structureStart3;
}
return null;
}
@@ -196,9 +195,9 @@ public class FeatureGenerator
structureToFeature.put(Feature.MINESHAFT.getName(), Arrays.asList("mineshaft", "mineshaft_mesa"));
structureToFeature.put(Feature.IGLOO.getName(), Collections.singletonList("igloo"));
structureToFeature.put(Feature.NETHER_BRIDGE.getName(), Collections.singletonList("fortress"));
structureToFeature.put("Nether_Fossil", Collections.singletonList("nether_fossil"));
structureToFeature.put("Bastion_Remnant", Arrays.asList("bastion_remnant", "bastion_remnant_housing", "bastion_remnant_stable", "bastion_remnant_treasure", "bastion_remnant_bridge"));
structureToFeature.put("Ruined_Portal", Collections.singletonList("ruined_portal"));
structureToFeature.put(Feature.NETHER_FOSSIL.getName(), Collections.singletonList("nether_fossil"));
structureToFeature.put(Feature.BASTION_REMNANT.getName(), Arrays.asList("bastion_remnant", "bastion_remnant_housing", "bastion_remnant_stable", "bastion_remnant_treasure", "bastion_remnant_bridge"));
structureToFeature.put(Feature.RUINED_PORTAL.getName(), Collections.singletonList("ruined_portal"));
structureToFeature.forEach((key, value) -> value.forEach(el -> featureToStructure.put(el, key)));
}
@@ -0,0 +1,29 @@
package carpet.mixins;
import carpet.CarpetSettings;
import net.minecraft.block.entity.PistonBlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Direction;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PistonBlockEntity.class)
public class PistonBlockEntity_creativeNoClipMixin
{
@Inject(method = "method_23672", at = @At("HEAD"), cancellable = true)
private static void dontPushSpectators(Direction direction, Entity entity, double d, Direction direction2, CallbackInfo ci)
{
if (CarpetSettings.creativeNoClip && entity instanceof PlayerEntity && (((PlayerEntity) entity).isCreative()) && ((PlayerEntity) entity).abilities.flying) ci.cancel();
}
@Redirect(method = "pushEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setVelocity(DDD)V"))
private void ignoreAccel(Entity entity, double x, double y, double z)
{
if (CarpetSettings.creativeNoClip && entity instanceof PlayerEntity && (((PlayerEntity) entity).isCreative()) && ((PlayerEntity) entity).abilities.flying) return;
entity.setVelocity(x,y,z);
}
}
@@ -0,0 +1,56 @@
package carpet.mixins;
import carpet.CarpetSettings;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
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.Redirect;
@Mixin(PlayerEntity.class)
public abstract class PlayerEntity_creativeNoClipMixin extends LivingEntity
{
@Shadow public abstract boolean isCreative();
@Shadow @Final public PlayerAbilities abilities;
protected PlayerEntity_creativeNoClipMixin(EntityType<? extends LivingEntity> type, World world)
{
super(type, world);
}
@Redirect(method = "tick", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/player/PlayerEntity;isSpectator()Z")
)
private boolean canClipTroughWorld(PlayerEntity playerEntity)
{
return playerEntity.isSpectator() || (CarpetSettings.creativeNoClip && playerEntity.isCreative() && playerEntity.abilities.flying);
}
@Redirect(method = "tickMovement", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/player/PlayerEntity;isSpectator()Z")
)
private boolean collidesWithEntities(PlayerEntity playerEntity)
{
return playerEntity.isSpectator() || (CarpetSettings.creativeNoClip && playerEntity.isCreative() && playerEntity.abilities.flying);
}
@Redirect(method = "updateSize", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/player/PlayerEntity;isSpectator()Z")
)
private boolean spectatorsDontPose(PlayerEntity playerEntity)
{
return playerEntity.isSpectator() || (CarpetSettings.creativeNoClip && playerEntity.isCreative() && playerEntity.abilities.flying);
}
}
@@ -0,0 +1,19 @@
package carpet.mixins;
import carpet.CarpetSettings;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.WorldRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(WorldRenderer.class)
public class WorldRenderer_creativeNoClipMixin
{
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSpectator()Z"))
private boolean canSeeWorld(ClientPlayerEntity clientPlayerEntity)
{
return clientPlayerEntity.isSpectator() || (CarpetSettings.creativeNoClip && clientPlayerEntity.isCreative());
}
}
@@ -398,6 +398,32 @@ public class CarpetExpression
}
}
private static Value structureToValue(StructureStart structure)
{
if (structure == null || structure == StructureStart.DEFAULT) return Value.NULL;
List<Value> pieces = new ArrayList<>();
for (StructurePiece piece : structure.getChildren())
{
BlockBox box = piece.getBoundingBox();
pieces.add(ListValue.of(
new StringValue( NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_PIECE.getId(piece.getType()))),
(piece.getFacing()== null)?Value.NULL: new StringValue(piece.getFacing().getName()),
ListValue.fromTriple(box.minX, box.minY, box.minZ),
ListValue.fromTriple(box.maxX, box.maxY, box.maxZ)
));
};
BlockBox boundingBox = structure.getBoundingBox();
Map<Value, Value> ret = new HashMap<>();
ret.put(new StringValue("box"), ListValue.of(
ListValue.fromTriple(boundingBox.minX, boundingBox.minY, boundingBox.minZ),
ListValue.fromTriple(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ)
));
ret.put(new StringValue("pieces"), ListValue.wrap(pieces));
return MapValue.wrap(ret);
}
private void API_BlockManipulation()
{
this.expr.addLazyFunction("block", -1, (c, t, lv) ->
@@ -1148,25 +1174,20 @@ public class CarpetExpression
}
if (structure != null)
{
BlockBox box = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize);
if (box == null) return LazyValue.NULL;
StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize);
if (start == null) return LazyValue.NULL;
if (!needSize) return LazyValue.TRUE;
Value ret = ListValue.of(
ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)),
ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ))
);
Value ret = structureToValue(start);
return (_c, _t) -> ret;
}
Map<Value, Value> ret = new HashMap<>();
for(StructureFeature<?> str : Feature.STRUCTURES.values())
{
BlockBox box = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize);
if (box == null) continue;
StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize);
if (start == null) continue;
Value key = new StringValue(FeatureGenerator.structureToFeature.get(str.getName()).get(0));
ret.put(key, (!needSize)?Value.NULL:ListValue.of(
ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)),
ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ))
));
ret.put(key, (!needSize)?Value.NULL:structureToValue(start));
}
Value retMap = MapValue.wrap(ret);
return (_c, _t) -> retMap;
@@ -1188,28 +1209,17 @@ public class CarpetExpression
if (start == StructureStart.DEFAULT)
continue;
BlockBox box = start.getBoundingBox();
ListValue coord1 = ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ));
ListValue coord2 = ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ));
structureList.put(new StringValue(FeatureGenerator.structureToFeature.get(entry.getKey()).get(0)), ListValue.of(coord1, coord2));
structureList.put(
new StringValue(FeatureGenerator.structureToFeature.get(entry.getKey()).get(0)),
ListValue.of(ListValue.fromTriple(box.minX, box.minY, box.minZ), ListValue.fromTriple(box.maxX, box.maxY, box.maxZ))
);
}
Value ret = MapValue.wrap(structureList);
return (_c, _t) -> ret;
}
String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT);
StructureStart start = structures.get(FeatureGenerator.featureToStructure.get(structureName));
if (start == null || start == StructureStart.DEFAULT) return LazyValue.NULL;
List<Value> pieces = new ArrayList<>();
for (StructurePiece piece : start.getChildren())
{
BlockBox box = piece.getBoundingBox();
pieces.add(ListValue.of(
new StringValue( NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_PIECE.getId(piece.getType()))),
(piece.getFacing()== null)?Value.NULL: new StringValue(piece.getFacing().getName()),
ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)),
ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ))
));
}
Value ret = ListValue.wrap(pieces);
Value ret = structureToValue(start);
return (_c, _t) -> ret;
});
@@ -75,6 +75,18 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
);
}
public static Value fromTriple(double a, double b, double c)
{
return ListValue.of(new NumericValue(a), new NumericValue(b), new NumericValue(c));
}
public static Value fromTriple(int a, int b, int c)
{
return fromTriple((double) a, b, c);
}
public static ListValue wrap(List<Value> list)
{
@@ -93,7 +93,7 @@ __structure_renderer(player_name) ->
for (starts, l(position, name) = _;
structure_data = structures(position):name;
if (!structure_data, continue()); // messed up references - shouldn't happen
structure_pieces = structures(position, name);
structure_pieces = structures(position, name):'pieces';
if (!structure_pieces, continue()); // messed up references - shouldn't happen
l(from, to) = structure_data;
total_size = _euclidean(from, to);
+7 -2
View File
@@ -157,7 +157,10 @@
"PistonBlockEntity_movableTEMixin",
"World_movableTEMixin",
"WorldChunk_movableTEMixin",
"PistonHandler_movableTEMixin"
"PistonHandler_movableTEMixin",
"PlayerEntity_creativeNoClipMixin",
"PistonBlockEntity_creativeNoClipMixin"
],
"client": [
"RenderTickCounter_tickSpeedMixin",
@@ -170,7 +173,9 @@
"PistonBlockEntityRenderer_movableTEMixin",
"ClientPlayNetworkHandler_smoothClientAnimationsMixin",
"ClientPlayerEntity_clientCommandMixin",
"WorldRenderer_fogOffMixin"
"WorldRenderer_fogOffMixin",
"WorldRenderer_creativeNoClipMixin"
],
"server": [
"MinecraftDedicatedServerMixin"