This commit is contained in:
gnembon committed 2024-02-29 11:05:15 +01:00
1 parent 2dd8674ea6
commit 4e57eecf2d
37 files changed
+534 -481

No files matched your search

+2 -2
View File
@@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check https://fabricmc.net/develop/
minecraft_version=24w07a
loader_version=0.15.6
minecraft_version=24w09a
loader_version=0.15.7
jsr305_version=3.0.2
fabric_version=0.91.1+1.20.3
@@ -16,6 +16,7 @@ import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.DimensionArgument;
@@ -304,7 +305,7 @@ public class PlayerCommand
private static int maxNameLength(MinecraftServer server)
{
return server.getPort() >= 0 ? Player.MAX_NAME_LENGTH : 40;
return server.getPort() >= 0 ? SharedConstants.MAX_PLAYER_NAME_LENGTH : 40;
}
private static int manipulate(CommandContext<CommandSourceStack> context, Consumer<EntityPlayerActionPack> action)
@@ -1,8 +1,7 @@
package carpet.fakes;
import com.mojang.datafixers.util.Either;
import java.util.concurrent.CompletableFuture;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.level.ChunkPos;
@@ -10,5 +9,5 @@ import net.minecraft.world.level.chunk.ChunkAccess;
public interface ChunkHolderInterface
{
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> setDefaultProtoChunk(ChunkPos chpos, BlockableEventLoop<Runnable> executor, ServerLevel world);
CompletableFuture<ChunkResult<ChunkAccess>> setDefaultProtoChunk(ChunkPos chpos, BlockableEventLoop<Runnable> executor, ServerLevel world);
}
@@ -1,8 +1,9 @@
package carpet.mixins;
import carpet.fakes.ChunkHolderInterface;
import com.mojang.datafixers.util.Either;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ChunkResult;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -14,23 +15,22 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
@Mixin(ChunkHolder.class)
public abstract class ChunkHolder_scarpetChunkCreationMixin implements ChunkHolderInterface
{
@Shadow protected abstract void updateChunkToSave(CompletableFuture<? extends Either<? extends ChunkAccess, ChunkHolder.ChunkLoadingFailure>> newChunkFuture, String type);
@Shadow protected abstract void updateChunkToSave(CompletableFuture<? extends ChunkResult<? extends ChunkAccess>> newChunkFuture, String type);
@Shadow @Final private AtomicReferenceArray<CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> futures;
@Shadow @Final private AtomicReferenceArray<CompletableFuture<ChunkResult<ChunkAccess>>> futures;
@Override
public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> setDefaultProtoChunk(ChunkPos chpos, BlockableEventLoop<Runnable> executor, ServerLevel world)
public CompletableFuture<ChunkResult<ChunkAccess>> setDefaultProtoChunk(ChunkPos chpos, BlockableEventLoop<Runnable> executor, ServerLevel world)
{
int i = ChunkStatus.EMPTY.getIndex();
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completableFuture2 = CompletableFuture.supplyAsync(
() -> Either.left(new ProtoChunk(chpos, UpgradeData.EMPTY, world, world.registryAccess().registryOrThrow(Registries.BIOME), null)), // todo figure out what that does - maybe add an option to reset with blending enabled..?
CompletableFuture<ChunkResult<ChunkAccess>> completableFuture2 = CompletableFuture.supplyAsync(
() -> ChunkResult.of(new ProtoChunk(chpos, UpgradeData.EMPTY, world, world.registryAccess().registryOrThrow(Registries.BIOME), null)), // todo figure out what that does - maybe add an option to reset with blending enabled..?
executor
);
updateChunkToSave(completableFuture2, "unfull"); // possible debug data
@@ -19,9 +19,9 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.TickTask;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkHolder.ChunkLoadingFailure;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkMap.DistanceManager;
import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
@@ -32,8 +32,8 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.storage.RegionFile;
import org.apache.commons.lang3.tuple.Pair;
import org.spongepowered.asm.mixin.Final;
@@ -44,8 +44,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.mojang.datafixers.util.Either;
import carpet.fakes.ChunkHolderInterface;
import carpet.fakes.ChunkTicketManagerInterface;
import carpet.fakes.ServerLightingProviderInterface;
@@ -104,7 +102,8 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
protected abstract Iterable<ChunkHolder> getChunks();
@Shadow protected abstract CompletableFuture<Either<List<ChunkAccess>, ChunkLoadingFailure>> getChunkRangeFuture(final ChunkHolder chunkHolder, final int i, final IntFunction<ChunkStatus> intFunction);
@Shadow
protected abstract CompletableFuture<ChunkResult<List<ChunkAccess>>> getChunkRangeFuture(ChunkHolder chunkHolder, int i, IntFunction<ChunkStatus> intFunction);
//@Shadow protected abstract void postLoadProtoChunk(final ServerLevel serverLevel, final List<CompoundTag> list);
@@ -112,8 +111,8 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
// in protoChunkToFullChunk
// fancier version of the one below, ensuring that the event is triggered when the chunk is actually loaded.
@Inject(method = "method_20460", at = @At("HEAD"), remap = false)
private void onChunkGeneratedStart(ChunkHolder chunkHolder, Either<ChunkAccess, ChunkLoadingFailure> chunk, CallbackInfoReturnable<CompletableFuture<Either<ChunkAccess, ChunkLoadingFailure>>> cir)
@Inject(method = "method_17227", at = @At("HEAD"), remap = false)
private void onChunkGeneratedStart(ChunkHolder chunkHolder, ChunkAccess chunkAccess, CallbackInfoReturnable<ChunkAccess> cir)
{
if (CHUNK_GENERATED.isNeeded() || CHUNK_LOADED.isNeeded())
{
@@ -125,27 +124,31 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
}
}
@Inject(method = "method_20460", at = @At("RETURN"), remap = false)
private void onChunkGeneratedEnd(ChunkHolder chunkHolder, Either<ChunkAccess, ChunkLoadingFailure> chunk, CallbackInfoReturnable<CompletableFuture<Either<ChunkAccess, ChunkLoadingFailure>>> cir)
@Inject(method = "method_17227", at = @At("RETURN"), remap = false)
private void onChunkGeneratedEnd(ChunkHolder chunkHolder, ChunkAccess chunk, CallbackInfoReturnable<CompletableFuture<ChunkResult<ChunkAccess>>> cir)
{
Boolean localGenerated= generated.get();
Boolean localGenerated = generated.get();
if (localGenerated != null)
{
MinecraftServer server = this.level.getServer();
MinecraftServer server = this.level.getServer();
int ticks = server.getTickCount();
ChunkPos chpos = chunkHolder.getPos();
// need to send these because if an app does something with that event, it may lock the thread
// so better be safe and schedule it for later, aSaP
if (CHUNK_GENERATED.isNeeded() && localGenerated)
server.tell(new TickTask(ticks, () -> CHUNK_GENERATED.onChunkEvent(this.level, chpos, true)));
{
server.tell(new TickTask(ticks, () -> CHUNK_GENERATED.onChunkEvent(this.level, chpos, true)));
}
if (CHUNK_LOADED.isNeeded())
server.tell(new TickTask(ticks, () -> CHUNK_LOADED.onChunkEvent(this.level, chpos, localGenerated)));
{
server.tell(new TickTask(ticks, () -> CHUNK_LOADED.onChunkEvent(this.level, chpos, localGenerated)));
}
}
}
/* simple but a version that doesn't guarantee that the chunk is actually loaded
@Inject(method = "convertToFullChunk", at = @At("HEAD"))
private void onChunkGeneratedEnd(ChunkHolder chunkHolder, CallbackInfoReturnable<CompletableFuture<Either<Chunk, Unloaded>>> cir)
private void onChunkGeneratedEnd(ChunkHolder chunkHolder, CallbackInfoReturnable<CompletableFuture<ChunkResult<ChunkAccess>>> cir)
{
if (CHUNK_GENERATED.isNeeded() && chunkHolder.getCurrentChunk().getStatus() != ChunkStatus.FULL)
{
@@ -162,29 +165,29 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
*/
@Unique
private void addTicket(final ChunkPos pos, final ChunkStatus status)
private void addTicket(ChunkPos pos, ChunkStatus status)
{ // UNKNOWN
this.distanceManager.addTicket(TicketType.UNKNOWN, pos, 33 + ChunkStatus.getDistance(status), pos);
}
@Unique
private void addTicket(final ChunkPos pos)
private void addTicket(ChunkPos pos)
{
this.addTicket(pos, ChunkStatus.EMPTY);
}
@Unique
private void addRelightTicket(final ChunkPos pos)
private void addRelightTicket(ChunkPos pos)
{
this.distanceManager.addRegionTicket(TicketType.LIGHT, pos, 1, pos);
}
@Override
public void releaseRelightTicket(final ChunkPos pos)
public void releaseRelightTicket(ChunkPos pos)
{
this.mainThreadExecutor.tell(Util.name(
() -> this.distanceManager.removeRegionTicket(TicketType.LIGHT, pos, 1, pos),
() -> "release relight ticket " + pos
() -> this.distanceManager.removeRegionTicket(TicketType.LIGHT, pos, 1, pos),
() -> "release relight ticket " + pos
));
}
@@ -195,57 +198,69 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
}
@Unique
private Set<ChunkPos> getExistingChunks(final Set<ChunkPos> requestedChunks)
private Set<ChunkPos> getExistingChunks(Set<ChunkPos> requestedChunks)
{
final Map<String, RegionFile> regionCache = new HashMap<>();
final Set<ChunkPos> ret = new HashSet<>();
Map<String, RegionFile> regionCache = new HashMap<>();
Set<ChunkPos> ret = new HashSet<>();
for (final ChunkPos pos : requestedChunks)
for (ChunkPos pos : requestedChunks)
{
if (WorldTools.canHasChunk(this.level, pos, regionCache, true))
{
ret.add(pos);
}
}
return ret;
}
@Unique
private Set<ChunkPos> loadExistingChunksFromDisk(final Set<ChunkPos> requestedChunks)
private Set<ChunkPos> loadExistingChunksFromDisk(Set<ChunkPos> requestedChunks)
{
final Set<ChunkPos> existingChunks = this.getExistingChunks(requestedChunks);
for (final ChunkPos pos : existingChunks)
Set<ChunkPos> existingChunks = this.getExistingChunks(requestedChunks);
for (ChunkPos pos : existingChunks)
{
this.updatingChunkMap.get(pos.toLong()).getOrScheduleFuture(ChunkStatus.EMPTY, (ChunkMap) (Object) this);
}
return existingChunks;
}
@Unique
private Set<ChunkPos> loadExistingChunks(final Set<ChunkPos> requestedChunks, final Object2IntMap<String> report)
private Set<ChunkPos> loadExistingChunks(Set<ChunkPos> requestedChunks, Object2IntMap<String> report)
{
if (report != null)
{
report.put("requested_chunks", requestedChunks.size());
}
// Load all relevant ChunkHolders into this.currentChunkHolders
// This will not trigger loading from disk yet
for (final ChunkPos pos : requestedChunks)
for (ChunkPos pos : requestedChunks)
{
this.addTicket(pos);
}
this.tickTicketManager();
// Fetch all currently loaded chunks
final Set<ChunkPos> loadedChunks = requestedChunks.stream().filter(
pos -> this.updatingChunkMap.get(pos.toLong()).getLastAvailable() != null // all relevant ChunkHolders exist
Set<ChunkPos> loadedChunks = requestedChunks.stream().filter(
pos -> this.updatingChunkMap.get(pos.toLong()).getLastAvailable() != null // all relevant ChunkHolders exist
).collect(Collectors.toSet());
if (report != null)
{
report.put("loaded_chunks", loadedChunks.size());
}
// Load remaining chunks from disk
final Set<ChunkPos> unloadedChunks = new HashSet<>(requestedChunks);
Set<ChunkPos> unloadedChunks = new HashSet<>(requestedChunks);
unloadedChunks.removeAll(loadedChunks);
final Set<ChunkPos> existingChunks = this.loadExistingChunksFromDisk(unloadedChunks);
Set<ChunkPos> existingChunks = this.loadExistingChunksFromDisk(unloadedChunks);
existingChunks.addAll(loadedChunks);
@@ -253,27 +268,27 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
}
@Unique
private Set<ChunkPos> loadExistingChunks(final Set<ChunkPos> requestedChunks)
private Set<ChunkPos> loadExistingChunks(Set<ChunkPos> requestedChunks)
{
return this.loadExistingChunks(requestedChunks, null);
}
@Unique
private void waitFor(final Future<?> future)
private void waitFor(Future<?> future)
{
this.mainThreadExecutor.managedBlock(future::isDone);
}
@Unique
private void waitFor(final List<? extends CompletableFuture<?>> futures)
private void waitFor(List<? extends CompletableFuture<?>> futures)
{
this.waitFor(Util.sequenceFailFast(futures));
}
@Unique
private ChunkAccess getCurrentChunk(final ChunkPos pos)
private ChunkAccess getCurrentChunk(ChunkPos pos)
{
final CompletableFuture<ChunkAccess> future = this.updatingChunkMap.get(pos.toLong()).getChunkToSave();
CompletableFuture<ChunkAccess> future = this.updatingChunkMap.get(pos.toLong()).getChunkToSave();
this.waitFor(future);
return future.join();
@@ -285,95 +300,125 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
this.addTicket(pos);
this.tickTicketManager();
if (this.updatingChunkMap.get(pos.toLong()).getLastAvailable() == null) // chunk unloaded
{
if (WorldTools.canHasChunk(this.level, pos, null, true))
{
this.updatingChunkMap.get(pos.toLong()).getOrScheduleFuture(ChunkStatus.EMPTY, (ChunkMap) (Object) this);
final ChunkAccess chunk = this.getCurrentChunk(pos);
if (!(chunk.getStatus().isOrAfter(ChunkStatus.LIGHT.getParent()))) return;
}
}
ChunkAccess chunk = this.getCurrentChunk(pos);
if (!(chunk.getStatus().isOrAfter(ChunkStatus.LIGHT.getParent())))
{
return;
}
((ServerLightingProviderInterface) this.lightEngine).removeLightData(chunk);
this.addRelightTicket(pos);
ChunkHolder chunkHolder = this.updatingChunkMap.get(pos.toLong());
final CompletableFuture<?> lightFuture = this.getChunkRangeFuture(chunkHolder, 1, (pos_) -> ChunkStatus.LIGHT)
.thenCompose(
either -> either.map(
list -> ((ServerLightingProviderInterface) this.lightEngine).relight(chunk),
unloaded -> {
CompletableFuture<?> lightFuture = this.getChunkRangeFuture(chunkHolder, 1, (pos_) -> ChunkStatus.LIGHT)
.thenCompose(results -> {
List<ChunkAccess> depList = results.orElse(null);
if (depList == null)
{
this.releaseRelightTicket(pos);
return CompletableFuture.completedFuture(null);
return CompletableFuture.completedFuture(ChunkResult.error(results::getError));
}
)
((ServerLightingProviderInterface) this.lightEngine).relight(chunk);
return CompletableFuture.completedFuture(ChunkResult.of(depList));
}
);
this.waitFor(lightFuture);
}
@Override
public Map<String, Integer> regenerateChunkRegion(final List<ChunkPos> requestedChunksList)
public Map<String, Integer> regenerateChunkRegion(List<ChunkPos> requestedChunksList)
{
final Object2IntMap<String> report = new Object2IntOpenHashMap<>();
final Set<ChunkPos> requestedChunks = new HashSet<>(requestedChunksList);
Object2IntMap<String> report = new Object2IntOpenHashMap<>();
Set<ChunkPos> requestedChunks = new HashSet<>(requestedChunksList);
// Load requested chunks
final Set<ChunkPos> existingChunks = this.loadExistingChunks(requestedChunks, report);
Set<ChunkPos> existingChunks = this.loadExistingChunks(requestedChunks, report);
// Finish pending generation stages
// This ensures that no generation events will be put back on the main thread after the chunks have been deleted
final Set<ChunkAccess> affectedChunks = new HashSet<>();
Set<ChunkAccess> affectedChunks = new HashSet<>();
for (final ChunkPos pos : existingChunks)
for (ChunkPos pos : existingChunks)
{
affectedChunks.add(this.getCurrentChunk(pos));
}
report.put("affected_chunks", affectedChunks.size());
// Load neighbors for light removal
final Set<ChunkPos> neighbors = new HashSet<>();
Set<ChunkPos> neighbors = new HashSet<>();
for (final ChunkAccess chunk : affectedChunks)
for (ChunkAccess chunk : affectedChunks)
{
final ChunkPos pos = chunk.getPos();
ChunkPos pos = chunk.getPos();
for (int x = -1; x <= 1; ++x)
{
for (int z = -1; z <= 1; ++z)
{
if (x != 0 || z != 0)
{
final ChunkPos nPos = new ChunkPos(pos.x + x, pos.z + z);
ChunkPos nPos = new ChunkPos(pos.x + x, pos.z + z);
if (!requestedChunks.contains(nPos))
{
neighbors.add(nPos);
}
}
}
}
}
this.loadExistingChunks(neighbors);
// Determine affected neighbors
final Set<ChunkAccess> affectedNeighbors = new HashSet<>();
Set<ChunkAccess> affectedNeighbors = new HashSet<>();
for (final ChunkPos pos : neighbors)
for (ChunkPos pos : neighbors)
{
final ChunkAccess chunk = this.getCurrentChunk(pos);
ChunkAccess chunk = this.getCurrentChunk(pos);
if (chunk.getStatus().isOrAfter(ChunkStatus.LIGHT.getParent()))
{
affectedNeighbors.add(chunk);
}
}
// Unload affected chunks
for (final ChunkAccess chunk : affectedChunks)
for (ChunkAccess chunk : affectedChunks)
{
final ChunkPos pos = chunk.getPos();
ChunkPos pos = chunk.getPos();
// remove entities
long longPos = pos.toLong();
if (this.entitiesInLevel.contains(longPos) && chunk instanceof LevelChunk)
((SimpleEntityLookupInterface<Entity>)((ServerWorldInterface)level).getEntityLookupCMPublic()).getChunkEntities(pos).forEach(entity -> { if (!(entity instanceof Player)) entity.discard();});
{
((SimpleEntityLookupInterface<Entity>) ((ServerWorldInterface) level).getEntityLookupCMPublic()).getChunkEntities(pos).forEach(entity -> {
if (!(entity instanceof Player))
{
entity.discard();
}
});
}
if (chunk instanceof LevelChunk)
{
((LevelChunk) chunk).setLoaded(false);
}
if (this.entitiesInLevel.remove(pos.toLong()) && chunk instanceof LevelChunk)
{
this.level.unload((LevelChunk) chunk); // block entities only
}
((ServerLightingProviderInterface) this.lightEngine).invokeUpdateChunkStatus(pos);
((ServerLightingProviderInterface) this.lightEngine).removeLightData(chunk);
@@ -383,13 +428,13 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
// Replace ChunkHolders
for (final ChunkAccess chunk : affectedChunks)
for (ChunkAccess chunk : affectedChunks)
{
final ChunkPos cPos = chunk.getPos();
final long pos = cPos.toLong();
ChunkPos cPos = chunk.getPos();
long pos = cPos.toLong();
final ChunkHolder oldHolder = this.updatingChunkMap.remove(pos);
final ChunkHolder newHolder = new ChunkHolder(cPos, oldHolder.getTicketLevel(), level, this.lightEngine, this.queueSorter, (ChunkHolder.PlayerProvider) this);
ChunkHolder oldHolder = this.updatingChunkMap.remove(pos);
ChunkHolder newHolder = new ChunkHolder(cPos, oldHolder.getTicketLevel(), level, this.lightEngine, this.queueSorter, (ChunkHolder.PlayerProvider) this);
((ChunkHolderInterface) newHolder).setDefaultProtoChunk(cPos, this.mainThreadExecutor, level); // enable chunk blending?
this.updatingChunkMap.put(pos, newHolder);
@@ -400,50 +445,54 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
this.promoteChunkMap();
// Force generation to previous states
// This ensures that the world is in a consistent state after this method
// Also, this is needed to ensure chunks are saved to disk
final Map<ChunkPos, ChunkStatus> targetGenerationStatus = affectedChunks.stream().collect(
Collectors.toMap(ChunkAccess::getPos, ChunkAccess::getStatus)
Map<ChunkPos, ChunkStatus> targetGenerationStatus = affectedChunks.stream().collect(
Collectors.toMap(ChunkAccess::getPos, ChunkAccess::getStatus)
);
for (final Entry<ChunkPos, ChunkStatus> entry : targetGenerationStatus.entrySet())
for (Entry<ChunkPos, ChunkStatus> entry : targetGenerationStatus.entrySet())
{
this.addTicket(entry.getKey(), entry.getValue());
}
this.tickTicketManager();
final List<Pair<ChunkStatus, CompletableFuture<?>>> targetGenerationFutures = new ArrayList<>();
List<Pair<ChunkStatus, CompletableFuture<?>>> targetGenerationFutures = new ArrayList<>();
for (final Entry<ChunkPos, ChunkStatus> entry : targetGenerationStatus.entrySet())
for (Entry<ChunkPos, ChunkStatus> entry : targetGenerationStatus.entrySet())
{
targetGenerationFutures.add(Pair.of(
entry.getValue(),
this.updatingChunkMap.get(entry.getKey().toLong()).getOrScheduleFuture(entry.getValue(), (ChunkMap) (Object) this)
entry.getValue(),
this.updatingChunkMap.get(entry.getKey().toLong()).getOrScheduleFuture(entry.getValue(), (ChunkMap) (Object) this)
));
}
final Map<ChunkStatus, List<CompletableFuture<?>>> targetGenerationFuturesGrouped = targetGenerationFutures.stream().collect(
Collectors.groupingBy(
Pair::getKey,
Collectors.mapping(
Entry::getValue,
Collectors.toList()
Map<ChunkStatus, List<CompletableFuture<?>>> targetGenerationFuturesGrouped = targetGenerationFutures.stream().collect(
Collectors.groupingBy(
Pair::getKey,
Collectors.mapping(
Entry::getValue,
Collectors.toList()
)
)
)
);
for (final ChunkStatus status : ChunkStatus.getStatusList())
for (ChunkStatus status : ChunkStatus.getStatusList())
{
final List<CompletableFuture<?>> futures = targetGenerationFuturesGrouped.get(status);
List<CompletableFuture<?>> futures = targetGenerationFuturesGrouped.get(status);
if (futures == null)
{
continue;
}
String statusName = BuiltInRegistries.CHUNK_STATUS.getKey(status).getPath();
report.put("layer_count_" + statusName, futures.size());
final long start = System.currentTimeMillis();
long start = System.currentTimeMillis();
this.waitFor(futures);
@@ -451,42 +500,46 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
}
report.put("relight_count", affectedNeighbors.size());
// Remove light for affected neighbors
for (final ChunkAccess chunk : affectedNeighbors)
for (ChunkAccess chunk : affectedNeighbors)
{
((ServerLightingProviderInterface) this.lightEngine).removeLightData(chunk);
}
// Schedule relighting of neighbors
for (final ChunkAccess chunk : affectedNeighbors)
for (ChunkAccess chunk : affectedNeighbors)
{
this.addRelightTicket(chunk.getPos());
}
this.tickTicketManager();
final List<CompletableFuture<?>> lightFutures = new ArrayList<>();
List<CompletableFuture<?>> lightFutures = new ArrayList<>();
for (final ChunkAccess chunk : affectedNeighbors)
for (ChunkAccess chunk : affectedNeighbors)
{
final ChunkPos pos = chunk.getPos();
ChunkPos pos = chunk.getPos();
lightFutures.add(this.getChunkRangeFuture (this.updatingChunkMap.get(pos.toLong()), 1, (pos_) -> ChunkStatus.LIGHT).thenCompose(
either -> either.map(
list -> ((ServerLightingProviderInterface) this.lightEngine).relight(chunk),
unloaded -> {
this.releaseRelightTicket(pos);
return CompletableFuture.completedFuture(null);
}
)
lightFutures.add(this.getChunkRangeFuture(this.updatingChunkMap.get(pos.toLong()), 1, (pos_) -> ChunkStatus.LIGHT).thenCompose(
results -> {
List<ChunkAccess> depList = results.orElse(null);
if (depList == null)
{
this.releaseRelightTicket(pos);
return CompletableFuture.completedFuture(ChunkResult.error(results::getError));
}
((ServerLightingProviderInterface) this.lightEngine).relight(chunk);
return CompletableFuture.completedFuture(ChunkResult.of(depList));
}
));
}
final long relightStart = System.currentTimeMillis();
long relightStart = System.currentTimeMillis();
this.waitFor(lightFutures);
@@ -496,7 +549,8 @@ public abstract class ChunkMap_scarpetChunkCreationMixin implements ThreadedAnvi
}
@Override
public Iterable<ChunkHolder> getChunksCM() {
public Iterable<ChunkHolder> getChunksCM()
{
return getChunks();
}
}
@@ -11,7 +11,6 @@ import static carpet.script.CarpetEventServer.Event.PLAYER_PICKS_UP_ITEM;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@Mixin(Inventory.class)
@@ -27,13 +26,11 @@ public abstract class Inventory_scarpetEventMixin
{
if (!PLAYER_PICKS_UP_ITEM.isNeeded() || !(player instanceof ServerPlayer))
return playerInventory.add(-1, stack);
Item item = stack.getItem();
int count = stack.getCount();
boolean res = playerInventory.add(-1, stack);
if (count != stack.getCount()) // res returns false for larger item adding to a almost full ineventory
{
ItemStack diffStack = new ItemStack(item, count - stack.getCount());
diffStack.setTag(stack.getTag());
ItemStack diffStack = stack.copyWithCount(count - stack.getCount());
PLAYER_PICKS_UP_ITEM.onItemAction((ServerPlayer) player, null, diffStack);
}
return res;
@@ -15,8 +15,8 @@ import org.spongepowered.asm.mixin.Mixin;
public class PickaxeItem_missingToolsMixin extends DiggerItem
{
protected PickaxeItem_missingToolsMixin(float attackDamage, float attackSpeed, Tier material, TagKey<Block> tag, Properties settings) {
super(attackDamage, attackSpeed, material, tag, settings);
protected PickaxeItem_missingToolsMixin(Tier material, TagKey<Block> tag, Properties settings) {
super(material, tag, settings);
}
@Override
@@ -106,7 +106,7 @@ public class CarpetClient
ListTag outputTag = (ListTag) tag.get("output");
for (int i = 0; i < outputTag.size(); i++)
{
CarpetSettings.LOG.info(" - response: " + Component.Serializer.fromJson(outputTag.getString(i)).getString());
CarpetSettings.LOG.info(" - response: " + Component.Serializer.fromJson(outputTag.getString(i), clientPlayer.registryAccess()).getString());
}
}
}
@@ -102,7 +102,7 @@ public class ServerNetworkHandler
ListTag outputResult = new ListTag();
for (Component line : output)
{
outputResult.add(StringTag.valueOf(Component.Serializer.toJson(line)));
outputResult.add(StringTag.valueOf(Component.Serializer.toJson(line, player.registryAccess())));
}
if (!output.isEmpty())
{
@@ -15,6 +15,8 @@ import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import carpet.script.CarpetContext;
import net.minecraft.core.RegistryAccess;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ClassUtils;
@@ -32,31 +34,31 @@ import carpet.script.value.Value;
/**
* <p>This class parses methods annotated with the {@link ScarpetFunction} annotation in a given {@link Class}, generating
* fully-featured, automatically parsed and converted functions to be used in the Scarpet language.</p>
*
*
* <p>This class and the rest in this package will try to ensure that the annotated method receives the proper parameters
* directly, without all the always-repeated code of evaluating {@link Value}s, checking and casting them to their respective
* types, and converting them to the final needed object.</p>
*
*
* <p>To do that, functions will save a list of {@link ValueConverter}s to convert all their parameters. {@link ValueConverter}s
* are able to convert from any compatible {@link Value} instance into the requested parameter type, as long as they are registered
* using their respective {@code register} functions.</p>
*
* <p>Built-in {@link ValueConverter}s include but are not limited to converters to convert {@link List}s to actual Java lists while also
*
* <p>Built-in {@link ValueConverter}s include but are not limited to converters to convert {@link List}s to actual Java lists while also
* converting every item inside of the {@link List} to the specified generic parameter ({@code <>}), with the same applying for maps</p>
*
* <p>Parameters can be given the annotations (present in the {@link Locator} and {@link Param} interfaces) in order to restrict them or
*
* <p>Parameters can be given the annotations (present in the {@link Locator} and {@link Param} interfaces) in order to restrict them or
* make them more permissive to accept types, such as {@link Param.AllowSingleton} for lists.</p>
*
*
* <p>You can also declare optional parameters by using Java's {@link Optional} as the type of one of your parameters, though it must be
* at the end of the function, just before varargs if present and/or any other {@link Optional} parameters.</p>
*
*
* <p>Output of the annotated methods will also be converted to a compatible {@link LazyValue} using the registered {@link OutputConverter}s,
* allowing to remove the need of explicitly converting to a {@link Value} and then to a {@link LazyValue} just to end the method (though you can
* return a {@link LazyValue} if you want.</p>
*
*
* <p>For a variable argument count, the Java varargs notation can be used in the last parameter, converting the function into a variable argument
* function that will pass all the rest of parameters to that last varargs parameter, also converted into the specified type.</p>
*
*
* <p>To begin, use the {@link #parseFunctionClass(Class)} method in a class with methods annotated with the {@link ScarpetFunction} annotation.</p>
*
* @see ScarpetFunction
@@ -83,26 +85,26 @@ public final class AnnotationParser
/**
* <p>Parses a given {@link Class} and registers its annotated methods, the ones with the {@link ScarpetFunction} annotation,
* to be used in the Scarpet language.</p>
*
*
* <p><b>Only call this method once per class per lifetime of the JVM!</b> (for example, at {@link carpet.CarpetExtension#onGameStarted()} or
* {@link net.fabricmc.api.ModInitializer#onInitialize()}).</p>
*
*
* <p>There is a set of requirements for the class and its methods:</p>
* <ul>
* <li>Annotated methods must not throw checked exceptions. They can throw regular {@link RuntimeException}s (including but not limited to
* <li>Annotated methods must not throw checked exceptions. They can throw regular {@link RuntimeException}s (including but not limited to
* {@link InternalExpressionException}).
* Basically, it's fine as long as you don't add a {@code throws} declaration to your methods.</li>
* <li>Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
* <li>Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
* annotation. They can still declare an unlimited amount by setting that maximum to {@link ScarpetFunction#UNLIMITED_PARAMS}. "Effectively varargs"
* means a function that has at least a parameter requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
* <li>Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
* <li>Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
* didn't want to support it. Those will crash with a {@code ClassCastException}</li>
* </ul>
* <p>Additionally, if the class contains annotated instance (non-static) methods, the class must be concrete and provide a no-arg constructor
* to instantiate it.</p>
*
* @see ScarpetFunction
*
* @param clazz The class to parse
* @see ScarpetFunction
*/
public static void parseFunctionClass(Class<?> clazz)
{
@@ -119,7 +121,7 @@ public final class AnnotationParser
catch (ReflectiveOperationException e)
{
throw new IllegalArgumentException(
"Couldn't create instance of given " + clazz + ". This is needed for non-static methods. Make sure default constructor is available", e);
"Couldn't create instance of given " + clazz + ". This is needed for non-static methods. Make sure default constructor is available", e);
}
});
Method[] methodz = clazz.getDeclaredMethods();
@@ -132,7 +134,7 @@ public final class AnnotationParser
if (method.getExceptionTypes().length != 0)
{
throw new IllegalArgumentException("Annotated method '" + method.getName() +"', provided in '"+clazz+"' must not declare checked exceptions");
throw new IllegalArgumentException("Annotated method '" + method.getName() + "', provided in '" + clazz + "' must not declare checked exceptions");
}
ParsedFunction function = new ParsedFunction(method, clazz, instanceSupplier);
@@ -143,7 +145,7 @@ public final class AnnotationParser
/**
* <p>Adds all parsed functions to the given {@link Expression}.</p>
* <p>This is handled automatically by Carpet</p>
*
*
* @param expr The expression to add every function to
*/
public static void apply(Expression expr)
@@ -190,7 +192,7 @@ public final class AnnotationParser
}
Class<?> originalVarArgsType = isMethodVarArgs ? methodParameters[methodParamCount - 1].getType().getComponentType() : null;
this.varArgsType = ClassUtils.primitiveToWrapper(originalVarArgsType); // Primitive array cannot be cast to Obj[]
this.primitiveVarArgs = originalVarArgsType != null && originalVarArgsType.isPrimitive();
this.primitiveVarArgs = originalVarArgsType != null && originalVarArgsType.isPrimitive();
this.varArgsConverter = isMethodVarArgs ? ValueConverter.fromAnnotatedType(methodParameters[methodParamCount - 1].getAnnotatedType()) : null;
@SuppressWarnings("unchecked") // Yes. Making a T is not worth
OutputConverter<Object> converter = OutputConverter.get((Class<Object>) method.getReturnType());
@@ -233,7 +235,8 @@ public final class AnnotationParser
MethodHandle tempHandle = MethodHandles.publicLookup().unreflect(method).asFixedArity().asSpreader(Object[].class, this.methodParamCount);
tempHandle = tempHandle.asType(tempHandle.type().changeReturnType(Object.class));
this.handle = Modifier.isStatic(method.getModifiers()) ? tempHandle : tempHandle.bindTo(instance.get());
} catch (IllegalAccessException e)
}
catch (IllegalAccessException e)
{
throw new IllegalArgumentException(e);
}
@@ -245,6 +248,8 @@ public final class AnnotationParser
@Override
public LazyValue apply(Context context, Context.Type t, List<LazyValue> lazyValues)
{
// yes we are making a minecraft dependency, because of the stupid registry access required to parse stuff
RegistryAccess regs = ((CarpetContext) context).registryAccess();
List<Value> lv = AbstractLazyFunction.unpackLazy(lazyValues, context, contextType);
if (isEffectivelyVarArgs)
{
@@ -262,7 +267,7 @@ public final class AnnotationParser
Object[] params = getMethodParams(lv, context, t);
try
{
Value result = outputConverter.convert(handle.invokeExact(params));
Value result = outputConverter.convert(handle.invokeExact(params), regs);
return (cc, tt) -> result;
}
catch (Throwable e)
@@ -306,8 +311,9 @@ public final class AnnotationParser
}
varArgsList.add(obj);
}
varArgs = varArgsList.toArray((Object[])Array.newInstance(varArgsType, 0));
} else
varArgs = varArgsList.toArray((Object[]) Array.newInstance(varArgsType, 0));
}
else
{
varArgs = (Object[]) Array.newInstance(varArgsType, remaining / varArgsConverter.valueConsumption());
for (int i = 0; lvIterator.hasNext(); i++)
@@ -337,7 +343,8 @@ public final class AnnotationParser
builder.append(", ");
builder.append(varArgsConverter.getTypeName());
builder.append("s...)");
} else
}
else
{
builder.append(')');
}
@@ -346,5 +353,7 @@ public final class AnnotationParser
}
}
private AnnotationParser() {}
private AnnotationParser()
{
}
}
@@ -3,9 +3,11 @@ package carpet.script.annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -29,43 +31,43 @@ import javax.annotation.Nullable;
* <p>A converter from a given {@link Object} of type T into a {@link Value}, used in order to convert the outputs of methods into usable Scarpet
* values.</p>
*
* @see #register(Class, Function)
* @see #register(Class, BiFunction)
* @param <T> The type to convert from into a {@link Value}
*/
public final class OutputConverter<T>
{
private static final Map<Class<?>, OutputConverter<?>> byResult = new HashMap<>();
private static final OutputConverter<Value> VALUE = new OutputConverter<>(Function.identity());
private static final OutputConverter<Value> VALUE = new OutputConverter<>((v, regs) -> v);
static
{
// Primitives are handled. Things are boxed in the process anyway, therefore would recommend boxed outputs, so you can use null
register(Void.TYPE, v -> Value.NULL);
register(Boolean.class, BooleanValue::of);
register(Integer.class, NumericValue::new);
register(Integer.class, (v, r) -> new NumericValue(v));
register(Double.class, NumericValue::of);
register(Float.class, NumericValue::of);
register(Long.class, NumericValue::new);
register(Long.class, (v, r) -> new NumericValue(v));
register(String.class, StringValue::new);
register(Entity.class, EntityValue::new);
register(Component.class, FormattedTextValue::new);
register(Tag.class, NBTSerializableValue::new);
register(BlockPos.class, ValueConversions::of);
register(Vec3.class, ValueConversions::of);
register(ItemStack.class, ValueConversions::of);
register(ResourceLocation.class, ValueConversions::of);
register(GlobalPos.class, ValueConversions::of);
register(BlockPos.class, (v, r) -> ValueConversions.of(v));
register(Vec3.class, (v, r) -> ValueConversions.of(v));
register(ItemStack.class, (v, r) -> ValueConversions.of(v, r));
register(ResourceLocation.class, (v, r) -> ValueConversions.of(v));
register(GlobalPos.class, (v, r) -> ValueConversions.of(v));
}
private final Function<T, Value> converter;
private final BiFunction<T, RegistryAccess, Value> converter;
private OutputConverter(Function<T, Value> converter)
private OutputConverter(BiFunction<T, RegistryAccess, Value> converter)
{
this.converter = converter;
}
/**
* <p>Returns the {@link OutputConverter} for the specified returnType.</p>
*
*
* @param <T> The type of the {@link OutputConverter} you are looking for
* @param returnType The class that the returned {@link OutputConverter} converts from
* @return The {@link OutputConverter} for the specified returnType
@@ -85,26 +87,26 @@ public final class OutputConverter<T>
/**
* <p>Converts the given input object into a {@link Value}, to be used in return values of Scarpet functions</p>
*
*
* <p>Returns {@link Value#NULL} if passed a {@code null} input</p>
*
*
* @param input The value to convert
* @return The converted value
*/
public Value convert(@Nullable T input)
public Value convert(@Nullable T input, RegistryAccess regs)
{
return input == null ? Value.NULL : converter.apply(input);
return input == null ? Value.NULL : converter.apply(input, regs);
}
/**
* <p>Registers a new type to be able to be used as the return value of methods, converting from inputType to a {@link Value}
* using the given function.</p>
*
*
* @param <T> The type of the input type
* @param inputType The class of T
* @param converter The function that converts the instance of T to a {@link Value}
*/
public static <T> void register(Class<T> inputType, Function<T, Value> converter)
public static <T> void register(Class<T> inputType, BiFunction<T, RegistryAccess, Value> converter)
{
OutputConverter<T> instance = new OutputConverter<>(converter);
if (byResult.containsKey(inputType))
@@ -113,15 +115,24 @@ public final class OutputConverter<T>
}
byResult.put(inputType, instance);
}
public static <T> void register(Class<T> inputType, Function<T, Value> converter)
{
register(inputType, (v, regs) -> converter.apply(v));
}
/**
* @see #register(Class, Function)
*
* @deprecated Just use {@link #register(Class, Function)}, it now does the same as this
* @see #register(Class, BiFunction)
*
* @deprecated Just use {@link #register(Class, BiFunction)}, it now does the same as this
*/
@Deprecated
public static <T> void registerToValue(Class<T> inputType, Function<T, Value> converter)
public static <T> void registerToValue(Class<T> inputType, BiFunction<T, RegistryAccess, Value> converter)
{
register(inputType, converter);
}
@Deprecated
public static <T> void registerToValue(Class<T> inputType, Function<T, Value> converter)
{
register(inputType, (v, regs) -> converter.apply(v));
}
}
@@ -14,8 +14,6 @@ import carpet.script.argument.FunctionArgument;
import carpet.script.argument.Vector3Argument;
import carpet.script.exception.ExitStatement;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ThrowStatement;
import carpet.script.exception.Throwables;
import carpet.script.external.Carpet;
import carpet.script.utils.SnoopyCommandSource;
import carpet.script.utils.SystemInfo;
@@ -348,7 +346,7 @@ public class Auxiliary
ShapeDispatcher.sendShape(
(playerTargets.isEmpty()) ? cc.level().players() : playerTargets,
shapes
shapes, cc.registryAccess()
);
return Value.TRUE;
});
@@ -475,7 +473,7 @@ public class Auxiliary
return BooleanValue.of(NbtUtils.compareNbt(match, source, numParam == 2 || lv.get(2).getBoolean()));
});
expression.addFunction("encode_nbt", lv -> {
expression.addContextFunction("encode_nbt", -1, (c, t, lv) -> {
int argSize = lv.size();
if (argSize == 0 || argSize > 2)
{
@@ -486,7 +484,7 @@ public class Auxiliary
Tag tag;
try
{
tag = v.toTag(force);
tag = v.toTag(force, ((CarpetContext)c).registryAccess());
}
catch (NBTSerializableValue.IncompatibleTypeException exception)
{
@@ -19,16 +19,15 @@ import carpet.script.value.ScreenValue;
import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import net.minecraft.commands.arguments.item.ItemInput;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
@@ -111,7 +110,7 @@ public class Inventories
type = cc.registry(Registries.RECIPE_TYPE).get(InputValidator.identifierOf(recipeType));
if (type == null)
{
throw new InternalExpressionException("Unknown recipe type: "+recipeType);
throw new InternalExpressionException("Unknown recipe type: " + recipeType);
}
}
List<Recipe<?>> recipes = Vanilla.RecipeManager_getAllMatching(cc.server().getRecipeManager(), type, InputValidator.identifierOf(recipeName), cc.registryAccess());
@@ -125,7 +124,7 @@ public class Inventories
{
ItemStack result = recipe.getResultItem(regs);
List<Value> ingredientValue = new ArrayList<>();
recipe.getIngredients().forEach( ingredient -> {
recipe.getIngredients().forEach(ingredient -> {
// I am flattening ingredient lists per slot.
// consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference
// in depths of lists.
@@ -142,7 +141,7 @@ public class Inventories
}
});
Value recipeSpec;
if (recipe instanceof final ShapedRecipe shapedRecipe)
if (recipe instanceof ShapedRecipe shapedRecipe)
{
recipeSpec = ListValue.of(
new StringValue("shaped"),
@@ -154,7 +153,7 @@ public class Inventories
{
recipeSpec = ListValue.of(new StringValue("shapeless"));
}
else if (recipe instanceof final AbstractCookingRecipe abstractCookingRecipe)
else if (recipe instanceof AbstractCookingRecipe abstractCookingRecipe)
{
recipeSpec = ListValue.of(
new StringValue("smelting"),
@@ -249,9 +248,15 @@ public class Inventories
{
return Value.NULL;
}
int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong();
OptionalInt count = OptionalInt.empty();
Value countVal = lv.get(inventoryLocator.offset() + 1);
if (!countVal.isNull())
{
count = OptionalInt.of((int) NumericValue.asNumber(countVal).getLong());
}
RegistryAccess regs = cc.registryAccess();
if (count == 0)
if (count.isPresent() && count.getAsInt() == 0)
{
// clear slot
ItemStack removedStack = inventoryLocator.inventory().removeItemNoUpdate(slot);
@@ -262,16 +267,16 @@ public class Inventories
{
ItemStack previousStack = inventoryLocator.inventory().getItem(slot);
ItemStack newStack = previousStack.copy();
newStack.setCount(count);
count.ifPresent(newStack::setCount);
inventoryLocator.inventory().setItem(slot, newStack);
syncPlayerInventory(inventoryLocator);
return ValueConversions.of(previousStack, regs);
}
CompoundTag nbt = null; // skipping one argument
CompoundTag nbt = null; // skipping one argument, item name
if (lv.size() > inventoryLocator.offset() + 3)
{
Value nbtValue = lv.get(inventoryLocator.offset() + 3);
if (nbtValue instanceof final NBTSerializableValue nbtsv)
if (nbtValue instanceof NBTSerializableValue nbtsv)
{
nbt = nbtsv.getCompoundTag();
}
@@ -280,17 +285,12 @@ public class Inventories
nbt = new NBTSerializableValue(nbtValue.getString()).getCompoundTag();
}
}
ItemInput newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset() + 2).getString(), nbt, cc.registryAccess());
ItemStack newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset() + 2).getString(), nbt, cc.registryAccess());
count.ifPresent(newitem::setCount);
ItemStack previousStack = inventoryLocator.inventory().getItem(slot);
try
{
inventoryLocator.inventory().setItem(slot, newitem.createItemStack(count, false));
syncPlayerInventory(inventoryLocator);
}
catch (CommandSyntaxException e)
{
throw new InternalExpressionException(e.getMessage());
}
inventoryLocator.inventory().setItem(slot, newitem);
syncPlayerInventory(inventoryLocator);
return ValueConversions.of(previousStack, regs);
});
@@ -303,7 +303,7 @@ public class Inventories
{
return Value.NULL;
}
ItemInput itemArg = null;
ItemStack itemArg = null;
if (lv.size() > inventoryLocator.offset())
{
Value secondArg = lv.get(inventoryLocator.offset());
@@ -342,7 +342,7 @@ public class Inventories
{
throw new InternalExpressionException("'inventory_remove' requires at least an item to be removed");
}
ItemInput searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()).getString(), cc.registryAccess());
ItemStack searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()).getString(), cc.registryAccess());
int amount = 1;
if (lv.size() > inventoryLocator.offset() + 1)
{
@@ -424,7 +424,7 @@ public class Inventories
}
Object owner = inventoryLocator.owner();
ItemEntity item;
if (owner instanceof final Player player)
if (owner instanceof Player player)
{
item = player.drop(droppedStack, false, true);
if (item == null)
@@ -478,7 +478,7 @@ public class Inventories
expression.addContextFunction("close_screen", 1, (c, t, lv) ->
{
Value value = lv.get(0);
if (!(value instanceof final ScreenValue screenValue))
if (!(value instanceof ScreenValue screenValue))
{
throw new InternalExpressionException("'close_screen' requires a screen value as the first argument.");
}
@@ -496,7 +496,7 @@ public class Inventories
{
throw new InternalExpressionException("'screen_property' requires at least a screen and a property name");
}
if (!(lv.get(0) instanceof final ScreenValue screenValue))
if (!(lv.get(0) instanceof ScreenValue screenValue))
{
throw new InternalExpressionException("'screen_property' requires a screen value as the first argument");
}
@@ -38,6 +38,7 @@ import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.QuartPos;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
@@ -51,6 +52,7 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
@@ -121,7 +123,6 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.WorldgenRandom;
@@ -840,6 +841,7 @@ public class WorldAccess
expression.addContextFunction("destroy", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
RegistryAccess regs = cc.registryAccess();
ServerLevel world = cc.level();
BlockArgument locator = BlockArgument.findIn(cc, lv, 0);
BlockState state = locator.block.getBlockState();
@@ -882,11 +884,14 @@ public class WorldAccess
: NBTSerializableValue.parseStringOrFail(tagValue.getString()).getCompoundTag();
}
}
ItemStack tool = new ItemStack(item, 1);
ItemStack tool;
if (tag != null)
{
tool.setTag(tag);
tool = ItemStack.parseOptional(regs, tag);
}
else
{
tool = new ItemStack(item, 1);
}
if (playerBreak && state.getDestroySpeed(world, where) < 0.0)
{
@@ -950,8 +955,7 @@ public class WorldAccess
{
return Value.NULL;
}
Tag outtag = tool.getTag();
return outtag == null ? Value.TRUE : new NBTSerializableValue(() -> outtag);
return new NBTSerializableValue(() -> tool.saveOptional(regs));
});
@@ -1106,7 +1110,7 @@ public class WorldAccess
CarpetContext cc = (CarpetContext) c;
String itemString = lv.get(0).getString();
Vector3Argument locator = Vector3Argument.findIn(lv, 1);
ItemInput stackArg = NBTSerializableValue.parseItem(itemString, cc.registryAccess());
ItemStack stackArg = NBTSerializableValue.parseItem(itemString, cc.registryAccess());
BlockPos where = BlockPos.containing(locator.vec);
// Paintings throw an exception if their direction is vertical, therefore we change the default here
String facing = lv.size() > locator.offset
@@ -1118,15 +1122,7 @@ public class WorldAccess
sneakPlace = lv.get(locator.offset + 1).getBoolean();
}
BlockValue.PlacementContext ctx;
try
{
ctx = BlockValue.PlacementContext.from(cc.level(), where, facing, sneakPlace, stackArg.createItemStack(1, false));
}
catch (CommandSyntaxException e)
{
throw new InternalExpressionException(e.getMessage());
}
BlockValue.PlacementContext ctx = BlockValue.PlacementContext.from(cc.level(), where, facing, sneakPlace, stackArg);
if (!(stackArg.getItem() instanceof final BlockItem blockItem))
{
@@ -1160,7 +1156,7 @@ public class WorldAccess
expression.addContextFunction("blocks_movement", -1, (c, t, lv) ->
booleanStateTest(c, "blocks_movement", lv, (s, p) ->
!s.isPathfindable(((CarpetContext) c).level(), p, PathComputationType.LAND)));
!s.isPathfindable(PathComputationType.LAND)));
expression.addContextFunction("block_sound", -1, (c, t, lv) ->
stateStringQuery(c, "block_sound", lv, (s, p) ->
@@ -144,7 +144,7 @@ public class ShapeDispatcher
return new ShapeWithConfig(ShapeDispatcher.create(server, shapeType, params), params);
}
public static void sendShape(Collection<ServerPlayer> players, List<ShapeWithConfig> shapes)
public static void sendShape(Collection<ServerPlayer> players, List<ShapeWithConfig> shapes, RegistryAccess regs)
{
List<ServerPlayer> clientPlayers = new ArrayList<>();
List<ServerPlayer> alternativePlayers = new ArrayList<>();
@@ -158,7 +158,7 @@ public class ShapeDispatcher
int tagcount = 0;
for (ShapeWithConfig s : shapes)
{
tag.add(ExpiringShape.toTag(s.config())); // 4000 shapes limit boxes
tag.add(ExpiringShape.toTag(s.config(), regs)); // 4000 shapes limit boxes
if (tagcount++ > 1000)
{
tagcount = 0;
@@ -312,11 +312,11 @@ public class ShapeDispatcher
{
}
public static CompoundTag toTag(Map<String, Value> params)
public static CompoundTag toTag(Map<String, Value> params, RegistryAccess regs)
{
CompoundTag tag = new CompoundTag();
params.forEach((k, v) -> {
Tag valTag = Param.of.get(k).toTag(v);
Tag valTag = Param.of.get(k).toTag(v, regs);
if (valTag != null)
{
tag.put(k, valTag);
@@ -724,7 +724,7 @@ public class ShapeDispatcher
}
else
{
this.item = ItemStack.of(((NBTSerializableValue) options.get("item")).getCompoundTag());
this.item = ItemStack.parseOptional(regs, ((NBTSerializableValue) options.get("item")).getCompoundTag());
}
blockLight = NumericValue.asNumber(options.getOrDefault("blocklight", optional.get("blocklight"))).getInt();
if (blockLight > 15)
@@ -1532,7 +1532,7 @@ public class ShapeDispatcher
}
@Nullable
public abstract Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize
public abstract Tag toTag(Value value, final RegistryAccess regs); //validates value, returning null if not necessary to keep it and serialize
public abstract Value validate(Map<String, Value> options, MinecraftServer server, Value value); // makes sure the value is proper
@@ -1547,9 +1547,9 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return value.toTag(true);
return value.toTag(true, regs);
}
@Override
@@ -1589,7 +1589,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return StringTag.valueOf(value.getString());
}
@@ -1621,7 +1621,7 @@ public class ShapeDispatcher
@Nullable
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
if (value instanceof final BlockValue blv)
{
@@ -1661,11 +1661,11 @@ public class ShapeDispatcher
public Value validate(Map<String, Value> options, MinecraftServer server, Value value)
{
ItemStack item = ValueConversions.getItemStackFromValue(value, true, server.registryAccess());
return new NBTSerializableValue(item.save(new CompoundTag()));
return new NBTSerializableValue(item.save(server.registryAccess()));
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return ((NBTSerializableValue) value).getTag();
}
@@ -1710,19 +1710,19 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
if (!(value instanceof FormattedTextValue))
{
value = new FormattedTextValue(Component.literal(value.getString()));
}
return StringTag.valueOf(((FormattedTextValue) value).serialize());
return StringTag.valueOf(((FormattedTextValue) value).serialize(regs));
}
@Override
public Value decode(Tag tag, Level level)
{
return FormattedTextValue.deserialize(tag.getAsString());
return FormattedTextValue.deserialize(tag.getAsString(), level.registryAccess());
}
}
@@ -1808,7 +1808,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return ByteTag.valueOf(value.getBoolean());
}
@@ -1834,7 +1834,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat());
}
@@ -1873,7 +1873,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat());
}
@@ -1894,7 +1894,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return IntTag.valueOf(NumericValue.asNumber(value, id).getInt());
}
@@ -1915,7 +1915,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return IntTag.valueOf(NumericValue.asNumber(value, id).getInt());
}
@@ -1946,7 +1946,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat());
}
@@ -2041,7 +2041,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
List<Value> lv = ((ListValue) value).getItems();
ListTag tag = new ListTag();
@@ -2092,7 +2092,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value pointsValue)
public Tag toTag(Value pointsValue, final RegistryAccess regs)
{
List<Value> lv = ((ListValue) pointsValue).getItems();
ListTag ltag = new ListTag();
@@ -2124,7 +2124,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return IntTag.valueOf(NumericValue.asNumber(value, id).getInt());
}
@@ -2139,7 +2139,7 @@ public class ShapeDispatcher
}
@Override
public Tag toTag(Value value)
public Tag toTag(Value value, final RegistryAccess regs)
{
return IntTag.valueOf(NumericValue.asNumber(value, id).getInt());
}
@@ -23,8 +23,8 @@ import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
import net.minecraft.world.level.border.BorderChangeListener;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.storage.RegionFile;
import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
import net.minecraft.world.level.dimension.DimensionType;
@@ -21,6 +21,7 @@ import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
@@ -41,7 +42,6 @@ import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import static carpet.script.value.NBTSerializableValue.nameFromRegistryId;
import static carpet.script.value.NBTSerializableValue.nameFromResource;
public class BlockValue extends Value
@@ -240,7 +240,7 @@ public class BlockValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
@@ -2,6 +2,7 @@ package carpet.script.value;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.Tag;
@@ -54,7 +55,7 @@ public class BooleanValue extends NumericValue
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
return ByteTag.valueOf(boolValue);
}
+120 -119
View File
@@ -131,7 +131,7 @@ public class EntityValue extends Value
public Entity getEntity()
{
if (entity instanceof final ServerPlayer serverPlayer && Vanilla.ServerPlayer_isInvalidEntityObject(serverPlayer))
if (entity instanceof ServerPlayer serverPlayer && Vanilla.ServerPlayer_isInvalidEntityObject(serverPlayer))
{
ServerPlayer newPlayer = entity.getServer().getPlayerList().getPlayer(entity.getUUID());
if (newPlayer != null)
@@ -144,7 +144,7 @@ public class EntityValue extends Value
public static ServerPlayer getPlayerByValue(MinecraftServer server, Value value)
{
if (value instanceof final EntityValue ev && ev.getEntity() instanceof final ServerPlayer sp)
if (value instanceof EntityValue ev && ev.getEntity() instanceof ServerPlayer sp)
{
return sp;
}
@@ -158,7 +158,7 @@ public class EntityValue extends Value
public static String getPlayerNameByValue(Value value)
{
if (value instanceof final EntityValue ev && ev.getEntity() instanceof final ServerPlayer sp)
if (value instanceof EntityValue ev && ev.getEntity() instanceof ServerPlayer sp)
{
return sp.getScoreboardName();
}
@@ -184,7 +184,7 @@ public class EntityValue extends Value
@Override
public boolean equals(Object v)
{
if (v instanceof final EntityValue ev)
if (v instanceof EntityValue ev)
{
return getEntity().getId() == ev.getEntity().getId();
}
@@ -194,7 +194,7 @@ public class EntityValue extends Value
@Override
public Value in(Value v)
{
if (v instanceof final ListValue lv)
if (v instanceof ListValue lv)
{
List<Value> values = lv.getItems();
String what = values.get(0).getString();
@@ -478,7 +478,7 @@ public class EntityValue extends Value
put("yaw", (e, a) -> new NumericValue(e.getYRot()));
put("head_yaw", (e, a) -> e instanceof LivingEntity ? new NumericValue(e.getYHeadRot()) : Value.NULL);
put("body_yaw", (e, a) -> e instanceof final LivingEntity le ? new NumericValue(le.yBodyRot) : Value.NULL);
put("body_yaw", (e, a) -> e instanceof LivingEntity le ? new NumericValue(le.yBodyRot) : Value.NULL);
put("pitch", (e, a) -> new NumericValue(e.getXRot()));
put("look", (e, a) -> {
@@ -500,19 +500,19 @@ public class EntityValue extends Value
put("width", (e, a) -> new NumericValue(e.getDimensions(Pose.STANDING).width()));
put("eye_height", (e, a) -> new NumericValue(e.getEyeHeight()));
put("age", (e, a) -> new NumericValue(e.tickCount));
put("breeding_age", (e, a) -> e instanceof final AgeableMob am ? new NumericValue(am.getAge()) : Value.NULL);
put("despawn_timer", (e, a) -> e instanceof final LivingEntity le ? new NumericValue(le.getNoActionTime()) : Value.NULL);
put("blue_skull", (e, a) -> e instanceof final WitherSkull w ? BooleanValue.of(w.isDangerous()) : Value.NULL);
put("offering_flower", (e, a) -> e instanceof final IronGolem ig ? BooleanValue.of(ig.getOfferFlowerTick() > 0) : Value.NULL);
put("item", (e, a) -> e instanceof final ItemEntity ie ? ValueConversions.of(ie.getItem(), e.getServer().registryAccess()) : e instanceof final ItemFrame frame ? ValueConversions.of(frame.getItem(), e.getServer().registryAccess()) : Value.NULL);
put("count", (e, a) -> (e instanceof final ItemEntity ie) ? new NumericValue(ie.getItem().getCount()) : Value.NULL);
put("pickup_delay", (e, a) -> (e instanceof final ItemEntity ie) ? new NumericValue(Vanilla.ItemEntity_getPickupDelay(ie)) : Value.NULL);
put("breeding_age", (e, a) -> e instanceof AgeableMob am ? new NumericValue(am.getAge()) : Value.NULL);
put("despawn_timer", (e, a) -> e instanceof LivingEntity le ? new NumericValue(le.getNoActionTime()) : Value.NULL);
put("blue_skull", (e, a) -> e instanceof WitherSkull w ? BooleanValue.of(w.isDangerous()) : Value.NULL);
put("offering_flower", (e, a) -> e instanceof IronGolem ig ? BooleanValue.of(ig.getOfferFlowerTick() > 0) : Value.NULL);
put("item", (e, a) -> e instanceof ItemEntity ie ? ValueConversions.of(ie.getItem(), e.getServer().registryAccess()) : e instanceof ItemFrame frame ? ValueConversions.of(frame.getItem(), e.getServer().registryAccess()) : Value.NULL);
put("count", (e, a) -> (e instanceof ItemEntity ie) ? new NumericValue(ie.getItem().getCount()) : Value.NULL);
put("pickup_delay", (e, a) -> (e instanceof ItemEntity ie) ? new NumericValue(Vanilla.ItemEntity_getPickupDelay(ie)) : Value.NULL);
put("portal_cooldown", (e, a) -> new NumericValue(Vanilla.Entity_getPublicNetherPortalCooldown(e)));
put("portal_timer", (e, a) -> new NumericValue(Vanilla.Entity_getPortalTimer(e)));
// ItemEntity -> despawn timer via ssGetAge
put("is_baby", (e, a) -> (e instanceof final LivingEntity le) ? BooleanValue.of(le.isBaby()) : Value.NULL);
put("is_baby", (e, a) -> (e instanceof LivingEntity le) ? BooleanValue.of(le.isBaby()) : Value.NULL);
put("target", (e, a) -> {
if (e instanceof final Mob mob)
if (e instanceof Mob mob)
{
LivingEntity target = mob.getTarget(); // there is also getAttacking in living....
if (target != null)
@@ -522,9 +522,9 @@ public class EntityValue extends Value
}
return Value.NULL;
});
put("home", (e, a) -> e instanceof final Mob mob ? (mob.getRestrictRadius() > 0) ? new BlockValue(null, (ServerLevel) e.level(), mob.getRestrictCenter()) : Value.FALSE : Value.NULL);
put("home", (e, a) -> e instanceof Mob mob ? (mob.getRestrictRadius() > 0) ? new BlockValue(null, (ServerLevel) e.level(), mob.getRestrictCenter()) : Value.FALSE : Value.NULL);
put("spawn_point", (e, a) -> {
if (e instanceof final ServerPlayer spe)
if (e instanceof ServerPlayer spe)
{
if (spe.getRespawnPosition() == null)
{
@@ -543,22 +543,22 @@ public class EntityValue extends Value
put("sneaking", (e, a) -> e.isShiftKeyDown() ? Value.TRUE : Value.FALSE);
put("sprinting", (e, a) -> e.isSprinting() ? Value.TRUE : Value.FALSE);
put("swimming", (e, a) -> e.isSwimming() ? Value.TRUE : Value.FALSE);
put("swinging", (e, a) -> e instanceof final LivingEntity le ? BooleanValue.of(le.swinging) : Value.NULL);
put("swinging", (e, a) -> e instanceof LivingEntity le ? BooleanValue.of(le.swinging) : Value.NULL);
put("air", (e, a) -> new NumericValue(e.getAirSupply()));
put("language", (e, a) -> !(e instanceof final ServerPlayer p) ? NULL : StringValue.of(Vanilla.ServerPlayer_getLanguage(p)));
put("persistence", (e, a) -> e instanceof final Mob mob ? BooleanValue.of(mob.isPersistenceRequired()) : Value.NULL);
put("hunger", (e, a) -> e instanceof final Player player ? new NumericValue(player.getFoodData().getFoodLevel()) : Value.NULL);
put("saturation", (e, a) -> e instanceof final Player player ? new NumericValue(player.getFoodData().getSaturationLevel()) : Value.NULL);
put("exhaustion", (e, a) -> e instanceof final Player player ? new NumericValue(player.getFoodData().getExhaustionLevel()) : Value.NULL);
put("absorption", (e, a) -> e instanceof final Player player ? new NumericValue(player.getAbsorptionAmount()) : Value.NULL);
put("xp", (e, a) -> e instanceof final Player player ? new NumericValue(player.totalExperience) : Value.NULL);
put("xp_level", (e, a) -> e instanceof final Player player ? new NumericValue(player.experienceLevel) : Value.NULL);
put("xp_progress", (e, a) -> e instanceof final Player player ? new NumericValue(player.experienceProgress) : Value.NULL);
put("score", (e, a) -> e instanceof final Player player ? new NumericValue(player.getScore()) : Value.NULL);
put("jumping", (e, a) -> e instanceof final LivingEntity le ? Vanilla.LivingEntity_isJumping(le) ? Value.TRUE : Value.FALSE : Value.NULL);
put("gamemode", (e, a) -> e instanceof final ServerPlayer sp ? new StringValue(sp.gameMode.getGameModeForPlayer().getName()) : Value.NULL);
put("language", (e, a) -> !(e instanceof ServerPlayer p) ? NULL : StringValue.of(Vanilla.ServerPlayer_getLanguage(p)));
put("persistence", (e, a) -> e instanceof Mob mob ? BooleanValue.of(mob.isPersistenceRequired()) : Value.NULL);
put("hunger", (e, a) -> e instanceof Player player ? new NumericValue(player.getFoodData().getFoodLevel()) : Value.NULL);
put("saturation", (e, a) -> e instanceof Player player ? new NumericValue(player.getFoodData().getSaturationLevel()) : Value.NULL);
put("exhaustion", (e, a) -> e instanceof Player player ? new NumericValue(player.getFoodData().getExhaustionLevel()) : Value.NULL);
put("absorption", (e, a) -> e instanceof Player player ? new NumericValue(player.getAbsorptionAmount()) : Value.NULL);
put("xp", (e, a) -> e instanceof Player player ? new NumericValue(player.totalExperience) : Value.NULL);
put("xp_level", (e, a) -> e instanceof Player player ? new NumericValue(player.experienceLevel) : Value.NULL);
put("xp_progress", (e, a) -> e instanceof Player player ? new NumericValue(player.experienceProgress) : Value.NULL);
put("score", (e, a) -> e instanceof Player player ? new NumericValue(player.getScore()) : Value.NULL);
put("jumping", (e, a) -> e instanceof LivingEntity le ? Vanilla.LivingEntity_isJumping(le) ? Value.TRUE : Value.FALSE : Value.NULL);
put("gamemode", (e, a) -> e instanceof ServerPlayer sp ? new StringValue(sp.gameMode.getGameModeForPlayer().getName()) : Value.NULL);
put("path", (e, a) -> {
if (e instanceof final Mob mob)
if (e instanceof Mob mob)
{
Path path = mob.getNavigation().getPath();
if (path == null)
@@ -577,7 +577,7 @@ public class EntityValue extends Value
{
return Value.NULL;
}
if (e instanceof final LivingEntity livingEntity)
if (e instanceof LivingEntity livingEntity)
{
Brain<?> brain = livingEntity.getBrain();
Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = brain.getMemories();
@@ -591,9 +591,9 @@ public class EntityValue extends Value
}
return Value.NULL;
});
put("gamemode_id", (e, a) -> e instanceof final ServerPlayer sp ? new NumericValue(sp.gameMode.getGameModeForPlayer().getId()) : Value.NULL);
put("gamemode_id", (e, a) -> e instanceof ServerPlayer sp ? new NumericValue(sp.gameMode.getGameModeForPlayer().getId()) : Value.NULL);
put("permission_level", (e, a) -> {
if (e instanceof final ServerPlayer spe)
if (e instanceof ServerPlayer spe)
{
for (int i = 4; i >= 0; i--)
{
@@ -609,7 +609,7 @@ public class EntityValue extends Value
});
put("player_type", (e, a) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
String moddedType = Carpet.isModdedPlayer(p);
if (moddedType != null)
@@ -637,15 +637,15 @@ public class EntityValue extends Value
return Value.NULL;
});
put("client_brand", (e, a) -> e instanceof final ServerPlayer sp ? StringValue.of(Carpet.getPlayerStatus(sp)) : Value.NULL);
put("client_brand", (e, a) -> e instanceof ServerPlayer sp ? StringValue.of(Carpet.getPlayerStatus(sp)) : Value.NULL);
put("team", (e, a) -> e.getTeam() == null ? Value.NULL : new StringValue(e.getTeam().getName()));
put("ping", (e, a) -> e instanceof final ServerPlayer sp ? new NumericValue(sp.connection.latency()) : Value.NULL);
put("ping", (e, a) -> e instanceof ServerPlayer sp ? new NumericValue(sp.connection.latency()) : Value.NULL);
//spectating_entity
// isGlowing
put("effect", (e, a) ->
{
if (!(e instanceof final LivingEntity le))
if (!(e instanceof LivingEntity le))
{
return Value.NULL;
}
@@ -663,7 +663,7 @@ public class EntityValue extends Value
return ListValue.wrap(effects);
}
String effectName = a.getString();
Holder<MobEffect> potion = BuiltInRegistries.MOB_EFFECT.getHolder(ResourceKey.create(Registries.MOB_EFFECT, InputValidator.identifierOf(effectName))).orElseThrow( () -> new InternalExpressionException("No such an effect: " + effectName));
Holder<MobEffect> potion = BuiltInRegistries.MOB_EFFECT.getHolder(ResourceKey.create(Registries.MOB_EFFECT, InputValidator.identifierOf(effectName))).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName));
if (!le.hasEffect(potion))
{
return Value.NULL;
@@ -672,13 +672,13 @@ public class EntityValue extends Value
return ListValue.of(new NumericValue(pe.getAmplifier()), new NumericValue(pe.getDuration()));
});
put("health", (e, a) -> e instanceof final LivingEntity le ? new NumericValue(le.getHealth()) : Value.NULL);
put("may_fly", (e, a) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().mayfly) : Value.NULL);
put("flying", (e, v) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().flying) : Value.NULL);
put("may_build", (e, v) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().mayBuild) : Value.NULL);
put("insta_build", (e, v) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().instabuild) : Value.NULL);
put("fly_speed", (e, v) -> e instanceof final ServerPlayer player ? NumericValue.of(player.getAbilities().getFlyingSpeed()) : Value.NULL);
put("walk_speed", (e, v) -> e instanceof final ServerPlayer player ? NumericValue.of(player.getAbilities().getWalkingSpeed()) : Value.NULL);
put("health", (e, a) -> e instanceof LivingEntity le ? new NumericValue(le.getHealth()) : Value.NULL);
put("may_fly", (e, a) -> e instanceof ServerPlayer player ? BooleanValue.of(player.getAbilities().mayfly) : Value.NULL);
put("flying", (e, v) -> e instanceof ServerPlayer player ? BooleanValue.of(player.getAbilities().flying) : Value.NULL);
put("may_build", (e, v) -> e instanceof ServerPlayer player ? BooleanValue.of(player.getAbilities().mayBuild) : Value.NULL);
put("insta_build", (e, v) -> e instanceof ServerPlayer player ? BooleanValue.of(player.getAbilities().instabuild) : Value.NULL);
put("fly_speed", (e, v) -> e instanceof ServerPlayer player ? NumericValue.of(player.getAbilities().getFlyingSpeed()) : Value.NULL);
put("walk_speed", (e, v) -> e instanceof ServerPlayer player ? NumericValue.of(player.getAbilities().getWalkingSpeed()) : Value.NULL);
put("holds", (e, a) -> {
EquipmentSlot where = EquipmentSlot.MAINHAND;
if (a != null)
@@ -689,17 +689,17 @@ public class EntityValue extends Value
{
throw new InternalExpressionException("Unknown inventory slot: " + a.getString());
}
if (e instanceof final LivingEntity le)
if (e instanceof LivingEntity le)
{
return ValueConversions.of(le.getItemBySlot(where), e.getServer().registryAccess());
}
return Value.NULL;
});
put("selected_slot", (e, a) -> e instanceof final Player p ? new NumericValue(p.getInventory().selected) : Value.NULL);
put("selected_slot", (e, a) -> e instanceof Player p ? new NumericValue(p.getInventory().selected) : Value.NULL);
put("active_block", (e, a) -> {
if (e instanceof final ServerPlayer sp)
if (e instanceof ServerPlayer sp)
{
BlockPos pos = Vanilla.ServerPlayerGameMode_getCurrentBlockPosition(sp.gameMode);
if (pos == null)
@@ -712,9 +712,9 @@ public class EntityValue extends Value
});
put("breaking_progress", (e, a) -> {
if (e instanceof final ServerPlayer sp)
if (e instanceof ServerPlayer sp)
{
int progress = Vanilla.ServerPlayerGameMode_getCurrentBlockBreakingProgress (sp.gameMode);
int progress = Vanilla.ServerPlayerGameMode_getCurrentBlockBreakingProgress(sp.gameMode);
return progress < 0 ? Value.NULL : new NumericValue(progress);
}
return Value.NULL;
@@ -745,7 +745,7 @@ public class EntityValue extends Value
if (a != null)
{
if (!(a instanceof final ListValue lv))
if (!(a instanceof ListValue lv))
{
reach = (float) NumericValue.asNumber(a).getDouble();
}
@@ -789,7 +789,7 @@ public class EntityValue extends Value
}
}
}
else if (e instanceof final ServerPlayer sp && sp.gameMode.isCreative())
else if (e instanceof ServerPlayer sp && sp.gameMode.isCreative())
{
reach = 5.0f;
}
@@ -829,7 +829,7 @@ public class EntityValue extends Value
});
put("attribute", (e, a) -> {
if (!(e instanceof final LivingEntity el))
if (!(e instanceof LivingEntity el))
{
return Value.NULL;
}
@@ -896,7 +896,7 @@ public class EntityValue extends Value
{
return;
}
if (e instanceof final ServerPlayer sp)
if (e instanceof ServerPlayer sp)
{
// this forces position but doesn't angles for some reason. Need both in the API in the future.
EnumSet<RelativeMovement> set = EnumSet.noneOf(RelativeMovement.class);
@@ -909,7 +909,7 @@ public class EntityValue extends Value
e.moveTo(x, y, z, yaw, pitch);
// we were sending to players for not-living entites, that were untracked. Living entities should be tracked.
//((ServerWorld) e.getEntityWorld()).getChunkManager().sendToNearbyPlayers(e, new EntityS2CPacket.(e));
if (e instanceof final LivingEntity le)
if (e instanceof LivingEntity le)
{
le.yBodyRotO = le.yRotO = yaw;
le.yHeadRotO = le.yHeadRot = yaw;
@@ -939,7 +939,7 @@ public class EntityValue extends Value
put("age", (e, v) -> e.tickCount = Math.abs((int) NumericValue.asNumber(v).getLong()));
put("health", (e, v) -> {
float health = (float) NumericValue.asNumber(v).getDouble();
if (health <= 0f && e instanceof final ServerPlayer player)
if (health <= 0f && e instanceof ServerPlayer player)
{
if (player.containerMenu != null)
{
@@ -950,7 +950,7 @@ public class EntityValue extends Value
}
((LivingEntity) e).setHealth(health);
}
if (e instanceof final LivingEntity le)
if (e instanceof LivingEntity le)
{
le.setHealth(health);
}
@@ -958,7 +958,7 @@ public class EntityValue extends Value
put("may_fly", (e, v) -> {
boolean mayFly = v.getBoolean();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().mayfly = mayFly;
if (!mayFly && player.getAbilities().flying)
@@ -971,7 +971,7 @@ public class EntityValue extends Value
put("flying", (e, v) -> {
boolean flying = v.getBoolean();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().flying = flying;
player.onUpdateAbilities();
@@ -980,7 +980,7 @@ public class EntityValue extends Value
put("may_build", (e, v) -> {
boolean mayBuild = v.getBoolean();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().mayBuild = mayBuild;
player.onUpdateAbilities();
@@ -989,7 +989,7 @@ public class EntityValue extends Value
put("insta_build", (e, v) -> {
boolean instaBuild = v.getBoolean();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().instabuild = instaBuild;
player.onUpdateAbilities();
@@ -998,7 +998,7 @@ public class EntityValue extends Value
put("fly_speed", (e, v) -> {
float flySpeed = NumericValue.asNumber(v).getFloat();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().setFlyingSpeed(flySpeed);
player.onUpdateAbilities();
@@ -1007,7 +1007,7 @@ public class EntityValue extends Value
put("walk_speed", (e, v) -> {
float walkSpeed = NumericValue.asNumber(v).getFloat();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().setWalkingSpeed(walkSpeed);
player.onUpdateAbilities();
@@ -1016,7 +1016,7 @@ public class EntityValue extends Value
put("selected_slot", (e, v) ->
{
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
int slot = NumericValue.asNumber(v).getInt();
player.connection.send(new ClientboundSetCarriedItemPacket(slot));
@@ -1041,7 +1041,7 @@ public class EntityValue extends Value
put("kill", (e, v) -> e.kill());
put("location", (e, v) ->
{
if (!(v instanceof final ListValue lv))
if (!(v instanceof ListValue lv))
{
throw new InternalExpressionException("Expected a list of 5 parameters as a second argument");
}
@@ -1056,7 +1056,7 @@ public class EntityValue extends Value
});
put("pos", (e, v) ->
{
if (!(v instanceof final ListValue lv))
if (!(v instanceof ListValue lv))
{
throw new InternalExpressionException("Expected a list of 3 parameters as a second argument");
}
@@ -1091,7 +1091,7 @@ public class EntityValue extends Value
put("pitch", (e, v) -> updatePosition(e, e.getX(), e.getY(), e.getZ(), e.getYRot(), Mth.clamp((float) NumericValue.asNumber(v).getDouble(), -90, 90)));
put("look", (e, v) -> {
if (!(v instanceof final ListValue lv))
if (!(v instanceof ListValue lv))
{
throw new InternalExpressionException("Expected a list of 3 parameters as a second argument");
}
@@ -1117,7 +1117,7 @@ public class EntityValue extends Value
put("move", (e, v) ->
{
if (!(v instanceof final ListValue lv))
if (!(v instanceof ListValue lv))
{
throw new InternalExpressionException("Expected a list of 3 parameters as a second argument");
}
@@ -1133,7 +1133,7 @@ public class EntityValue extends Value
put("motion", (e, v) ->
{
if (!(v instanceof final ListValue lv))
if (!(v instanceof ListValue lv))
{
throw new InternalExpressionException("Expected a list of 3 parameters as a second argument");
}
@@ -1168,7 +1168,7 @@ public class EntityValue extends Value
put("accelerate", (e, v) ->
{
if (!(v instanceof final ListValue lv))
if (!(v instanceof ListValue lv))
{
throw new InternalExpressionException("Expected a list of 3 parameters as a second argument");
}
@@ -1189,7 +1189,7 @@ public class EntityValue extends Value
return;
}
boolean showName = false;
if (v instanceof final ListValue lv)
if (v instanceof ListValue lv)
{
showName = lv.getItems().get(1).getBoolean();
v = lv.getItems().get(0);
@@ -1200,7 +1200,7 @@ public class EntityValue extends Value
put("persistence", (e, v) ->
{
if (!(e instanceof final Mob mob))
if (!(e instanceof Mob mob))
{
return;
}
@@ -1213,11 +1213,11 @@ public class EntityValue extends Value
put("dismount", (e, v) -> e.stopRiding());
put("mount", (e, v) -> {
if (v instanceof final EntityValue ev)
if (v instanceof EntityValue ev)
{
e.startRiding(ev.getEntity(), true);
}
if (e instanceof final ServerPlayer sp)
if (e instanceof ServerPlayer sp)
{
sp.connection.send(new ClientboundSetPassengersPacket(e));
}
@@ -1229,15 +1229,15 @@ public class EntityValue extends Value
{
throw new InternalExpressionException("'mount_passengers' needs entities to ride");
}
if (v instanceof final EntityValue ev)
if (v instanceof EntityValue ev)
{
ev.getEntity().startRiding(e);
}
else if (v instanceof final ListValue lv)
else if (v instanceof ListValue lv)
{
for (Value element : lv.getItems())
{
if (element instanceof final EntityValue ev)
if (element instanceof EntityValue ev)
{
ev.getEntity().startRiding(e);
}
@@ -1249,7 +1249,7 @@ public class EntityValue extends Value
{
throw new InternalExpressionException("'tag' requires parameters");
}
if (v instanceof final ListValue lv)
if (v instanceof ListValue lv)
{
for (Value element : lv.getItems())
{
@@ -1266,7 +1266,7 @@ public class EntityValue extends Value
{
throw new InternalExpressionException("'clear_tag' requires parameters");
}
if (v instanceof final ListValue lv)
if (v instanceof ListValue lv)
{
for (Value element : lv.getItems())
{
@@ -1288,20 +1288,20 @@ public class EntityValue extends Value
//});
put("breeding_age", (e, v) ->
{
if (e instanceof final AgeableMob am)
if (e instanceof AgeableMob am)
{
am.setAge((int) NumericValue.asNumber(v).getLong());
}
});
put("talk", (e, v) -> {
// attacks indefinitely
if (e instanceof final Mob mob)
if (e instanceof Mob mob)
{
mob.playAmbientSound();
}
});
put("home", (e, v) -> {
if (!(e instanceof final PathfinderMob ec))
if (!(e instanceof PathfinderMob ec))
{
return;
}
@@ -1321,7 +1321,7 @@ public class EntityValue extends Value
BlockPos pos;
int distance = 16;
if (v instanceof final BlockValue bv)
if (v instanceof BlockValue bv)
{
pos = bv.getPos();
if (pos == null)
@@ -1329,7 +1329,7 @@ public class EntityValue extends Value
throw new InternalExpressionException("Block is not positioned in the world");
}
}
else if (v instanceof final ListValue lv)
else if (v instanceof ListValue lv)
{
List<Value> list = lv.getItems();
Vector3Argument locator = Vector3Argument.findIn(list, 0, false, false);
@@ -1355,7 +1355,7 @@ public class EntityValue extends Value
}); //requires mixing
put("spawn_point", (e, a) -> {
if (!(e instanceof final ServerPlayer spe))
if (!(e instanceof ServerPlayer spe))
{
return;
}
@@ -1363,7 +1363,7 @@ public class EntityValue extends Value
{
spe.setRespawnPosition(null, null, 0, false, false);
}
else if (a instanceof final ListValue lv)
else if (a instanceof ListValue lv)
{
List<Value> params = lv.getItems();
Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false, false);
@@ -1373,7 +1373,7 @@ public class EntityValue extends Value
boolean forced = false;
if (params.size() > blockLocator.offset)
{
Value worldValue = params.get(blockLocator.offset + 0);
Value worldValue = params.get(blockLocator.offset);
world = ValueConversions.dimFromValue(worldValue, spe.getServer()).dimension();
if (params.size() > blockLocator.offset + 1)
{
@@ -1386,7 +1386,7 @@ public class EntityValue extends Value
}
spe.setRespawnPosition(world, pos, angle, forced, false);
}
else if (a instanceof final BlockValue bv)
else if (a instanceof BlockValue bv)
{
if (bv.getPos() == null || bv.getWorld() == null)
{
@@ -1406,7 +1406,7 @@ public class EntityValue extends Value
put("pickup_delay", (e, v) ->
{
if (e instanceof final ItemEntity ie)
if (e instanceof ItemEntity ie)
{
ie.setPickUpDelay((int) NumericValue.asNumber(v).getLong());
}
@@ -1414,7 +1414,7 @@ public class EntityValue extends Value
put("despawn_timer", (e, v) ->
{
if (e instanceof final LivingEntity le)
if (e instanceof LivingEntity le)
{
le.setNoActionTime((int) NumericValue.asNumber(v).getLong());
}
@@ -1440,7 +1440,7 @@ public class EntityValue extends Value
put("ai", (e, v) ->
{
if (e instanceof final Mob mob)
if (e instanceof Mob mob)
{
mob.setNoAi(!v.getBoolean());
}
@@ -1459,7 +1459,7 @@ public class EntityValue extends Value
});
put("effect", (e, v) ->
{
if (!(e instanceof final LivingEntity le))
if (!(e instanceof LivingEntity le))
{
return;
}
@@ -1468,13 +1468,13 @@ public class EntityValue extends Value
le.removeAllEffects();
return;
}
else if (v instanceof final ListValue lv)
else if (v instanceof ListValue lv)
{
List<Value> list = lv.getItems();
if (list.size() >= 1 && list.size() <= 6)
{
String effectName = list.get(0).getString();
Holder<MobEffect> effect = BuiltInRegistries.MOB_EFFECT.getHolder(InputValidator.identifierOf(effectName)).orElseThrow( () -> new InternalExpressionException("No such an effect: " + effectName));
Holder<MobEffect> effect = BuiltInRegistries.MOB_EFFECT.getHolder(InputValidator.identifierOf(effectName)).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName));
if (list.size() == 1)
{
le.removeEffect(effect);
@@ -1486,7 +1486,8 @@ public class EntityValue extends Value
le.removeEffect(effect);
return;
}
if (duration < 0){
if (duration < 0)
{
duration = -1;
}
int amplifier = 0;
@@ -1516,7 +1517,7 @@ public class EntityValue extends Value
else
{
String effectName = v.getString();
Holder<MobEffect> effect = BuiltInRegistries.MOB_EFFECT.getHolder(InputValidator.identifierOf(effectName)).orElseThrow( () -> new InternalExpressionException("No such an effect: " + effectName));
Holder<MobEffect> effect = BuiltInRegistries.MOB_EFFECT.getHolder(InputValidator.identifierOf(effectName)).orElseThrow(() -> new InternalExpressionException("No such an effect: " + effectName));
le.removeEffect(effect);
return;
}
@@ -1524,7 +1525,7 @@ public class EntityValue extends Value
});
put("gamemode", (e, v) -> {
if (!(e instanceof final ServerPlayer sp))
if (!(e instanceof ServerPlayer sp))
{
return;
}
@@ -1538,7 +1539,7 @@ public class EntityValue extends Value
});
put("jumping", (e, v) -> {
if (!(e instanceof final LivingEntity le))
if (!(e instanceof LivingEntity le))
{
return;
}
@@ -1546,7 +1547,7 @@ public class EntityValue extends Value
});
put("jump", (e, v) -> {
if (e instanceof final LivingEntity le)
if (e instanceof LivingEntity le)
{
Vanilla.LivingEntity_setJumping(le);
}
@@ -1557,7 +1558,7 @@ public class EntityValue extends Value
});
put("swing", (e, v) -> {
if (e instanceof final LivingEntity le)
if (e instanceof LivingEntity le)
{
InteractionHand hand = InteractionHand.MAIN_HAND;
if (v != null)
@@ -1578,7 +1579,7 @@ public class EntityValue extends Value
put("invulnerable", (e, v) -> {
boolean invulnerable = v.getBoolean();
if (e instanceof final ServerPlayer player)
if (e instanceof ServerPlayer player)
{
player.getAbilities().invulnerable = invulnerable;
player.onUpdateAbilities();
@@ -1593,49 +1594,49 @@ public class EntityValue extends Value
put("frost", (e, v) -> e.setTicksFrozen((int) NumericValue.asNumber(v).getLong()));
put("hunger", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.getFoodData().setFoodLevel((int) NumericValue.asNumber(v).getLong());
}
});
put("exhaustion", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.getFoodData().setExhaustion(NumericValue.asNumber(v).getFloat());
}
});
put("add_exhaustion", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.getFoodData().addExhaustion(NumericValue.asNumber(v).getFloat());
}
});
put("absorption", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.setAbsorptionAmount(NumericValue.asNumber(v, "absorbtion").getFloat());
}
});
put("add_xp", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.giveExperiencePoints(NumericValue.asNumber(v, "add_xp").getInt());
}
});
put("xp_level", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.giveExperienceLevels(NumericValue.asNumber(v, "xp_level").getInt() - p.experienceLevel);
}
});
put("xp_progress", (e, v) -> {
if (e instanceof final ServerPlayer p)
if (e instanceof ServerPlayer p)
{
p.experienceProgress = NumericValue.asNumber(v, "xp_progress").getFloat();
p.connection.send(new ClientboundSetExperiencePacket(p.experienceProgress, p.totalExperience, p.experienceLevel));
@@ -1643,14 +1644,14 @@ public class EntityValue extends Value
});
put("xp_score", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.setScore(NumericValue.asNumber(v, "xp_score").getInt());
}
});
put("saturation", (e, v) -> {
if (e instanceof final Player p)
if (e instanceof Player p)
{
p.getFoodData().setSaturation(NumericValue.asNumber(v, "saturation").getFloat());
}
@@ -1659,7 +1660,7 @@ public class EntityValue extends Value
put("air", (e, v) -> e.setAirSupply(NumericValue.asNumber(v, "air").getInt()));
put("breaking_progress", (e, a) -> {
if (e instanceof final ServerPlayer sp)
if (e instanceof ServerPlayer sp)
{
int progress = (a == null || a.isNull()) ? -1 : NumericValue.asNumber(a).getInt();
Vanilla.ServerPlayerGameMode_setBlockBreakingProgress(sp.gameMode, progress);
@@ -1671,7 +1672,7 @@ public class EntityValue extends Value
{
UUID uUID = e.getUUID();
Value tagValue = NBTSerializableValue.fromValue(v);
if (tagValue instanceof final NBTSerializableValue nbtsv)
if (tagValue instanceof NBTSerializableValue nbtsv)
{
e.load(nbtsv.getCompoundTag());
e.setUUID(uUID);
@@ -1683,7 +1684,7 @@ public class EntityValue extends Value
{
UUID uUID = e.getUUID();
Value tagValue = NBTSerializableValue.fromValue(v);
if (tagValue instanceof final NBTSerializableValue nbtsv)
if (tagValue instanceof NBTSerializableValue nbtsv)
{
CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag()));
nbttagcompound.merge(nbtsv.getCompoundTag());
@@ -1694,14 +1695,14 @@ public class EntityValue extends Value
});
put("blue_skull", (e, v) -> {
if (e instanceof final WitherSkull w)
if (e instanceof WitherSkull w)
{
w.setDangerous(v.getBoolean());
}
});
put("offering_flower", (e, v) -> {
if (e instanceof final IronGolem ig)
if (e instanceof IronGolem ig)
{
ig.offerFlower(v.getBoolean());
}
@@ -1709,11 +1710,11 @@ public class EntityValue extends Value
});
put("item", (e, v) -> {
ItemStack item = ValueConversions.getItemStackFromValue(v, true, e.level().registryAccess());
if (e instanceof final ItemEntity itementity)
if (e instanceof ItemEntity itementity)
{
itementity.setItem(item);
}
if (e instanceof final ItemFrame itemframe)
if (e instanceof ItemFrame itemframe)
{
itemframe.setItem(item);
}
@@ -1734,7 +1735,7 @@ public class EntityValue extends Value
}
@Override
public net.minecraft.nbt.Tag toTag(boolean force)
public net.minecraft.nbt.Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
@@ -1,6 +1,6 @@
package carpet.script.value;
import com.google.gson.JsonElement;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
@@ -19,7 +19,7 @@ public class FormattedTextValue extends StringValue
public static Value combine(Value left, Value right)
{
MutableComponent text;
if (left instanceof final FormattedTextValue ftv)
if (left instanceof FormattedTextValue ftv)
{
text = ftv.getText().copy();
}
@@ -32,7 +32,7 @@ public class FormattedTextValue extends StringValue
text = Component.literal(left.getString());
}
if (right instanceof final FormattedTextValue ftv)
if (right instanceof FormattedTextValue ftv)
{
text.append(ftv.getText().copy());
return new FormattedTextValue(text);
@@ -80,19 +80,13 @@ public class FormattedTextValue extends StringValue
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return StringTag.valueOf(Component.Serializer.toJson(text));
}
@Override
public JsonElement toJson()
{
return Component.Serializer.toJsonTree(text);
return StringTag.valueOf(Component.Serializer.toJson(text, regs));
}
@Override
@@ -101,19 +95,19 @@ public class FormattedTextValue extends StringValue
return combine(this, o);
}
public String serialize()
public String serialize(RegistryAccess regs)
{
return Component.Serializer.toJson(text);
return Component.Serializer.toJson(text, regs);
}
public static FormattedTextValue deserialize(String serialized)
public static FormattedTextValue deserialize(String serialized, RegistryAccess regs)
{
return new FormattedTextValue(Component.Serializer.fromJson(serialized));
return new FormattedTextValue(Component.Serializer.fromJson(serialized, regs));
}
public static Component getTextByValue(Value value)
{
return (value instanceof final FormattedTextValue ftv) ? ftv.getText() : Component.literal(value.getString());
return (value instanceof FormattedTextValue ftv) ? ftv.getText() : Component.literal(value.getString());
}
}
@@ -1,5 +1,6 @@
package carpet.script.value;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
public abstract class FrameworkValue extends Value
@@ -29,7 +30,7 @@ public abstract class FrameworkValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
throw new UnsupportedOperationException("Scarpet language component cannot be serialized to the tag");
}
@@ -1,6 +1,7 @@
package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
public class FunctionAnnotationValue extends Value
@@ -41,7 +42,7 @@ public class FunctionAnnotationValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
throw new UnsupportedOperationException("Global value cannot be serialized to the tag");
}
@@ -19,6 +19,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
@@ -112,13 +113,13 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
@Override
public boolean equals(Object o)
{
return o instanceof final FunctionValue fv && name.equals(fv.name) && variant == fv.variant;
return o instanceof FunctionValue fv && name.equals(fv.name) && variant == fv.variant;
}
@Override
public int compareTo(Value o)
{
if (o instanceof final FunctionValue fv)
if (o instanceof FunctionValue fv)
{
int nameSame = this.name.compareTo(fv.name);
return nameSame != 0 ? nameSame : (int) (variant - fv.variant);
@@ -303,7 +304,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
@@ -7,6 +7,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
@@ -238,7 +239,7 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
@@ -16,6 +16,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.IntTag;
@@ -129,7 +130,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
public Value add(Value other)
{
ListValue output = new ListValue();
if (other instanceof final ListValue list)
if (other instanceof ListValue list)
{
List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
@@ -164,7 +165,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
public Value subtract(Value other)
{
ListValue output = new ListValue();
if (other instanceof final ListValue list)
if (other instanceof ListValue list)
{
List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
@@ -199,7 +200,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
public Value multiply(Value other)
{
ListValue output = new ListValue();
if (other instanceof final ListValue list)
if (other instanceof ListValue list)
{
List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
@@ -228,7 +229,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
public Value divide(Value other)
{
ListValue output = new ListValue();
if (other instanceof final ListValue list)
if (other instanceof ListValue list)
{
List<Value> otherItems = list.items;
if (otherItems.size() == items.size())
@@ -256,7 +257,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
@Override
public int compareTo(Value o)
{
if (o instanceof final ListValue ol)
if (o instanceof ListValue ol)
{
int size = this.getItems().size();
int otherSize = ol.getItems().size();
@@ -284,7 +285,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
@Override
public boolean equals(Object o)
{
return o instanceof final ListValue list && getItems().equals(list.getItems());
return o instanceof ListValue list && getItems().equals(list.getItems());
}
public List<Value> getItems()
@@ -555,7 +556,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
int argSize = items.size();
if (argSize == 0)
@@ -565,12 +566,12 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
ListTag tag = new ListTag();
if (argSize == 1)
{
tag.add(items.get(0).toTag(force));
tag.add(items.get(0).toTag(force, regs));
return tag;
}
// figuring out the types
List<Tag> tags = new ArrayList<>();
items.forEach(v -> tags.add(v.toTag(force)));
items.forEach(v -> tags.add(v.toTag(force, regs)));
Set<TagTypeCompat> cases = EnumSet.noneOf(TagTypeCompat.class);
tags.forEach(t -> cases.add(TagTypeCompat.getType(t)));
if (cases.size() == 1) // well, one type of items
@@ -13,6 +13,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
@@ -104,11 +105,11 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
public Value add(Value o)
{
Map<Value, Value> newItems = new HashMap<>(map);
if (o instanceof final MapValue mapValue)
if (o instanceof MapValue mapValue)
{
newItems.putAll(mapValue.map);
}
else if (o instanceof final AbstractListValue alv)
else if (o instanceof AbstractListValue alv)
{
for (Value value : alv)
{
@@ -142,7 +143,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
public void put(Value v)
{
if (!(v instanceof final ListValue pair))
if (!(v instanceof ListValue pair))
{
map.put(v, Value.NULL);
return;
@@ -169,7 +170,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
@Override
public boolean equals(Object o)
{
return o instanceof final MapValue mapValue && map.equals(mapValue.map);
return o instanceof MapValue mapValue && map.equals(mapValue.map);
}
public Map<Value, Value> getMap()
@@ -249,7 +250,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
CompoundTag tag = new CompoundTag();
map.forEach((k, v) ->
@@ -258,7 +259,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
{
throw new NBTSerializableValue.IncompatibleTypeException(k);
}
tag.put(k.getString(), v.toTag(force));
tag.put(k.getString(), v.toTag(force, regs));
});
return tag;
}
@@ -25,7 +25,7 @@ import net.minecraft.commands.arguments.item.ItemParser;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.core.particles.ItemParticleOption;
import net.minecraft.nbt.CollectionTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.EndTag;
@@ -104,15 +104,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
nbtSupplier = tagSupplier;
}
public static Value fromStack(ItemStack stack)
public static Value fromStack(ItemStack stack, RegistryAccess regs)
{
if (stack.hasTag())
{
NBTSerializableValue value = new NBTSerializableValue();
value.nbtSupplier = stack::getTag;
return value;
}
return Value.NULL;
NBTSerializableValue value = new NBTSerializableValue();
value.nbtSupplier = () -> stack.saveOptional(regs);
return value;
}
public static Value nameFromRegistryId(@Nullable ResourceLocation id)
@@ -341,29 +337,32 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
private static final Map<String, ItemInput> itemCache = new HashMap<>();
public static ItemInput parseItem(String itemString, RegistryAccess regs)
public static ItemStack parseItem(String itemString, RegistryAccess regs)
{
return parseItem(itemString, null, regs);
}
public static ItemInput parseItem(String itemString, @Nullable CompoundTag customTag, RegistryAccess regs)
public static ItemStack parseItem(String itemString, @Nullable CompoundTag customTag, RegistryAccess regs)
{
if (customTag != null) {
return ItemStack.parseOptional(regs, customTag);
}
try
{
ItemInput res = itemCache.get(itemString); // [SCARY SHIT] persistent caches over server reloads
if (res != null)
{
return customTag == null ? res : new ItemInput(Holder.direct(res.getItem()), customTag);
return res.createItemStack(1, false);
}
ItemParser.ItemResult parser = (new ItemParser(regs)).parse(new StringReader(itemString));
res = new ItemInput(parser.item(), parser.nbt());
res = new ItemInput(parser.item(), parser.components());
itemCache.put(itemString, res);
if (itemCache.size() > 64000)
{
itemCache.clear();
}
return customTag == null ? res : new ItemInput(Holder.direct(res.getItem()), customTag);
return res.createItemStack(1, false);
}
catch (CommandSyntaxException e)
{
@@ -764,7 +763,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
@@ -2,6 +2,7 @@ package carpet.script.value;
import java.util.ArrayList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import com.google.gson.JsonElement;
@@ -89,7 +90,7 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
@@ -3,6 +3,7 @@ package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import net.minecraft.core.RegistryAccess;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
@@ -27,7 +28,7 @@ public class NumericValue extends Value
public static NumericValue asNumber(Value v1, String id)
{
if (v1 instanceof final NumericValue nv)
if (v1 instanceof NumericValue nv)
{
return nv;
}
@@ -36,7 +37,7 @@ public class NumericValue extends Value
public static NumericValue asNumber(Value v1)
{
if (v1 instanceof final NumericValue nv)
if (v1 instanceof NumericValue nv)
{
return nv;
}
@@ -129,7 +130,7 @@ public class NumericValue extends Value
@Override
public Value add(Value v)
{ // TODO test if definintn add(NumericVlaue) woud solve the casting
if (v instanceof final NumericValue nv)
if (v instanceof NumericValue nv)
{
return longValue != null && nv.longValue != null ? new NumericValue(longValue + nv.longValue) : new NumericValue(value + nv.value);
}
@@ -139,7 +140,7 @@ public class NumericValue extends Value
@Override
public Value subtract(Value v)
{ // TODO test if definintn add(NumericVlaue) woud solve the casting
if (v instanceof final NumericValue nv)
if (v instanceof NumericValue nv)
{
return longValue != null && nv.longValue != null ? new NumericValue(longValue - nv.longValue) : new NumericValue(value - nv.value);
}
@@ -149,7 +150,7 @@ public class NumericValue extends Value
@Override
public Value multiply(Value v)
{
if (v instanceof final NumericValue nv)
if (v instanceof NumericValue nv)
{
return longValue != null && nv.longValue != null ? new NumericValue(longValue * nv.longValue) : new NumericValue(value * nv.value);
}
@@ -159,7 +160,7 @@ public class NumericValue extends Value
@Override
public Value divide(Value v)
{
return v instanceof final NumericValue nv ? new NumericValue(getDouble() / nv.getDouble()) : super.divide(v);
return v instanceof NumericValue nv ? new NumericValue(getDouble() / nv.getDouble()) : super.divide(v);
}
@Override
@@ -175,7 +176,7 @@ public class NumericValue extends Value
{
return -o.compareTo(this);
}
if (o instanceof final NumericValue no)
if (o instanceof NumericValue no)
{
return longValue != null && no.longValue != null ? longValue.compareTo(no.longValue) : Double.compare(value, no.value);
}
@@ -185,13 +186,13 @@ public class NumericValue extends Value
@Override
public boolean equals(Object o)
{
if (o instanceof final Value otherValue)
if (o instanceof Value otherValue)
{
if (otherValue.isNull())
{
return o.equals(this);
}
if (o instanceof final NumericValue no)
if (o instanceof NumericValue no)
{
if (longValue != null && no.longValue != null)
{
@@ -279,7 +280,7 @@ public class NumericValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (longValue != null)
{
@@ -17,6 +17,7 @@ import java.util.Map;
import java.util.OptionalInt;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
@@ -373,18 +374,25 @@ public class ScreenValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (this.screenHandler == null)
{
return Value.NULL.toTag(true);
return Value.NULL.toTag(true, regs);
}
ListTag nbtList = new ListTag();
for (int i = 0; i < this.screenHandler.slots.size(); i++)
{
ItemStack itemStack = this.screenHandler.getSlot(i).getItem();
nbtList.add(itemStack.save(new CompoundTag()));
if (itemStack.isEmpty())
{
nbtList.add(new CompoundTag());
}
else
{
nbtList.add(itemStack.save(regs));
}
}
return nbtList;
}
@@ -1,5 +1,6 @@
package carpet.script.value;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
@@ -46,7 +47,7 @@ public class StringValue extends Value
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
return StringTag.valueOf(str);
}
@@ -16,6 +16,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
public class ThreadValue extends LazyListValue
@@ -108,13 +109,13 @@ public class ThreadValue extends LazyListValue
@Override
public boolean equals(Object o)
{
return o instanceof final ThreadValue tv && tv.id == this.id;
return o instanceof ThreadValue tv && tv.id == this.id;
}
@Override
public int compareTo(Value o)
{
if (!(o instanceof final ThreadValue tv))
if (!(o instanceof ThreadValue tv))
{
throw new InternalExpressionException("Cannot compare tasks to other types");
}
@@ -128,13 +129,13 @@ public class ThreadValue extends LazyListValue
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
if (!force)
{
throw new NBTSerializableValue.IncompatibleTypeException(this);
}
return getValue().toTag(true);
return getValue().toTag(true, regs);
}
@Override
@@ -2,6 +2,7 @@ package carpet.script.value;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
public class UndefValue extends NullValue
@@ -87,7 +88,7 @@ public class UndefValue extends NullValue
}
@Override
public Tag toTag(boolean force)
public Tag toTag(boolean force, RegistryAccess regs)
{
throw getError();
}
+4 -3
View File
@@ -12,6 +12,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
import javax.annotation.Nullable;
@@ -97,7 +98,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
public Value divide(Value v)
{
if (v instanceof final NumericValue number)
if (v instanceof NumericValue number)
{
String lstr = getString();
return new StringValue(lstr.substring(0, (int) (lstr.length() / number.getDouble())));
@@ -121,7 +122,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
@Override // for hashmap key access, and == operator
public boolean equals(Object o)
{
if (o instanceof final Value v)
if (o instanceof Value v)
{
return this.compareTo(v) == 0;
}
@@ -254,7 +255,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
}
}
public abstract Tag toTag(boolean force);
public abstract Tag toTag(boolean force, RegistryAccess regs);
public JsonElement toJson()
{
@@ -8,14 +8,12 @@ import carpet.script.utils.Colors;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.advancements.critereon.MinMaxBounds;
import net.minecraft.commands.arguments.item.ItemInput;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.Vec3i;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
@@ -58,8 +56,6 @@ import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.StreamSupport;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import javax.annotation.Nullable;
public class ValueConversions
@@ -97,22 +93,12 @@ public class ValueConversions
);
}
@Deprecated
public static Value of(ItemStack stack)
{
return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of(
of(BuiltInRegistries.ITEM.getKey(stack.getItem())),
new NumericValue(stack.getCount()),
NBTSerializableValue.fromStack(stack)
);
}
public static Value of(ItemStack stack, RegistryAccess regs)
{
return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of(
of(regs.registryOrThrow(Registries.ITEM).getKey(stack.getItem())),
new NumericValue(stack.getCount()),
NBTSerializableValue.fromStack(stack)
NBTSerializableValue.fromStack(stack, regs)
);
}
@@ -503,22 +489,9 @@ public class ValueConversions
{
name = value.getString();
}
ItemInput itemInput = NBTSerializableValue.parseItem(name, nbtTag, regs);
try
{
return itemInput.createItemStack(count, false);
}
catch (CommandSyntaxException cse)
{
if (!withCount)
{
throw new IllegalStateException("Unexpected exception while creating item stack of " + name + ". All items should be able to stack to one", cse);
}
else
{
throw new ThrowStatement(count + " stack size of " + name, Throwables.UNKNOWN_ITEM);
}
}
ItemStack itemInput = NBTSerializableValue.parseItem(name, nbtTag, regs);
itemInput.setCount(count);
return itemInput;
}
public static Value guess(ServerLevel serverWorld, Object o)
+3 -3
View File
@@ -55,9 +55,9 @@ public class BlockInfo
//lst.add(Messenger.s(String.format(" - Picks neighbour light value: %s", state.useNeighborBrightness(world, pos))));
lst.add(Messenger.s(""));
lst.add(Messenger.s(String.format(" - Causes suffocation: %s", state.isSuffocating(world, pos)))); //canSuffocate
lst.add(Messenger.s(String.format(" - Blocks movement on land: %s", !state.isPathfindable(world,pos, PathComputationType.LAND))));
lst.add(Messenger.s(String.format(" - Blocks movement in air: %s", !state.isPathfindable(world,pos, PathComputationType.AIR))));
lst.add(Messenger.s(String.format(" - Blocks movement in liquids: %s", !state.isPathfindable(world,pos, PathComputationType.WATER))));
lst.add(Messenger.s(String.format(" - Blocks movement on land: %s", !state.isPathfindable(PathComputationType.LAND))));
lst.add(Messenger.s(String.format(" - Blocks movement in air: %s", !state.isPathfindable(PathComputationType.AIR))));
lst.add(Messenger.s(String.format(" - Blocks movement in liquids: %s", !state.isPathfindable(PathComputationType.WATER))));
lst.add(Messenger.s(String.format(" - Can burn: %s", state.ignitedByLava())));
lst.add(Messenger.s(String.format(" - Hardness: %.2f", state.getDestroySpeed(world, pos))));
lst.add(Messenger.s(String.format(" - Blast resistance: %.2f", block.getExplosionResistance())));
@@ -13,7 +13,7 @@ import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride;