new Attempt -> not functional yet

das hier ist ein backup, das noch unglaublich viele Fehler hat aber es war echt anstrengend, deswegen brauchen wir das. Bitte löschen sobald funktionierender release (hoffentlich) irgendwann kommt.
This commit is contained in:
Paula 2024-05-31 16:57:15 +02:00
parent 74e05e6c7e
commit 936c50e13c
87 changed files with 4814 additions and 157 deletions

View File

@ -1,5 +1,7 @@
package modchest; package modchest;
import modchest.assets.OverlayAssetListener;
import modchest.block.custom.gridCodecs;
import modchest.networking.modNetworkingClient; import modchest.networking.modNetworkingClient;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.util.ModelIdentifier; import net.minecraft.client.util.ModelIdentifier;
@ -9,6 +11,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class REServerModClient implements ClientModInitializer { public class REServerModClient implements ClientModInitializer {
public static gridCodecs CODECS;
public static OverlayAssetListener CLIENT_OVERLAYS;
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {

View File

@ -0,0 +1,105 @@
package modchest.assets;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.BufferUnderflowException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import org.spongepowered.include.com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener;
import net.minecraft.client.gui.screen.Overlay;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import net.minecraft.util.Unit;
import net.minecraft.util.profiler.Profiler;
@Environment(EnvType.CLIENT)
public class OverlayAssetListener implements SimpleResourceReloadListener<Collection<Identifier>> {
private final Map<Identifier, Overlay> overlayInfoMap = new HashMap<>();
public Overlay getOverlayFor(final Identifier id) {
return Overlay.ofNullable(overlayInfoMap.get(id));
}
@Override
public CompletableFuture<Collection<Identifier>> load(ResourceManager manager, Profiler profiler,
Executor executor) {
return CompletableFuture.supplyAsync(() -> {
overlayInfoMap.clear();
return resourceManager.findResources("modchest/overlays", s -> s.endsWith(".json"));
}, executor);
}
private DataResult<Unit> parseOverlayAndDependencies(final ResourceManager resourceManager,
final Identifier rootOverlayId) {
final Set<Identifier> loadedDependencies = new HashSet<>();
if (!overlayInfoMap.containsKey(rootOverlayId)) {
return parseOverlay(resourceManager, loadedDependencies, rootOverlayId);
} else {
return DataResult.success(Unit.INSTANCE);
}
}
private DataResult<Unit> parseOverlay(final ResourceManager resourceManager,
final Set<Identifier> loadedDependencies, final Identifier overlayId) {
final JsonElement element;
try {
element = new Gson().fromJson(
new BufferedReader(new InputStreamReader(resourceManager.getResource(overlayId).getInputStream())),
JsonElement.class);
} catch (final IOException e) {
return DataResult.error("Exception while loading an overlay:");
}
final DataResult<Pair<Overlay.Some, JsonElement>> result = Overlay.Some.PARENT_CODEC
.decode(JsonOps.INSTANCE, element)
.flatMap(pair -> pair.getFirst().map(parentId -> {
if (!loadedDependencies.add(parentId)) {
return DataResult.error("Circular dependency;" + pair.getFirst() + "and" + overlayId + ".");
} else {
parseOverlay(resourceManager, loadedDependencies, parentId);
return DataResult.success(Unit.INSTANCE);
}
}).orElse(DataResult.success(Unit.INSTANCE)))
.flatMap(unit -> Overlay.Some.CODEC.decode(JsonOps.INSTANCE, element));
result.get().mapLeft(pair -> {
overlayInfoMap.put(overlayId, pair.getFirst());
});
return result.map(p -> Unit.INSTANCE);
}
@Override
public CompletableFuture<Void> apply(Collection<Identifier> data, ResourceManager manager, Profiler profiler,
Executor executor) {
return CompletableFuture.runAsync(() -> {
for (final Identifier id : identifiers) {
final DataResult<Unit> result = parseOverlayAndDependencies(manager, id);
result.get().ifRight(partial -> META.LOGGER
.warn("Error while parsing overlay \"" + id + "\": " + partial.message()));
}
}, executor);
}
@Override
public Identifier getFabricId() {
return id;
}
}

View File

@ -0,0 +1,68 @@
package modchest.assets;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.NonnullDefault;
import modchest.util.ToOptional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
@Environment(EnvType.CLIENT)
public abstract class Parent implements ToOptional<Parent> {
public static Parent ofNullable(@Nullable final Identifier parentId) {
if (parentId == null) {
return NONE;
} else {
return new Some(parentId);
}
}
public abstract Optional<Identifier> id();
public abstract <T> T run(@NonnullDefault Function<Identifier, T> f, T whenNone);
public static class Some extends Parent implements ToOptional.Some<Parent> {
private final @NonnullDefault Identifier parent;
public Some(final @NonnullDefault Identifier parent) {
this.parent = parent;
}
@Override
public Optional<Identifier> id() {
return Optional.of(parent);
}
@Override
public <T> T run(Function<Identifier, T> f, T whenNone) {
return f.apply(parent);
}
}
public static final Parent NONE = new Parent() {
@Override
public Optional<Identifier> id() {
return Optional.empty();
}
@Override
public <T> T run(@NonnullDefault final Function<Identifier, T> f, final T whenNone) {
return whenNone;
}
@Override
public <T> T match(final Function<Parent, T> some, final Supplier<T> none) {
return none.get();
}
@Override
public Optional<Parent> toOptional() {
return Optional.empty();
}
};
}

View File

@ -0,0 +1,26 @@
package modchest.assets.overlay;
import com.mojang.serialization.Codec;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.BlockState;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
@Environment(EnvType.CLIENT)
public class ColoredLike {
public static final Codec<ColoredLike> CODEC = Identifier.CODEC
.xmap(id -> Registry.BLOCK.get(id).getDefaultState(), state -> Registry.BLOCK.getId(state.getBlock()))
.xmap(ColoredLike::new, coloredLike -> coloredLike.colorSource);
private final BlockState colorSource;
public ColoredLike(final BlockState colorSource) {
this.colorSource = colorSource;
}
public BlockState colorSource() {
return colorSource;
}
}

View File

@ -0,0 +1,42 @@
package modchest.assets.overlay;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import modchest.util.ToOptional;
import modchest.util.Float4;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
@Environment(EnvType.CLIENT)
public interface Offsetter extends ToOptional<Offsetter> {
Float4 offsett(Float4 original);
public Identifier getId();
Identifier NONE_ID = META.id("none");
Offsetter NONE = new Offsetter() {
@Override
public Optional<Offsetter> toOptional() {
return Optional.empty();
}
@Override
public <T> T match(final Function<Offsetter, T> some, final Supplier<T> none) {
return none.get();
}
@Override
public Identifier getId() {
return NONE_ID;
}
@Override
public Float4 offsett(Float4 original) {
return original;
}
};
}

View File

@ -0,0 +1,28 @@
package modchest.assets.overlay;
import java.util.HashMap;
import java.util.Map;
import com.mojang.serialization.Codec;
import modchest.util.Identifiable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
@Environment(EnvType.CLIENT)
public class OffsetterRegistry {
private OffsetterRegistry() {
}
private static final Map<Identifier, Identifiable<Codec<Offsetter>>> registeredOffsetters = new HashMap<>();
private static void register(final Identifier id, final Codec<Offsetter> codec) {
registeredOffsetters.put(id, new Identifiable<>(codec, id));
}
public static Identifiable<Codec<Offsetter>> get(final Identifier id) {
return registeredOffsetters.get(id);
}
}

View File

@ -0,0 +1,37 @@
package modchest.assets.overlay;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class Offsetters {
public static final Codec<Offsetters> CODEC = RecordCodecBuilder.create(inst -> inst.group(
CODECS.OFFSETTER.optionalFieldOf("u").forGetter(o -> o.u.toOptional()),
CODECS.OFFSETTER.optionalFieldOf("v").forGetter(o -> o.v.toOptional())
).apply(inst, Offsetters::new));
public static final Offsetters NONE = new Offsetters();
public final Offsetter u;
public final Offsetter v;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public Offsetters(final Optional<Offsetter> u, final Optional<Offsetter> v) {
this.u = u.orElse(Offsetter.NONE);
this.v = v.orElse(Offsetter.NONE);
}
private Offsetters() {
this.u = Offsetter.NONE;
this.v = Offsetter.NONE;
}
}

View File

@ -0,0 +1,133 @@
package modchest.assets.overlay;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import modchest.assets.Parent;
import modchest.assets.Parent.Some;
import modchest.transform.TransformResult;
import modchest.util.Float4;
import modchest.util.ToOptional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
@Environment(EnvType.CLIENT)
public abstract class Overlay implements ToOptional<Overlay> {
public static Overlay ofNullable(final @Nullable Some some) {
if (some == null) {
return NONE;
} else {
return some;
}
}
public abstract TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir);
public abstract TextureSource textureSource();
public abstract Optional<ColoredLike> coloredLike();
public abstract SidedOffsetters.Base sideOffsetters();
public static final Overlay NONE = new Overlay() {
@Override
public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir) {
return TransformResult.NOTHING_TO_DO;
}
@Override
public TextureSource textureSource() {
return TextureSource.NONE;
}
@Override
public Optional<ColoredLike> coloredLike() {
return Optional.empty();
}
@Override
public SidedOffsetters.Base sideOffsetters() {
return SidedOffsetters.NONE;
}
@Override
public Optional<Overlay> toOptional() {
return Optional.empty();
}
@Override
public <T> T match(Function<Overlay, T> some, Supplier<T> none) {
return none.get();
}
};
public static class Some extends Overlay implements ToOptional.Some<Overlay> {
public static final Codec<Optional<Identifier>> PARENT_CODEC = RecordCodecBuilder.create(inst -> inst.group(
Identifier.CODEC.optionalFieldOf("parent").forGetter(i -> i)).apply(inst, i -> i));
public static final Codec<Overlay.Some> CODEC = RecordCodecBuilder.create(inst -> inst.group(
Identifier.CODEC.optionalFieldOf("parent").forGetter(o -> o.parent.id()),
TextureSource.CODEC.optionalFieldOf("textureSource").forGetter(o -> o.textureSource.toOptional()),
ColoredLike.CODEC.optionalFieldOf("coloredLike").forGetter(o -> o.coloredLike),
SidedOffsetters.CODEC.optionalFieldOf("offsets").forGetter(o -> o.sideOffsetters.toOptional()))
.apply(inst, Overlay.Some::new));
private final Parent parent;
private final TextureSource textureSource;
private final Optional<ColoredLike> coloredLike;
private final SidedOffsetters.Base sideOffsetters;
public Some(final Optional<Identifier> parent, final Optional<TextureSource> textureSource,
final Optional<ColoredLike> coloredLike, final Optional<SidedOffsetters.Base> sideOffsetters) {
this.parent = Parent.ofNullable(parent.orElse(null));
this.textureSource = textureSource.ofNullable(parent.orElse(null));
this.coloredLike = coloredLike;
this.sideOffsetters = sideOffsetters.orElse(SidedOffsetters.NONE);
}
@Override
public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction dir) {
final Float4 finalUs = sidedOffsetters().applyUs(us, dir);
float Float4 finalVs = sidedOffsetters().applyVs(vs, dir);
return textureSource().apply(mqv, finalUs, finalVs, dir);
}
@Override
public TextureSource textureSource() {
if (textureSource != TextureSource.NONE) {
return textureSource;
} else {
return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).textureSource(), TextureSource.NONE);
}
}
@Override
public Optional<ColoredLike> coloredLike() {
if (coloredLike.isPresent()) {
return coloredLike;
} else {
return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).coloredLike(), Optional.empty());
}
}
@Override
public Base sideOffsetters() {
if (sideOffsetters != SidedOffsetters.NONE) {
return sidedOffsetters;
} else {
return parent.run(parent -> CLIENT_OVERLAYS.getOverlayFor(parent).sidedOffsetters(),
SidedOffsetters.NONE);
}
}
}
}

View File

@ -0,0 +1,76 @@
package modchest.assets.overlay;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import com.mojang.serialization.Codec;
import modchest.util.Float4;
import modchest.util.ToOptional;
import modchest.util.initializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.math.Direction;
@Environment(EnvType.CLIENT)
public abstract class SidedOffsetters {
private SidedOffsetters() {
}
public static final Codec<SidedOffsetters.Base> CODEC = Some.CODEC.xmap(some -> some, base -> (Some) base);
public static final Base NONE = new Base() {
@Override
public Optional<Base> toOptional() {
return Optional.empty();
}
@Override
public Float4 applyUs(final Float4 origUs, Direction dir) {
return origUs;
}
@Override
public Float4 applyVs(final Float4 origVs, Direction dir) {
return origVs;
}
@Override
public <T, t> T match(Function<Base, t> some, Supplier<T> none) {
return none.get();
}
};
public interface Base extends ToOptional<Base> {
Float4 applyUs(Float4 origUs, Direction dir);
Float4 applyVs(Float4 origVs, Direction dir);
}
public static class Some implements Base, ToOptional.Some<Base> {
public static final Codec<SidedOffsetters.Some> CODEC = CODECS.sidedMapOf(Offsetters.CODEC)
.xmap(SidedOffsetters.Some::new, so -> so.map);
private final Map<Direction, Offsetters> map;
public Some(final Map<Direction, Offsetters> map) {
for (final Direction dir : Direction.values()) {
map.putIfAbsent(dir, Offsetters.NONE);
}
this.map = map;
}
@Override
public Float4 applyUs(Float4 origUs, Direction dir) {
return map.get(dir).u.offsett(origUs);
}
@Override
public Float4 applyVs(Float4 origVs, Direction dir) {
return map.get(dir).v.offsett(origVs);
}
}
}

View File

@ -0,0 +1,161 @@
package modchest.assets.overlay;
import java.rmi.registry.Registry;
import java.util.EnumMap;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import org.spongepowered.asm.mixin.Final;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import modchest.transform.MaterialApplier;
import modchest.transform.SpriteApplier;
import modchest.transform.TransformResult;
import modchest.util.Float4;
import modchest.util.ToOptional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
@Environment(EnvType.CLIENT)
public abstract class TextureSource implements ToOptional<TextureSource> {
public static class Entry {
public final SpriteApplier textureApplier;
public final MaterialApplier materialApplier;
public static final Entry NONE = new Entry();
private Entry() {
this.textureApplier = SpriteApplier.NONE;
this.materialApplier = MaterialApplier.NONE;
}
@SuppressWarnings("deprecation")
public Entry(Identifier texture, Optional<Identifier> materialSource) {
final Sprite sprite = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
.apply(texture);
this.textureApplier = SpriteApplier.ofNullable(sprite);
final Optional<BlockState> materialSourceState = materialSource
.map(id -> Registry.BLOCK.get(id).getDefaultState());
this.materialApplier = MaterialApplier.ofSpriteAndBlockState(sprite, materialSourceState.orElse(null));
}
}
public static final Codec<TextureSource> CODEC = Codec.STRING
.flatXmap(TextureSourceKind::fromString, kind -> DataResult.success(kind.toString()))
.dispatch(ts -> ts.kind, kind -> {
switch (kind) {
case SINGLE:
return RecordCodecBuilder.create(
inst -> inst.group(Single.SINGLE_CODEC.fieldOf("value").forGetter(i -> (Single) i))
.apply(inst, i -> i));
case SIDED:
return RecordCodecBuilder.create(
inst -> inst.group(Sided.SIDED_CODEC.fieldOf("value").forGetter(i -> (Single) i))
.apply(inst, i -> i));
default:
throw new IllegalStateException("Invalid TextureSourceKind:" + kind);
}
});
public final TextureSourceKind kind;
protected TextureSource(final TextureSourceKind kind) {
this.kind = kind;
}
public TransformResult apply(final MutableQuadView mqv, final Float4 us, Float4 vs, final Direction side) {
final Entry entry = entryFor(side);
entry.materialApplier.apply(mqv);
return entry.textureApplier.apply(mqv, us, vs);
}
protected abstract Entry entryFor(final Direction side);
public static class Single extends TextureSource implements ToOptional.Some<TextureSource> {
public static final Codec<Single> SINGLE_CODEC = RecordCodecBuilder.create(inst -> inst
.group(Identifier.CODEC.fieldOf("texture").forGetter(s -> s.entry.textureApplier.id()),
Identifier.CODEC.optionalFieldOf("materialSource").forGetter(s -> s.entry.materialApplier.id()))
.apply(inst, Single::new));
private final Entry entry;
public Single(final Identifier texture, final Optional<Identifier> materialSourceId) {
super(TextureSourceKind.SINGLE);
entry = new Entry(texture, materialSourceId);
}
@Override
protected Entry entryFor(Direction side) {
return entry;
}
}
public static class Sided extends TextureSource implements ToOptional.Some<TextureSource> {
public static final Codec<Sided> SIDED_CODEC;
static {
final Codec<Entry> sidedValueCodec = RecordCodecBuilder.create(inst -> inst.group(
Identifier.CODEC.fieldOf("texture").forGetter(e -> e.textureApplier.id()),
Identifier.CODEC.optionalFieldOf("materialFrom").forGetter(e -> e.materialApplier.id()))
.apply(inst, Entry::new));
SIDED_CODEC = CODECS.sidedMapOf(sidedValueCodec).xmap(
map -> new Sided(new EnumMap<>(map)),
sided -> sided.entries);
}
private final EnumMap<Direction, Entry> entries;
public Sided(final EnumMap<Direction, Entry> entries) {
super(TextureSourceKind.SIDED);
for (final Direction dir : Direction.values()) {
entries.putIfAbsent(dir, Entry.NONE);
}
this.entries = entries;
}
@Override
public Optional<TextureSource> toOptional() {
return Optional.of(this);
}
@Override
protected Entry entryFor(Direction side) {
return entries.get(side);
}
}
public static final TextureSource NONE = new TextureSource(null) {
@Override
public Optional<TextureSource> toOptional() {
return Optional.empty();
}
@Override
public <T> T match(Function<TextureSource, T> some, Supplier<T> none) {
return none.get();
}
@Override
public TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs, Direction side) {
return TransformResult.NOTHING_TO_DO;
}
@Override
protected Entry entryFor(Direction side) {
return null;
}
};
}

View File

@ -0,0 +1,24 @@
package modchest.assets.overlay;
import com.ibm.icu.impl.locale.LocaleDistance.Data;
import com.mojang.serialization.DataResult;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public enum TextureSourceKind {
SINGLE,
SIDED;
public static DataResult<TextureSourceKind> fromString(final String string) {
switch (string) {
case "single":
return DataResult.success(SINGLE);
case "sided":
return DataResult.success(SIDED);
default:
return DataResult.error("Invalid texture source:" + string);
}
}
}

View File

@ -0,0 +1,35 @@
package modchest.assets.overlay;
import modchest.util.Float4;
import modchest.util.ToOptional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
@Environment(EnvType.CLIENT)
public class ZeroOffsetter implements Offsetter, ToOptional.Some<Offsetter> {
private final Identifier id;
public ZeroOffsetter(final Identifier id) {
this.id = id;
}
@Override
public Float4 offset(final Float4 original) {
final float min = original.min();
final float max = original.max();
final float delta = max - min;
if (original.a == min) {
return Float4.of(0, delta, delta, 0);
} else {
return Float4.of(delta, 0, 0, delta);
}
}
@Override
public Identifier getId() {
return id;
}
}

View File

@ -0,0 +1,68 @@
package modchest.block.custom;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import modchest.assets.overlay.Offsetter;
import modchest.assets.overlay.OffsetterRegistry;
import modchest.util.Identifiable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import net.minecraft.util.math.Direction;
@Environment(EnvType.CLIENT)
public class gridCodecs {
public final Codec<Direction> DIRECTION = Codec.STRING.flatXmap(
name -> {
Direction result = Direction.byName(name);
if (result != null) {
return DataResult.success(result);
} else {
return DataResult.error("Invalid direction:" + name);
}
},
d -> DataResult.success(d.toString()));
public final Codec<Offsetter> OFFSETTER = Identifier.CODEC
.flatXmap(
id -> {
final @Nullable Identifiable<Codec<Offsetter>> codec = OffsetterRegistry.get(id);
if (codec != null) {
return DataResult.success(codec);
} else {
return DataResult.error("Invalid offsetter type:" + id);
}
},
codec -> DataResult.success(codec.id())
)
.dispatch(
o -> OffsetterRegistry.get(o.getId()),
codec -> RecordCodecBuilder.create(inst -> inst.group(
codec.value().fieldOf("value").forGetter(c -> c)
).apply(inst, c -> c))
);
public <V> Codec<Map<Direction, V>> sideMapOf(final Codec<V> valueCodec) {
final Codec<Pair<List<Direction>, V>> itemCodec = RecordCodecBuilder.create(inst -> inst.group(
DIRECTION.listOf().fieldOf("sides").forGetter(Pair::getFirst),
valueCodec.fieldOf("value").forGetter(Pair::getSecond)
.apply(inst, Pair::new));
return itemCodec.listOf().xmap(
pairs -> pairs.stream().flatMap(pair -> pair.getFirst().stream().map(dir -> new Pair<>(dir, pair.getSecond()))).collect(Pair.toMap()),
map -> map.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue))
.entrySet().stream()
.map(e -> new Pair<>(e.getValue().stream().map(Map.Entry::getKey).collect(Collectors.toList()), e.getKey()))
.collect(Collectors.toList()));
)
}
}

View File

@ -0,0 +1,20 @@
package modchest.block.custom;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.transformer.Config;
public class gridConfig extends Config<OwenElement> {
public static final ValueKey<Boolean> SHOW_PLACEMENT_PREVIEW = builder(true)
.with((oldValue, newValue) -> gridPreviewOutline.enabled = newValue)
.build();
@Override
public @NotNull ConfigSerializer<OwenElement> getSerializer() {
return FlatOwenSerializer.INSTANCE;
}
@Override
public @NotNull SaveType getSafeType() {
return SaveType.ROOT;
}
}

View File

@ -0,0 +1,168 @@
/*package modchest.block.custom;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.swing.Renderer;
import com.mojang.datafixers.util.Pair;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
@Environment(EnvType.CLIENT)
public class gridModelChange implements UnbakedModel, BakedModel, FabricBakedModel {
@Override
public boolean isVanillaAdapter() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'isVanillaAdapter'");
}
@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos,
Supplier<Random> randomSupplier, RenderContext context) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'emitBlockQuads'");
}
@Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'emitItemQuads'");
}
@Override
public ModelOverrideList getOverrides() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getOverrides'");
}
@Override
public Sprite getParticleSprite() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getParticleSprite'");
}
@Override
public List<BakedQuad> getQuads(BlockState arg0, Direction arg1, Random arg2) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getQuads'");
}
@Override
public ModelTransformation getTransformation() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getTransformation'");
}
@Override
public boolean hasDepth() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'hasDepth'");
}
@Override
public boolean isBuiltin() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'isBuiltin'");
}
@Override
public boolean isSideLit() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'isSideLit'");
}
@Override
public boolean useAmbientOcclusion() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'useAmbientOcclusion'");
}
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
Get the sprites
for (int i = 0; i < SPRITE_IDS.length; ++i) {
sprites[i] = textureGetter.apply(SPRITE_IDS[i]);
}
// Build the mesh using the Renderer API
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
MeshBuilder builder = renderer.meshBuilder();
QuadEmitter emitter = builder.getEmitter();
for (Direction direction : Direction.values()) {
// UP and DOWN share the Y axis
int spriteIdx = direction == Direction.UP || direction == Direction.DOWN ? SPRITE_TOP : SPRITE_SIDE;
// Add a new face to the mesh
emitter.square(direction, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
// Set the sprite of the face, must be called after .square()
// We haven't specified any UV coordinates, so we want to use the whole texture.
// BAKE_LOCK_UV does exactly that.
emitter.spriteBake(sprites[spriteIdx], MutableQuadView.BAKE_LOCK_UV);
// Enable texture usage
emitter.color(-1, -1, -1, -1);
// Add the quad to the mesh
emitter.emit();
}
mesh = builder.build();
return this;
}
@Override
public Collection<Identifier> getModelDependencies() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getModelDependencies'");
}
@Override
public Collection<SpriteIdentifier> getTextureDependencies(Function<Identifier, UnbakedModel> unbakedModelGetter,
Set<Pair<String, String>> unresolvedTextureReferences) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getTextureDependencies'");
}
/*@SuppressWarnings("deprecation")
private static final SpriteIdentifier[] SPRITE_IDS = new SpriteIdentifier[] {
new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier("minecraft:block/furnace_front_on")),
new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier("minecraft:block/furnace_top"))
};
private final Sprite[] sprites = new Sprite[SPRITE_IDS.length];
// Some constants to avoid magic numbers, these need to match the SPRITE_IDS
private static final int SPRITE_SIDE = 0;
private static final int SPRITE_TOP = 1;
private Mesh mesh;
} */

View File

@ -0,0 +1,203 @@
package modchest.block.custom;
import static net.minecraft.block.Block.field_31022;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Properties;
import org.lwjgl.system.MemoryStack;
import modchest.event.playerAfterRespawnEvent;
import modchest.grid.gridBlock;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.fabricmc.tinyremapper.extension.mixin.hard.util.CamelPrefixString;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.util.math.Vector3d;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.Vector4f;
public class gridPreviewOutline {
public static boolean enanbled = true;
public static void renderPreviewOutline(final WorldRenderContext context) {
if (!enanbled) {
return;
}
final MinecraftClient client = MinecraftClient.getInstance();
final ClientPlayerEntity player = client.player;
if (player == null) {
return;
}
final ItemStack stack = player.getStackInHand(Hand.MAIN_HAND);
if (!(stack.getItem() instanceof BlockItem)) {
return;
}
final Block block = ((BlockItem) stack.getItem()).getBlock();
if (!(block instanceof gridBlock)) {
return;
}
if (!(client.crosshairTarget instanceof BlockHitResult)
|| client.crosshairTarget.getType() == HitResult.Type.MISS || client.world == null) {
return;
}
final BlockHitResult hitResult = (BlockHitResult) client.crosshairTarget;
final ItemPlacementContext placementContext = new ItemPlacementContext(player, Hand.MAIN_HAND, stack,
hitResult);
final BlockState blockState = ((BlockItemAccess) player.getMainHandStack().getItem())
.getPlacementStateProxy(placementContext);
if (blockState == null) {
return;
}
final BlockPos pos = placementContext.getBlockPos();
final BakedModel model = client.getBlockRenderManager().getModel(blockState);
final boolean valid;
if (block == Blocks.GRID_DOOR) {
final BlockPos upPos = pos.up();
final BlockState upState = blockState.with(Properties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.UPPER);
final BakedModel upModel = client.getBlockRenderManager().getModel(upState);
final boolean upValid = new ItemPlacementContext(player, Hand.MAIN_HAND, stack,
hitResult.withBlockPos(upPos)).canReplaceExisting() || client.world.getBlockState(upPos).isAir();
final boolean downValid = blockState.canPlaceAt(client.world, pos)
&& (placementContext.canPlace() || client.world.getBlockState(pos).isAir());
if (!upValid) {
valid = false;
} else {
valid = downValid;
}
renderPreview(context, client.world, upState, upPos, upModel, upValid && downValid);
} else {
valid = blockState.canPlaceAt(client.world, pos)
&& (placementContext.canPlace() || client.world.getBlockState(pos).isAir());
}
renderPreview(context, client.world, blockState, pos, model, valid);
}
private static void renderPreview(final WorldRenderContext context, final ClientWorld world,
final BlockState blockState, final BlockPos pos, final BakedModel model, final boolean valid) {
final MatrixStack matrixStack = context.matrixStack();
final Camera camera = context.camera();
final int ticks = ((WorldRendererAccess) context.worldRenderer()).ticks();
final float tickDelta = context.tickDelta();
for (int directionId = 0; directionId <= 6; directionId++) {
final List<BakedQuad> quads = model.getQuads(blockState, ModelHelper.faceFromIndex(directionId),
world.random);
matrixStack.push();
matrixStack.translate(-camera.getPos().x, -camera.getPos().y, -camera.getPos().z);
matrixStack.translate(pos.getX(), pos.getY(), pos.getZ());
if (blockState.contains(Properties.HORIZONTAL_FACING)) {
matrixStack.translate(0.5, 0.5, 0.5);
matrixStack.translate(-0.5, -0.5, -0.5);
}
final float scale = 1F - (1F / 60) + ((float) Math.sin((ticks + tickDelta) / 4.5F) / 60);
matrixStack.translate(-0.5 * scale, -0.5 * scale, -0.5 * scale);
matrixStack.translate(scale, scale, scale);
matrixStack.translate(0.5 / scale, 0.5 / scale, 0.5 / scale);
final int c = 0;
final int r = valid ? c : 255;
final int g = valid ? 255 : c;
final int b = valid ? 64 : 0;
final int a = valid ? 191 : 63;
final MatrixStack.Entry entry = matrixStack.peek();
final VertexConsumer faces = context.consumers()
.getBuffer(TexturedRenderLayers.getItemEntityTranslucentCull());
for (final BakedQuad quad : quads) {
render(quad, entry, faces, r, g, b, a);
}
matrixStack.pop();
}
}
private static void render(final BakedQuad quad, final MatrixStack.Entry entry, final VertexConsumer consumer,
final float r, final float g, final float b, final float a) {
final int[] vertexData = quad.getVertexData();
final Vec3i vector = quad.getFace().getVector();
final Vector3f newVector = new Vector3f((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ());
final Matrix4f model = entry.getModel();
newVector.transform(entry.getNormal());
final int j = vertexData.length / 8;
final MemoryStack memoryStack = MemoryStack.stackPush();
Throwable var17 = null;
try {
final ByteBuffer byteBuffer = memoryStack
.malloc(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL.getVertexSize());
final IntBuffer intBuffer = byteBuffer.asIntBuffer();
for (int k = 0; k < j; ++k) {
intBuffer.clear();
intBuffer.put(vertexData, k * 8, 8);
final float x = byteBuffer.getFloat(0);
final float y = byteBuffer.getFloat(4);
final float z = byteBuffer.getFloat(8);
final float v;
final float w;
final int u = 0x00F000F0;
v = byteBuffer.getFloat(16);
w = byteBuffer.getFloat(20);
final Vector4f vector4f = new Vector4f(x, y, z, 1.0F);
vector4f.transform(model);
consumer.vertex(vector4f.getX(), vector4f.getY(), vector4f.getZ(), r / 255F, g / 255F, b / 255F,
a / 255F, v, w, OverlayTexture.DEFAULT_UV, u, newVector.getX(), newVector.getY(),
newVector.getZ());
}
} catch (final Throwable var38) {
var17 = var38;
throw var38;
} finally {
if (var17 != null) {
try {
memoryStack.close();
} catch (final Throwable var37) {
var17.addSuppressed(var37);
}
} else {
memoryStack.close();
}
}
}
}

View File

@ -0,0 +1,18 @@
package modchest.gui;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.Text;
@Environment(EnvType.CLIENT)
public class gridScreen extends CottonInventoryScreen<gridGuiDescription>{
@SuppressWarnings("deprecation")
public static final ScreenRegistry.Factory<gridGuiDescription, gridScreen> FACTORY = (desc, playerInventory, title) ->
new gridScreen(desc, playerInventory.player, title);
public gridScreen(final gridGuiDescription description, final PlayerEntity player, final Text title) {
super(description, player, title);
}
}

View File

@ -1,66 +1,230 @@
package modchest.networking.packet; /*
* package modchest.networking.packet;
*
* import static net.minecraft.block.Block.getBlockFromItem;
*
* import java.util.Random;
*
* import modchest.block.custom.grid.gridBlock;
* import modchest.rendering.gridBlockTexture;
* import net.fabricmc.fabric.api.networking.v1.PacketSender;
* import net.minecraft.block.Block;
* import net.minecraft.block.BlockState;
* import net.minecraft.block.Blocks;
* import net.minecraft.block.entity.BlockEntity;
* import net.minecraft.client.MinecraftClient;
* import net.minecraft.client.color.block.BlockColors;
* import net.minecraft.client.network.ClientPlayNetworkHandler;
* import net.minecraft.client.render.BufferBuilder;
* import net.minecraft.client.render.OverlayTexture;
* import net.minecraft.client.render.RenderLayer;
* import net.minecraft.client.render.Tessellator;
* import net.minecraft.client.render.VertexConsumer;
* import net.minecraft.client.render.VertexConsumerProvider;
* import net.minecraft.client.render.VertexFormat;
* import net.minecraft.client.render.VertexFormats;
* import net.minecraft.client.render.WorldRenderer;
* import net.minecraft.client.render.block.BlockModelRenderer;
* import net.minecraft.client.render.entity.ItemFrameEntityRenderer;
* import net.minecraft.client.render.model.BakedModel;
* import net.minecraft.client.util.ModelIdentifier;
* import net.minecraft.client.util.SpriteIdentifier;
* import net.minecraft.client.util.math.MatrixStack;
* import net.minecraft.entity.decoration.ItemFrameEntity;
* import net.minecraft.entity.player.PlayerEntity;
* import net.minecraft.nbt.NbtCompound;
* import net.minecraft.network.PacketByteBuf;
* import net.minecraft.text.Text;
* import net.minecraft.util.Identifier;
* import net.minecraft.util.math.BlockPos;
* import net.minecraft.util.math.Matrix3f;
* import net.minecraft.util.math.Matrix4f;
* import net.minecraft.world.BlockRenderView;
*
* public class gridRenderRequestS2CPacket extends BlockModelRenderer {
*
* public gridRenderRequestS2CPacket(BlockColors colors) {
* super(colors);
* // TODO Auto-generated constructor stub
* }
*
*
*
* public static void receive(MinecraftClient minecraftClient,
* ClientPlayNetworkHandler clientPlayNetworkHandler,
* PacketByteBuf buffer, PacketSender PacketSender) {
*
* NbtCompound nbtgrid = buffer.readNbt();
* int[] gridPostitionAr = nbtgrid.getIntArray("gridBlockPos");
* int x = gridPostitionAr[0];
* int y = gridPostitionAr[1];
* int z = gridPostitionAr[2];
* BlockPos gridBlockPos = new BlockPos(x, y, z);
*
*
* /*PlayerEntity playerEntity = minecraftClient.player;
* playerEntity.sendMessage(Text.of("gridRenderRequestS2CPacket.receive"));
* BlockRenderView world = minecraftClient.world;
*
* NbtCompound nbtgrid = buffer.readNbt();
* int[] gridPostitionAr = nbtgrid.getIntArray("gridBlockPos");
* int x = gridPostitionAr[0];
* int y = gridPostitionAr[1];
* int z = gridPostitionAr[2];
* BlockPos gridBlockPos = new BlockPos(x, y, z);
*
* /*
* long seed = nbtgrid.getLong("WorldSeed");
* Random randomGrid = new Random(seed);
* BlockState gridBlockState = world.getBlockState(gridBlockPos);
* //playerEntity.sendMessage(Text.of(gridBlockState.toString())); //
* {minecraft:spruce_planks}
* Block BlockInHand =
* getBlockFromItem(playerEntity.getMainHandStack().getItem());
* String inHandData = BlockInHand.getDefaultState().toString();
* //playerEntity.sendMessage(Text.of(inHandData)); // Bsp:
* {minecraft:warped_planks}
* BlockState stateInHand = BlockInHand.getDefaultState();
* Object obj = inHandData.split("minecraft:");
* //playerEntity.sendMessage(Text.of(obj.toString())); // Bsp:
* java.lang.string;@4f4001c7
* Identifier gridBlockId = new Identifier("modchest", "block/grid_block"); //
* Mod-ID + Blockpfad
* //playerEntity.sendMessage(Text.of(gridBlockId.toString()));
* // minecraftClient.getBakedModelManager().getBlockModels();
* // minecraftClient.getSpriteAtlas(gridBlockTexture.getBlockInHandId(null));
* playerEntity.sendMessage(Text.of("before bracket"));
*
* //ModelIdentifier gridModelId = (ModelIdentifier) gridBlockId; -> geht nicht,
* gridBlockId nicht instance of ModelIdentifier
* // playerEntity.sendMessage(Text.of(gridModelId.toString()));
* //BakedModel gridModel =
* MinecraftClient.getInstance().getBakedModelManager().getModel(gridModelId);
* //int overlay = OverlayTexture.DEFAULT_UV;
* //MatrixStack matrix = new MatrixStack();
* //MatrixStack.Entry matrix;
* //Tessellator tessellator = Tessellator.getInstance();
* //Matrix4f positionMatrix =
* drawContext.getMatrices().peek().getPositionMatrix();
* //BufferBuilder builder = tessellator.getBuffer();
* /*builder.begin(VertexFormat.DrawMode.QUADS,
* VertexFormats.POSITION_COLOR_TEXTURE);
* builder.vertex(positionMatrix, 20, 20, 0).color(1f, 1f, 1f, 1f).texture(0f,
* 0f).next();
* builder.vertex(positionMatrix, 20, 60, 0).color(1f, 0f, 0f, 1f).texture(0f,
* 1f).next();
* builder.vertex(positionMatrix, 60, 60, 0).color(0f, 1f, 0f, 1f).texture(1f,
* 1f).next();
* builder.vertex(positionMatrix, 60, 20, 0).color(0f, 0f, 1f, 1f).texture(1f,
* 0f).next();
* // RenderSystem.setShader(null);
* // RenderSystem.setShaderTexture(0, new Identifier("REServerMod",
* // "block/grid_block_texture.png"));
* // RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
* tessellator.draw();
* builder.begin(VertexFormat.DrawMode.QUADS,
* VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL); //kaputt
* builder.vertex(1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1); //kaputt
* builder.popState(); //funktioniert ohne Zwei Zeilen davor
*/
// drawContext.getMatrices().peek().getPositionMatrix(): Matrix4f positionMatrix
// = drawContext.getMatrices().peek().getPositionMatrix();
import static net.minecraft.block.Block.getBlockFromItem; /*
* Tessellator tessellator = Tessellator.getInstance();
/*import modchest.rendering.gridBlockRender; * BufferBuilder bufferBuilder = tessellator.getBuffer();
import modchest.rendering.gridBlockTexture;*/ *
import net.fabricmc.fabric.api.networking.v1.PacketSender; * MatrixStack matrices = new MatrixStack();
import net.minecraft.block.Block; * BlockState defaultState = Blocks.STONE.getDefaultState();
import net.minecraft.client.MinecraftClient; * playerEntity.sendMessage(Text.of(defaultState.toString()));
import net.minecraft.client.color.block.BlockColors; * VertexConsumerProvider consumers =
import net.minecraft.client.network.ClientPlayNetworkHandler; * VertexConsumerProvider.immediate(bufferBuilder);
import net.minecraft.client.network.ClientPlayerEntity; * playerEntity.sendMessage(Text.of(consumers.toString()));
import net.minecraft.client.render.block.BlockModelRenderer; * Identifier TEXTURE = new Identifier("modchest",
import net.minecraft.entity.player.PlayerEntity; * "textures/block/texture_test.png");
import net.minecraft.nbt.NbtCompound; * playerEntity.sendMessage(Text.of(TEXTURE.toString()));
import net.minecraft.network.PacketByteBuf; * //SpriteIdentifier SPRITE = ;
import net.minecraft.text.Text; * //SpriteIdentifier#getVertexConsumer( consumers, LAYER_SUPPLIER ) // to use a
import net.minecraft.util.math.BlockPos; * sprite as a texture
* //VertexConsumer consumer = consumers.getBuffer(RenderLayer.getCutout());
public class gridRenderRequestS2CPacket extends BlockModelRenderer { * //VertexConsumer consumer =
* consumers.getBuffer(RenderLayer.getEntityCutout(TEXTURE));
public gridRenderRequestS2CPacket(BlockColors colors) { * //playerEntity.sendMessage(Text.of(consumer.toString()));
super(colors); * /*MatrixStack.Entry matrix = matrices.peek();
// TODO Auto-generated constructor stub * matrices.push();
} * matrices.translate(0.5, 0.5, 0.5);
* Matrix4f model = matrix.getPositionMatrix();
public static void receive(MinecraftClient minecraftClient, ClientPlayNetworkHandler clientPlayNetworkHandler, * Matrix3f normal = matrix.getNormalMatrix();
PacketByteBuf buffer, PacketSender PacketSender) { * int r = 225;
// clientPlayNetworkHandler.getWorld(); * int g = 255;
NbtCompound nbtgrid = buffer.readNbt(); * int b = 255;
int[] positionarray = nbtgrid.getIntArray("BlockPosition"); * int a = 200;
Integer h = positionarray[0]; *
Integer i = positionarray[1]; * //int light = gridBlockState.getLuminance();
Integer j = positionarray[2]; * int light = WorldRenderer.getLightmapCoordinates(world, gridBlockPos);
* int overlay = OverlayTexture.DEFAULT_UV;
BlockPos gridBlockPos = new BlockPos(h, i, j); *
* consumer.vertex(model, -0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(0,
// minecraftClient.getBakedModelManager().getBlockModels(); * 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
// minecraftClient.getSpriteAtlas(gridBlockTexture.getBlockInHandId(null)); * consumer.vertex(model, 0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(1,
* 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
//BlockRenderView world = minecraftClient.world; * consumer.vertex(model, 0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(1,
* 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
/*@Nullable * consumer.vertex(model, -0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(0,
BlockState gridBlockState = getStateFromRawId(FORCE_STATE); * 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
MatrixStack matrix = new MatrixStack(); * matrices.pop();
MatrixStack.Entry entry; *
Random randomGrid = new Random(); * MinecraftClient.getInstance().getBlockRenderManager().renderBlockAsEntity(
long seed = 7756495;*/ * defaultState, matrices, consumers, light, overlay);
*
PlayerEntity playerEntity = minecraftClient.player; * /*
Block BlockInHand = getBlockFromItem(playerEntity.getMainHandStack().getItem()); *
String inHandData = BlockInHand.getDefaultState().toString(); * SpriteIdentifier SPRITE =;
playerEntity.sendMessage(Text.of(inHandData)); * // solid layer, no texture
* VertexConsumer consumer = consumers.getBuffer(RenderLayer.getSolid());
//Identifier testBlockId = new Identifier("modchest", "block/test_block"); // Mod-ID + Blockpfad * // cutout layer, textured
//ModelIdentifier testModelId = new ModelIdentifier(testBlockId, "all"); // Verwende "normal" als Variante * VertexConsumer consumer =
//BakedModel gridModel = MinecraftClient.getInstance().getBakedModelManager().getModel(testModelId); * consumers.getBuffer(RenderLayer.getEntityCutout(TEXTURE));
* // cutout layer, textured (sprite)
/* * VertexConsumer consumer = SPRITE.getVertexConsumer(consumers,
* gridBlockRender.render(world, BakedModel model, gridBlockState, gridBlockPos, * RenderLayer::getEntityCutout);
* matrix, gridConsumer, true, randomGrid, seed, overlay); * Identifier texture = new Identifier("textures/block/texture_test.png");
*/ * // set texture and enable transparency
* VertexConsumer consumer =
} * consumers.getBuffer(RenderLayer.getEntityTranslucentCull(texture));
* MatrixStack.Entry matrix = matrices.peek();
} * // translate to the middle of the block
* matrices.push();
* matrices.translate(0.5, 0.5, 0.5);
* Matrix4f model = matrix.getModel();
* Matrix3f normal = matrix.getNormal();
* int r = 255;
* int g = 255;
* int b = 255;
* int a = 200;
* // use the value provided (in block entity renderer) for breaking animation,
* or
* // use 'OverlayTexture.DEFAULT_UV' to disable breaking animation
* int overlay = OverlayTexture.DEFAULT_UV;
* // provided by block entity renderer, or queried from WorldRenderer:
* // (use only to query light at positions different than provided)
* int light = WorldRenderer.getLightmapCoordinates(world, gridBlockPos);
* // emit 4 vertices - one quad
* consumer.vertex(model, -0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(0,
* 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
* consumer.vertex(model, 0.5f, -0.5f, -0.5f).color(r, g, b, a).texture(1,
* 0).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
* consumer.vertex(model, 0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(1,
* 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
* consumer.vertex(model, -0.5f, -0.5f, 0.5f).color(r, g, b, a).texture(0,
* 1).overlay(overlay).light(light).normal(normal, 0.0F, 1.0F, 0.0F).next();
* matrices.pop();
*
*
* // gridBlockRender.render(world, gridModel, gridBlockState, gridBlockPos,
* // matrix, gridConsumer, true, randomGrid, seed, overlay);
*
* }
*
* }
*/

View File

@ -1,24 +0,0 @@
package modchest.rendering;
import net.minecraft.block.BlockState;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.block.BlockModelRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
public class gridBlockRender extends BlockModelRenderer{
public gridBlockRender(BlockColors colors) {
super(colors);
}
@Override
public void render(BlockRenderView world, BakedModel model, BlockState state, BlockPos pos,
MatrixStack matrices, VertexConsumer vertexConsumer, boolean cull, Random random, long seed, int overlay) {
}
}

View File

@ -0,0 +1,96 @@
package modchest.transform;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import modchest.util.Float4;
import modchest.util.ToOptional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
@Environment(EnvType.CLIENT)
public abstract class BaseApplier implements ToOptional<BaseApplier> {
public abstract TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 vs, int color);
public static final BaseApplier NONE = new BaseApplier() {
@Override
public TransformResult apply(MutableQuadView mqv, Direction dir, int index, Float4 vs, int color) {
return TransformResult.NOTHING_TO_DO;
}
@Override
public Optional<BaseApplier> toOptional() {
return Optional.empty();
}
@Override
public <T> T match(final Function<BaseApplier, T> some, final Supplier<T> none) {
return none.get();
}
};
public static class Some extends BaseApplier implements ToOptional.Some<BaseApplier> {
private final BlockState state;
private final Object2IntMap<Direction> sizes = new Object2IntOpenHashMap<>(7);
private final Map<Direction, SpriteApplier[]> spriteAppliers = new HashMap<>(7);
private final Map<Direction, MaterialApplier[]> materialAppliers = new HashMap<>(7);
private final Map<Direction, LazyColorApplier[]> colorAppliers = new HashMap<>(7);
public Some(final BlockState state, final BakedModel model, final Random r) {
this.state= state;
for (int i = 0; i<= 6; i++) {
final Direction dir = ModelHelper.faceFromIndex(i);
final List<BakedQuad> quads = model.getQuads(state, dir, r);
final int size = quads.size();
sizes.put(dir, size);
final SpriteApplier[] spriteAppliers = this.spriteAppliers.computeIfAbsent(dir, x -> new SpriteAppliers[size]);
final MaterialApplier[] materialAppliers = this.materialAppliers.computeIfAbsent(dir, x -> new MaterialApplier[size]);
final LazyColorApplier[] colorAppliers = this.colorAppliers.computeIfAbsent(dir, x -> new LazyColorApplier[size]);
for(int j = 0; j < size; j++) {
final BakedQuad quad = quads.get(j);
final Sprite sprite = ((BakedQuadAccess) quad).sprite();
spriteAppliers[j] = new SpriteApplier.Some(sprite);
materialAppliers[j] = new MaterialApplier,ofSpriteAndBlockState(sprite, state);
if (quad.hasColor()) {
colorAppliers[j] = new LazyColorApplier.Some();
} else {
colorAppliers[j] = LazyColorApplier.NONE;
}
}
}
}
@Override
public TransformResult apply(MutableQuadView mqv, Direction dir, int quadIndex, Float4 vs, int color) {
int size = sizes.getInt(dir);
if (size == 0) {
return TransformResult.failed(String.format("No %s quads in model for %s", dir, state));
}
final int index = quadIndex % size;
materialAppliers.get(dir)[index].apply(mqv);
colorAppliers.get(dir)[index].apply(mqv, color);
return spriteAppliers.get(dir)[index].apply(mqv, us, vs);
}
}
}

View File

@ -0,0 +1,56 @@
package modchest.transform;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Function;
import java.util.function.Supplier;
import modchest.util.ToOptional;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
@Environment(EnvType.CLIENT)
public abstract class ColorApplier implements ToOptional<ColorApplier> {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public static ColorApplier ofOptional(final OptionalInt optional) {
if (optional.isPresent()) {
return new Some(optional.getAsInt());
} else {
return NONE;
}
}
public abstract void apply(MutableQuadView mqv);
@SuppressWarnings("java:S1186")
public static final ColorApplier NONE = new ColorApplier() {
@Override
public void apply(final MutableQuadView mqv) {
}
@Override
public Optional<ColorApplier> toOptional() {
return Optional.empty();
}
@Override
public <T> T match(final Function<ColorApplier, T> some, final Supplier<T> none) {
return none.get();
}
};
public static class Some extends ColorApplier implements ToOptional.Some<ColorApplier> {
private final int color;
public Some(final int color) {
this.color = color;
}
@Override
public void apply(final MutableQuadView mqv) {
mqv.spriteColor(0, color, color, color, color);
}
}
}

View File

@ -0,0 +1,26 @@
package modchest.transform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
@Environment(EnvType.CLIENT)
public abstract class LazyColorApplier {
@SuppressWarnings("java:S1186")
public static final LazyColorApplier NONE = new LazyColorApplier() {
@Override
public void apply(final MutableQuadView mqv, final int color) {
}
};
public abstract void apply(MutableQuadView mqv, int color);
public static class Some extends LazyColorApplier {
@Override
public void apply(final MutableQuadView mqv, final int color) {
mqv.spriteColor(0, color, color, color, color);
}
}
}

View File

@ -0,0 +1,62 @@
package modchest.transform;
import java.util.Optional;
import javax.swing.text.html.Option;
import org.jetbrains.annotations.NotNull;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.minecraft.block.BlockState;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
@Environment(EnvType.CLIENT)
public abstract class MaterialApplier {
public static MaterialApplier ofSpriteAndBlockState(@NotNull final Sprite sprite, @NotNull final BlockState blockState) {
if (blockState == null) {
return NONE;
}
final RenderMaterial material = MaterialMap.get(blockState).getMapped(sprite);
final Identifier id = Registry.BLOCK.getId(blockState.getBlock());
return MaterialApplier.ofNullable(id, material);
}
public static final MaterialApplier NONE = new MaterialApplier() {
@Override
public void apply(final MutableQuadView mqv) {}
@Override
public Optional<Identifier> id() {
return Optional.empty();
}
};
public abstract void apply(MutableQuadView mqv);
public abstract Optional<Identifier> id();
public static class Some extends MaterialApplier {
private final @NotNull Identifier id;
private final @NotNull RenderMaterial toApply;
public Some(final @NotNull Identifier id, final @NotNull RenderMaterial toApply) {
this.toApply = toApply;
this.id = id;
}
@Override
public void apply(final MutableQuadView mqv) {
mqv.material(toApply);
}
@Override
public Optional<Identifier> id() {
return Optional.of(id);
}
}
}

View File

@ -0,0 +1,66 @@
package modchest.transform;
import org.jetbrains.annotations.Nullable;
import modchest.util.Float4;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.minecraft.client.texture.MissingSprite;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
@Environment(EnvType.CLIENT)
public abstract class SpriteApplier {
public static SpriteApplier ofNullable(@Nullable final Sprite toApply) {
if (toApply != null) {
return new Some(toApply);
} else {
return NONE;
}
}
public abstract TransformResult apply(MutableQuadView mqv, Float4 us, Float4 vs);
public abstract Identifier id();
public static final SpriteApplier NONE = new SpriteApplier() {
@Override
public TransformResult apply(final MutableQuadView mqv, final Float4 us, final Float4 vs) {
return TransformResult.NOTHING_TO_DO;
}
@Override
public Identifier id() {
return MissingSprite.getMissingSpriteId();
}
};
public static class Some extends SpriteApplier {
private final Sprite toApply;
public Some(final Sprite toApply) {
this.toApply = toApply;
}
@Override
public TransformResult apply(final MutableQuadView mqv, final Float4 us, final Float4 vs) {
mqv.sprite(0, 0, MathHelper.lerp(us.a, toApply.getMinU(), toApply.getMaxU()),
MathHelper.lerp(vs.a, toApply.getMinV(), toApply.getMaxV()));
mqv.sprite(1, 0, MathHelper.lerp(us.b, toApply.getMinU(), toApply.getMaxU()),
MathHelper.lerp(vs.b, toApply.getMinV(), toApply.getMaxV()));
mqv.sprite(2, 0, MathHelper.lerp(us.c, toApply.getMinU(), toApply.getMaxU()),
MathHelper.lerp(vs.c, toApply.getMinV(), toApply.getMaxV()));
mqv.sprite(3, 0, MathHelper.lerp(us.d, toApply.getMinU(), toApply.getMaxU()),
MathHelper.lerp(vs.d, toApply.getMinV(), toApply.getMaxV()));
return TransformResult.DID_SOMETHING;
}
@Override
public Identifier id() {
return toApply.getId();
}
}
}

View File

@ -0,0 +1,31 @@
package modchest.transform;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class TransformResult {
public enum Status {
DID_SOMETHING,
NOTHING_TO_DO,
FAILED,;
}
public static final TransformResult DID_SOMETHING = new TransformResult(Status.DID_SOMETHING, null);
public static final TransformResult NOTHING_TO_DO = new TransformResult(Status.NOTHING_TO_DO, null);
public final Status status;
public final @Nullable String message;
private TransformResult(Status status, @Nullable String message) {
this.status = status;
this.message = message;
}
public static TransformResult failed(String message) {
return new TransformResult(Status.FAILED, message);
}
}

View File

@ -0,0 +1,207 @@
package modchest.transform;
import java.util.EnumMap;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import modchest.block.custom.grid.gridSlotInfo;
import modchest.grid.data.gridData;
import modchest.util.Float4;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Overlay;
import net.minecraft.client.texture.SpriteAtlasTexture.Data;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
@Environment(EnvType.CLIENT)
public final class gridTransform implements RenderContext.QuadTransform {
public static final QuadTransformRegistry.QuadTransformSource SOURCE = new QuadTransformRegistry.QuadTransformSource() {
@Override
public RenderContext.QuadTransform getForBlock(final BlockRenderView brv, final BlockState state,
final BlockPos pos, final Supplier<Random> randomSupplier) {
return new gridTransform(brv, state, pos, randomSupplier);
}
@Override
public RenderContext.QuadTransform getForItem(final ItemStack stack, final Supplier<Random> randomSupplier) {
final gridSlotInfo slotInfo = (gridSlotInfo) ((BlockItem) stack.getItem()).getBlock();
if (!stack.hasTag()) {
return new gridTransform(slotInfo, new gridData(slotInfo.sections()), randomSupplier);
} else {
return new gridTransform(slotInfo,
gridData.fromTag(stack.getSubTag("BlockEntityTag").getCompound("gridData")), randomSupplier);
}
}
};
private final EnumMap<Direction, Integer> transformCount = new EnumMap<>(Direction.class);
@Override
public boolean transform(MutableQuadView mqv) {
if (mqv.tag() == 0) {
return true;
}
final Direction dir = mqv.lightFace();
final int quadIndex = transformedCount.computeIfAbsent(dir, d-> 0);
transformedCount.put(dir, quadIndex + 1);
final int partIndex = getPartIndex(mqv, dir);
final Data data = this.data[partIndex];
final Pair<Float4, Float4> origUvs = getUvs(mqv, dir);
if (mqv.tag() == 1) {
TransformResult result = data.baseApplier.apply(mqv, dir, quadIndex, origUvs.getFirst(), origUvs.getSecond(), data.baseColor);
switch (result.status) {
case DID_SOMETHING:
case NOTHING_TO_DO:
return true;
case FAILED:
META:LOGGER.warn("An error occured with a gridEntity:" + result.message);
return false;
}
} else if (mqv.tag() == 2) {
TransformResult result = data.overlay.match(overlay -> {
data.overlayColorApplier.apply(mqv);
return overlay.apply(mqv, dir, quadIndex, origUvs.getFirst(), origUvs.getSecond(), data.baseColor)
},
() -> data.baseApplier.apply(mqv, dir, quadIndex, origUvs.getFirst(), origUvs.getSecond(), data.baseColor)
);
switch (result.status) {
case DID_SOMETHING:
return true;
case NOTHING_TO_DO:
return false;
case FAILED:
META:LOGGER.warn("An error occured with a gridEntity:" + result.message);
}
} else {
return false;
}
META.LOGGER.warn("Somehow gridTransform::transform didn't return a valid value");
return false;
}
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private static class Data {
public final BaseApplier baseApplier;
public final Overlay overlay;
public final ColorApplier overlayColorApplier;
public final int baseColor;
public Data(final BaseApplier baseApplier, final Overlay overlay, final OverlayInt maybeCachedOverlayColor,
final int baseColor) {
this.baseApplier = baseApplier;
this.overlay = overlay;
this.overlayColorApplier = ColorApplier.ofOptional(maybeCachedOverlayColor);
this.baseColor = baseColor;
}
}
private final gridSlotInfo slotInfo;
private final Data[] data;
private gridTransform(final gridSlotInfo slotInfo, final BlockRenderView brv, final BlockPos pos,
final Supplier<Random> ranSupplier,
final List<Pair<Optional<BlockState>, Optional<Identifier>>> attachment) {
this.slotInfo = slotInfo;
data = attachment.stream().map(pair -> {
final Optional<BlockState> maybeBaseState = pair.getFirst();
final int color;
final BaseApplier baseApplier;
if (maybeBaseState.isPresent()) {
final BlockState baseState = maybeBaseState.get();
color = Optional.ofNullable(ColorProviderRegistry.BLOCK.get(baseState.getBlock()))
.map(prov -> prov.getColor(baseState, brv, pos, 1) | 0xFF000000).orElse(0xFFFFFFFF);
baseApplier = new BaseApplier.Some(baseState,
MinecraftClient.getInstance().getBlockRenderManager().getModel(baseState),
randomSupplier.get());
} else {
color = 0xFFFFFFFF;
baseApplier = BaseApplier.NONE;
}
final Overlay overlay = pair.getSecond().map(CLIENT_OVERLAYS::getOverlayFor).orElse(Overlay.NONE);
final OptionalInt cachedOverlayColor = flatMapToInt(overlay.coloredLike(), coloredLike -> mapToInt(
Optional.ofNullable(ColorProviderRegistry.BLOCK.get(coloredLike.colorSource().getBlock())),
prov -> prov.getColor(coloredLike.colorSource(), brv, pos, 1) | 0xFF000000));
return new Data(baseApplier, overlay, cachedOverlayColor, color);
}).toArray(Data[]::new);
}
private gridTransform(final gridSlotInfo slotInfo, final gridData gridData, final Supplier<Random> randomSupplier) {
this(slotInfo, MinecraftClient.getInstance().player.clientWorld,
MinecraftClient.getInstance().player.getBlockPos(), randomSupplier, gridData.toRenderAttachment());
}
private gridTransform(final BlockRenderView brv, final BlockState state, final BlockPos pos,
final Supplier<Random> randomSupplier) {
this(
(gridSlotInfo) state.getBlock(),
brv,
pos,
randomSupplier,
(List<Pair<Optional<BlockState>, Optional<Identifier>>>) ((RenderAttachedBlockView) brv)
.getBlockEntityRenderAttachment(pos));
}
protected int getPartIndex(final MutableQuadView mqv, final Direction dir) {
return slotInfo.getRelativeSlotAt(
new Vec3d(calcCenter(mqv::x), calcCenter(mqv::y), calcCenter(mqv::z)), dir);
}
protected Pair<Float4, Float4> getUvs(final MutableQuadView mqv, final Direction dir) {
final IntStream us = IntStream.rangeClosed(0, 3);
final IntStream vs = IntStream.rangeClosed(0, 3);
switch (dir) {
case DOWN:
return Pair.of(
Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.x(i), 0, 1)).iterator()),
Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.z(i), 0, 1)).iterator()));
case UP:
return Pair.of(
Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.x(i), 0, 1)).iterator()),
Float4.fromIterator(vs.mapToDouble(i -> MathHelper.clamp(mqv.z(i), 0, 1)).iterator()));
case NORTH:
return Pair.of(
Float4.fromIterator(us.mapToDouble(i -> 1 - MathHelper.clamp(mqv.x(i), 0f, 1f)).iterator()),
Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator()));
case SOUTH:
return Pair.of(
Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.x(i), 0f, 1f)).iterator()),
Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator()));
case EAST:
return Pair.of(
Float4.fromIterator(us.mapToDouble(i -> 1 - MathHelper.clamp(mqv.z(i), 0f, 1f)).iterator()),
Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator()));
case WEST:
return Pair.of(
Float4.fromIterator(us.mapToDouble(i -> MathHelper.clamp(mqv.z(i), 0f, 1f)).iterator()),
Float4.fromIterator(vs.mapToDouble(i -> 1 - MathHelper.clamp(mqv.y(i), 0f, 1f)).iterator()));
default:
throw new IllegalArgumentException("Invalid direction:" + dir);
}
}
}

View File

@ -0,0 +1,27 @@
package modchest.util;
import it.unimi.dsi.fastutil.ints.Int2FloatFunction;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class QuadUtil {
private QuadUtil() {
throw new IllegalStateException("Should not instantiate utility class.");
}
public static float calcCenter(final Int2FloatFunction key) {
float min = Float.POSITIVE_INFINITY;
float max = Float.NEGATIVE_INFINITY;
for ( int i = 0; i <= 3; i++) {
final float cur = key.get(i);
if (cur > max) {
max = cur;
} else if (cur < min) {
min = cur;
}
}
return (min +max) / 2;
}
}

View File

@ -0,0 +1,27 @@
package modchest.util;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.function.Function;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public interface ToOptional<O extends ToOptional<O>> {
Optional<O> toOptional();
<T> T match(Function<O, T> some, Supplier<T> none);
interface Some<O extends ToOptional<O>> extends ToOptional<O> {
default Optional<O> toOptional() {
return Optional.of((O) this);
}
@Override
default <T> T match(final Function<O, T> some, final Supplier<T> none) {
return some.apply((O) this);
}
}
}

View File

@ -2,8 +2,18 @@ package modchest;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.resource.ResourceType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import modchest.data.OverlayDataListener;
import modchest.grid.gridBlockEntityTypes;
import modchest.grid.gridBlocks;
import modchest.grid.gridItems;
import modchest.grid.gridMeta;
import modchest.item.custom.SpecialItems;
import modchest.util.initializer; import modchest.util.initializer;
//Main file; Hier wird alles aufgesetzt //Main file; Hier wird alles aufgesetzt
@ -11,6 +21,16 @@ public class REServerMod implements ModInitializer {
public static final String MOD_ID = "modchest"; public static final String MOD_ID = "modchest";
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
public static REServerModProperties PROPERTIES;
public static SpecialItems SPECIAL_ITEMS;
public static gridMeta META;
public static gridBlocks BLOCKS;
public static gridItems ITEMS;
public static gridBlockEntityTypes BLOCK_ENTITY_TYPES;
public static OverlayDataListener OVERLAYS;
@Override @Override
public void onInitialize() { //Der uebersicht halber sind jetzt alle initializer in Klassen in util in initializer public void onInitialize() { //Der uebersicht halber sind jetzt alle initializer in Klassen in util in initializer
initializer.itemGroups(); initializer.itemGroups();
@ -18,6 +38,17 @@ public class REServerMod implements ModInitializer {
initializer.events(); initializer.events();
initializer.networking(); initializer.networking();
PROPERTIES = new GridProperties();
SPECIAL_ITEMS = new SpecialItems();
META = new gridMeta()
BLOCKS = new gridBlocks();
ITEMS = new gridItems();
BLOCK_ENTITY_TYPES = new gridBlockEntityTypes();
OVERLAYS = new OverlayDataListener();
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(OVERLAYS);
LOGGER.info("Modchest successfully loaded!"); LOGGER.info("Modchest successfully loaded!");
} }
} }

View File

@ -1,5 +0,0 @@
package modchest.block.custom;
public class grid {
}

View File

@ -0,0 +1,40 @@
package modchest.block.custom.grid;
public interface grid {
/*
* public static PacketByteBuf writeBufferEntity(EntityHitResult hitResult,
* ServerWorld serverWorld) {
* long seed = serverWorld.getSeed();
* Vec3d gridEntityPos = hitResult.getPos();
* NbtCompound Nbtgrid = new NbtCompound();
* double gridX = gridEntityPos.getX();
* Nbtgrid.putDouble("gridX", gridX);
* double gridY = gridEntityPos.getY();
* Nbtgrid.putDouble("gridY", gridY);
* double gridZ = gridEntityPos.getZ();
* Nbtgrid.putDouble("gridZ", gridZ);
* Nbtgrid.putLong("WorldSeed", seed);
* PacketByteBuf gridBuffer = PacketByteBufs.create();
* gridBuffer.writeNbt(Nbtgrid);
* return gridBuffer;
* }
*
*
* public static PacketByteBuf writeBufferBlock(BlockHitResult hitResult,
* ServerWorld serverWorld){
* long seed = serverWorld.getSeed();
* BlockPos gridBlockPos = hitResult.getBlockPos();
* int[] gridBlockPosAr = new int[3];
* gridBlockPosAr [0] = gridBlockPos.getX();
* gridBlockPosAr [1] = gridBlockPos.getY();
* gridBlockPosAr [2] = gridBlockPos.getZ();
* NbtCompound Nbtgrid = new NbtCompound();
* Nbtgrid.putIntArray("gridBlockPos", gridBlockPosAr);
* Nbtgrid.putLong("WorldSeed", seed);
* PacketByteBuf gridBlockBuffer = PacketByteBufs.create();
* return gridBlockBuffer;
*
* }
*/
}

View File

@ -0,0 +1,151 @@
package modchest.block.custom.grid;
import net.minecraft.block.Block;
import net.minecraft.util.math.Direction;
import net.minecraft.block.BlockState;
public class gridBlock extends Block {
public gridBlock(final Settings settings) {
super(settings);
}
@SuppressWarnings("deprecation")
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom);
}
}
/*
* public gridBlock(Settings settings) {
* super(settings);
* }
*
* @SuppressWarnings("deprecation")
*
* @Override
* public boolean isSideInvisible(BlockState state, BlockState stateFrom,
* Direction direction) {
* return super.isSideInvisible(state, stateFrom, direction) || (state ==
* stateFrom);
* }
*
* /* BLOCK ENTITY
*/
/*
* @Override
* public BlockRenderType getRenderType(BlockState state) { // sonst Block
* unsichtbar
* return BlockRenderType.MODEL;
* }
*
* @Override
* public BlockEntity createBlockEntity(BlockPos arg0, BlockState arg1) {
* // TODO Auto-generated method stub
* throw new
* UnsupportedOperationException("Unimplemented method 'createBlockEntity'");
* }
*
* /*@SuppressWarnings("deprecation")
*
* @Override
* public void onStateReplaced(BlockState state, World world, BlockPos pos,
* BlockState newState, boolean moved) { // wenn Block zerstört wird Inventar
* Inhalt in die Welt gespawnt
* if (state.getBlock() != newState.getBlock()) {
* BlockEntity blockEntity = world.getBlockEntity(pos);
* if (blockEntity instanceof gridBlockEntity) {
* ItemScatterer.spawn(world, pos, (gridBlockEntity) blockEntity);
* world.updateComparators(pos, this);
* }
* super.onStateReplaced(state, world, pos, newState, moved);
* }
* }
*/
/*
* @SuppressWarnings("deprecation")
*
* @Override
* public ActionResult onUse(BlockState state, World world, BlockPos pos,
* PlayerEntity player, Hand hand,
* BlockHitResult hitResult) {
*
* if (!world.isClient) {
* NamedScreenHandlerFactory screenHandlerFactory =
* state.createScreenHandlerFactory(world, pos);
*
* if (screenHandlerFactory != null) {
* player.openHandledScreen(screenHandlerFactory);
* }
* }
* player.sendMessage(Text.literal("onUse"));
* return ActionResult.SUCCESS;
* /*
* if (!world.isClient) {
* Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem());
* BlockState StateInHand = BlockInHand.getDefaultState();
* BlockPos gridBlockPos = hitResult.getBlockPos();
* if
* (world.getBlockState(hitResult.getBlockPos()).getBlock().toString().equals(
* "Block{modchest:grid_block}")
* && player.isSpectator() == false) {
* if (BlockInHand instanceof gridBlock) {
* return ActionResult.PASS;
* } else {
* player.sendMessage(Text.of("gridBlock benutzt"));
* // world.setBlockState(gridBlockPos, StateInHand); // tauscht den "benutzten"
* // gridBlock mit dem
* // Blocks in der Hand, wie platzieren, nur cooler
* player.getMainHandStack().decrement(1);
* player.jump();
* // player.onLanding(player.playSoundIfNotSilent());
* if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) {
* // nötig, um
* // sicherzustellen, dass
* // eine
* // ServerPlayerEntity
* // fürs networking übergeben wird und nicht eine
* // PlayerEntity, da sonst Absturz; gleiches für ServerWorld
* ServerWorld serverWorld = (ServerWorld) world;
* ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
* ServerPlayNetworking.send(serverPlayer,
* modNetworkingServer.grid_block_networking,
* grid.writeBufferBlock(hitResult, serverWorld));
* }
* }
* } else {
* return ActionResult.PASS;
* }
*
* }
* return ActionResult.SUCCESS;
*/
/*
* }
*
* @Override
* public BlockEntity createBlockEntity(BlockPos arg0, BlockState arg1) {
* // TODO Auto-generated method stub
* throw new
* UnsupportedOperationException("Unimplemented method 'createBlockEntity'");
* }
*/
/*
* @Override
* public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
* return new gridBlockEntity(pos, state);
* }
*
* @Override
* public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world,
* BlockState state, BlockEntityType<T> type) {
* return checkType(type, modBlockEntities.grid_block_entity,
* gridBlockEntity::tick);
* }
* }
*/

View File

@ -0,0 +1,10 @@
package modchest.block.custom.grid;
import net.minecraft.block.CarpetBlock;
public class gridCarpet extends CarpetBlock {
public gridCarpet(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,10 @@
package modchest.block.custom.grid;
import net.minecraft.block.DoorBlock;
public class gridDoor extends DoorBlock {
public gridDoor(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,10 @@
package modchest.block.custom.grid;
import net.minecraft.block.FenceBlock;
public class gridFence extends FenceBlock{
public gridFence(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,11 @@
package modchest.block.custom.grid;
import net.minecraft.block.FenceGateBlock;
public class gridFenceGate extends FenceGateBlock{
public gridFenceGate(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,11 @@
package modchest.block.custom.grid;
import net.minecraft.block.SnowBlock;
public class gridLayer extends SnowBlock{
public gridLayer(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,11 @@
package modchest.block.custom.grid;
import net.minecraft.block.PaneBlock;
public class gridPane extends PaneBlock{
public gridPane(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,17 @@
package modchest.block.custom.grid;
import net.minecraft.block.AbstractBlock.Settings;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.Direction;
public class gridPath extends PathBlock {
public gridPath(final Settings settings) {
super(settings);
}
@SuppressWarnings("deprecation")
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom);
}
}

View File

@ -0,0 +1,11 @@
package modchest.block.custom.grid;
import net.minecraft.block.PressurePlateBlock;
public class gridPressurePlate extends PressurePlateBlock{
public gridPressurePlate(ActivationRule type, Settings settings) {
super(ActivationRule.MOBS, settings);
}
}

View File

@ -0,0 +1,87 @@
package modchest.block.custom.grid;
import java.util.Properties;
import javax.swing.text.html.BlockView;
import modchest.block.entity.gridEntity;
import modchest.grid.data.Sections;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
public class gridSlab extends SlabBlock implements gridSlotInfo, BlockEntityProvider {
public gridSlab(Settings settings) {
super(settings);
}
public static final int LOWER_SLOT = 0;
public static final int UPPER_SLOT = 1;
@Override
public Sections sections() {
return META.GRID_SLAB_SECTIONS;
}
@Override
public int getRelativeSlotAt(final Vec3d posInBlock, final Direction side) {
switch (side) {
case UP:
return posInBlock.y == 0.5 ? LOWER_SLOT : UPPER_SLOT;
case DOWN:
return posInBlock.y == 0.5 ? UPPER_SLOT : LOWER_SLOT;
default:
return posInBlock.y < 0.5 ? LOWER_SLOT : UPPER_SLOT;
}
}
@Override
public boolean absoluteSlotIsValid(final gridEntity grid, final BlockState state, final int slot) {
final int wantedSlot;
switch (state.get(Properties.SLAB_TYPE)) {
case DOUBLE:
return true;
case TOP:
wantedSlot = UPPER_SLOT;
break;
case BOTTOM:
wantedSlot = LOWER_SLOT;
break;
default:
throw new IllegalStateException("unreachable");
}
switch (grid.sections().findSectionIndexOf(slot)) {
case Sections.BASE_INDEX:
return grid.sections().base().makeAbsolute(slot) == wantedSlot;
case Sections.OVERLAY_INDEX:
return grid.sections().overlay().makeAbsolute(slot) == wantedSlot;
case Sections.SPECIAL_INDEX:
return true;
default:
throw new IllegalArgumentException("Invalid slot for grid slab:" + slot);
}
}
@SuppressWarnings("deprecation")
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom);
}
@Override
public BlockEntity createBlockEntity(final BlockView world) {
return new gridEntity(BLOCK_ENTITY_TYPES.GRID_SLAB, META.GRID_SLAB_SECTIONS);
}
@Override
public BlockEntity createBlockEntity(BlockPos arg0, BlockState arg1) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'createBlockEntity'");
}
}

View File

@ -0,0 +1,13 @@
package modchest.block.custom.grid;
import modchest.block.entity.gridEntity;
import modchest.grid.data.Sections;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
public interface gridSlotInfo {
Sections sections();
int getRelativeSlotAt(Vec3d posInBlock, Direction side);
boolean absoluteSlotIsValid(gridEntity entity, BlockState state, int slot);
}

View File

@ -0,0 +1,12 @@
package modchest.block.custom.grid;
import net.minecraft.block.BlockState;
import net.minecraft.block.StairsBlock;
public class gridStairs extends StairsBlock{
public gridStairs(BlockState baseBlockState, Settings settings) {
super(baseBlockState, settings);
}
}

View File

@ -0,0 +1,13 @@
package modchest.block.custom.grid;
import net.minecraft.block.TorchBlock;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleTypes;
public class gridTorch extends TorchBlock{
public gridTorch(Settings settings, ParticleEffect particle) {
super(settings, ParticleTypes.FLAME);
}
}

View File

@ -0,0 +1,11 @@
package modchest.block.custom.grid;
import net.minecraft.block.TrapdoorBlock;
public class gridTrapdoor extends TrapdoorBlock{
public gridTrapdoor(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,11 @@
package modchest.block.custom.grid;
import net.minecraft.block.WallBlock;
public class gridWall extends WallBlock{
public gridWall(Settings settings) {
super(settings);
}
}

View File

@ -0,0 +1,13 @@
package modchest.block.custom.grid;
import net.minecraft.block.WallTorchBlock;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleTypes;
public class gridWallTorch extends WallTorchBlock {
public gridWallTorch(Settings settings, ParticleEffect particleEffect) {
super(settings, ParticleTypes.FLAME);
}
}

View File

@ -1,50 +0,0 @@
package modchest.block.custom;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.block.Block;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.PacketByteBuf;
public class gridBlock extends Block {
public static final String ServerPlayNetworking = null;
public gridBlock(Settings settings) {
super(settings);
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.MODEL;
}
@SuppressWarnings("deprecation")
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom);
}
public static PacketByteBuf writeBuffer(BlockHitResult hitResult) {
BlockPos gridBlockPos = hitResult.getBlockPos();
int[] gridPos = new int[3];
gridPos[0] = gridBlockPos.getX();
gridPos[1] = gridBlockPos.getY();
gridPos[2] = gridBlockPos.getZ();
NbtCompound Nbtgrid = new NbtCompound();
Nbtgrid.putIntArray("BlockPosition", gridPos);
PacketByteBuf gridBlockBuffer = PacketByteBufs.create();
gridBlockBuffer.writeNbt(Nbtgrid);
// gridBlockBuffer.writeBlockHitResult(hitResult);
// gridBlockBuffer.writeBlockPos(gridBlockPos);
return gridBlockBuffer;
}
}

View File

@ -0,0 +1,370 @@
package modchest.block.entity;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.swing.text.html.Option;
import org.spongepowered.asm.mixin.transformer.ClassInfo.FrameData;
import com.ibm.icu.impl.Pair;
import modchest.item.modItems;
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.LockableContainerBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.PropertyDelegate;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerContext;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableTextContent;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
public class gridEntity extends LockableContainerBlockEntity implements ExtendedScreenHandlerFactory, RenderAttachedBlockEntity, BlockEntityClientSerializable {
private gridData data;
//private final DefaultedList<ItemStack> inventory = DefaultedList.ofSize(1, ItemStack.EMPTY);
//protected final PropertyDelegate propertyDelegate; // synchronisieren zwischen client und server
//private int progress = 0;
//private int maxProgress = 72;
public gridEntity(final BlockEntityType type, final Sections sections) {
super type;
data = new gridData(sections);
}
public gridData data() {
return data;
}
public Sections sections() {
return data.sections();
}
public Optional<ItemStack>[] items() {
return data.items();
}
public List<Optional<ItemStack>> baseItems() {
return data.baseItems();
}
public List<Optional<ItemStack>> overlayItems() {
return data.overlayItems();
}
public List<Optional<ItemStack>> specialItems() {
return data.specialItems();
}
public Optional<BlockState>[] baseStates() {
return data.baseStates();
}
public void copyFrom(final int slot, final ItemStack stack, final int count, final boolean take) {
final ItemStack newStack = stack.copy();
final int realCount = Math.min(count, stack.getCount());
newStack.setCount(realCount);
if (take) {
stack.setCount(stack.getCount() - realCount);
}
this.setStack(slot, newStack);
}
@Override
public int getMaxCountPerStack() {
return 1;
}
@Override
public boolean isValid(final int slot, final ItemStack stack) {
switch (sections().findSectionIndexOf(slot)) {
case Sections.BASE_INDEX: return checkIf(stack).isValidForBase(s -> Optional.of(s.getBlock().getDefaultState()), world, pos).isPresent();
case Sections.OVERLAY_INDEX: return checkIf(stack).isValidForOverlay();
case Sections.SPECIAL_INDEX: return checkIf(stack).isValidForSpecial();
default: return false;
}
}
private void beforeRemove(final int slot) {
switch (sections().findSectionIndexOf(slot)) {
case Sections.BASE_INDEX: baseStates()[sections().base().makeRelative(slot)] = Optional.empty();
break;
case Sections.OVERLAY_INDEX:
break;
case Sections.SPECIAL_INDEX:
SPECIAL_ITEMS.Map.get(getItemBeforeEmpty(getStack(slot))).onRemove(world, this);
break;
default:
throw new IllegalArgumentException("Invalid slot:" + slot);
}
}
@Override
public ItemStack removeStack(final int slot, final int amount) {
beforeRemove(slot);
return Optional.of(slot).filter(s -> sections().itemIndices().contains(s)).filter(s -> amount > 0).flatMap(s -> items()[s])
.map(orig -> new Pair<>(orig, orig.split(amount))).map(pair -> {
markDirty();
if (pair.getFirst().isEmpty()) {
items() [slot] = Optional.empty();
}
return pair.getSecond();
}).orElse(ItemStack.EMPTY);
}
@Override
public ItemStack removeStack(int slot) {
beforeRemove(slot);
markDirty();
final Optional<ItemStack> result = items()[slot];
items()[slot] = Optional.empty();
return result.orElse(ItemStack.EMPTY);
}
@Override
public ItemStack getStack(int slot) {
return items()[slot].orElse(ItemStack.EMPTY);
}
@Override
public int size() {
return items().length;
}
@Override
public boolean isEmpty() {
return Arrays.stream(items()).noneMatch(Optional::isPresent);
}
@Override
public boolean canPlayerUse(PlayerEntity player) {
return true;
}
@Override
public void clear() {
for (int i = 0; size = size(); i < size; i++) {
items()[i] = Optional.empty();
}
}
@Override
public void setStack(int slot, ItemStack stack) {
final int sectionIndex = sections().findSectionIndexOf(slot);
final Runnable setStack = () -> {
items()[slot] = Optional.of(stack);
stack.setCount(Math.min(stack.getCount(), getMaxCountPerStack()));
markDirty();
};
switch (sectionIndex) {
case Sections.BASE_INDEX: setStack.run();
final int baseSlot = sections().base().makeRelative(slot);
baseStates()[baseSlot] = baseItems().get(baseSlot).map(ItemStack::getItem).filter(i -> i instanceof BlockItem).map(i -> ((BlockItem) i).getBlock().getDefaultState());
break;
case Sections.SPECIAL_INDEX:
final SpecialItems.SpecialItem old = SPECIAL_ITEMS.Map.get(getItemBeforeEmpty(getStack(slot)));
if (old != null && world != null) {
old.onRemove(world, this);
}
setStack.run();
final SpecialItems.SpecialItems _new = SPECIAL_ITEMS.Map.get(getStack(slot).getItem());
if (_new != null && world != null) {
_new.onAdd(world,this);
}
break;
default: setStack.run();;
break;
}
}
@Override
public void markDirty() {
super.markDirty();
final World world = this.world;
if (world != null) {
final BlockState state = world.getBlockState(pos);
final Block block = state.getBlock();
if (world.isClient) {
MinecraftClient.getInstance().worldRenderer.updateBlock(world, pos, getCachedState(), state, 1);
} else {
sync();
PlayerLookup.tracking(this).forEach(p -> p.networkHandler.sendPacket(this.toUpdatePacket()));
world.updateNeighborsAlways(pos.offset(Direction.UP), block);
}
}
}
@Override
public List<Pair<Optional<BlockState>, Optional<Identifier>>> getRenderAttachmentData() {
return data.toRenderAttachment();
}
@Override
public CompoundTag toTag(final CompoundTag tag) {
toClientTag(tag);
return super.toTag(tag);
}
@Override
public void fromTag(BlockState state, CompoundTag tag) {
fromClientTag(tag);
super.fromTag(state, tag);
}
@Override
public CompoundTag toClientTag(CompoundTag tag) {
tag.put("gridData", data.toTag());
return tag;
}
@Override
public CompoundTag fromClientTag (final CompoundTag tag) {
data = gridData.fromTag(compoundTag.getCompound("gridData"));
this.markDirty();
}
@Override
protected ScreenHandler createScreenHandler(final int syncId, final PlayerInventory playerInventory) {
return new gridGuiDescription(syncId, playerInventory, ScreenHandlerContext.create(world, pos));
}
@Override
public void writeScreenopeningData(final ServerPlayerEntity serverPlayerEntity, final PacketByteBuf packetByteBuf) {
packetByteBuf.writeBlockPos(pos);
}
@Override
protected Text getContainerName() {
return new TranslatableText(getCachedState().getBlock().getTranslationKey());
}
/*@Override
public DefaultedList<ItemStack> getItems() {
return this.inventory;
}
@Override
public Text getDisplayName() {
return Text.literal("gridBlock");
}
@Override
protected void writeNbt(NbtCompound nbt) {
Inventories.writeNbt(nbt, inventory);
super.writeNbt(nbt);
nbt.putInt("grid_block_entity_progress", progress);
}
@Override
public void readNbt(NbtCompound nbt) {
Inventories.readNbt(nbt, inventory);
progress = nbt.getInt("grid_block_entity_progress");
super.readNbt(nbt);
}
public static void tick(World world, BlockPos pos, BlockState state, gridBlockEntity entity) {
if (world.isClient()) {
return;
}
if(hasRecipe(entity)) {
entity.progress++;
markDirty(world, pos, state); //reloads blockPosition/chunk -> synchronize server and client
if (entity.progress >= entity.maxProgress) {
craftItem(entity);
}
} else {
entity.resetProgress();
markDirty(world, pos, state);
}
}
private void resetProgress() {
this.progress = 0;
}
private static void craftItem(gridBlockEntity entity) {
SimpleInventory inventory = new SimpleInventory(entity.size());
for (int i = 0; i < entity.size(); i++) {
inventory.setStack(i, entity.getStack(i));
}
if (hasRecipe(entity)) {
entity.removeStack(1,1);
entity.setStack(2, new ItemStack(modItems.pirates_coin, entity.getStack(2).getCount() + 1));
}
}
private static boolean hasRecipe(gridBlockEntity entity) {
SimpleInventory inventory = new SimpleInventory(entity.size());
for (int i = 0; i< entity.size(); i++) {
inventory.setStack(i, entity.getStack(i));
}
boolean hasRawGemInFirstSlot = entity.getStack(1).getItem() == modItems.pirates_coin;
return hasRawGemInFirstSlot && canInsertAmountIntoOutputSlot(inventory, 1) && canInsertItemIntoOutputSlot(inventory, modItems.pirates_coin);
}
private static boolean canInsertItemIntoOutputSlot(SimpleInventory inventory, Item output) {
return inventory.getStack(2).getItem() == output || inventory.getStack(2).isEmpty();
}
private static boolean canInsertAmountIntoOutputSlot(SimpleInventory inventory, int count) {
return inventory.getStack(2).getMaxCount() > inventory.getStack(2).getCount() + count;
}
@Override
public ScreenHandler createMenu(int arg0, PlayerInventory arg1, PlayerEntity arg2) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'createMenu'");
}
public ItemStack getRenderStack() {
if (this.getStack(2).isEmpty()) {
return this.getStack(1);
} else {
return this.getStack(2);
}
}*/
}

View File

@ -10,10 +10,16 @@ import net.minecraft.util.registry.Registry;
//rendert letztendlich die Interaktionsmenüs der Blöcke //rendert letztendlich die Interaktionsmenüs der Blöcke
public class modBlockEntities { public class modBlockEntities {
public static BlockEntityType<steeringWheelEntity> steering_wheel_interface; // Interaktionsmenü wird erstellt public static BlockEntityType<steeringWheelEntity> steering_wheel_interface; // Interaktionsmenü wird erstellt
// public static BlockEntityType<gridBlockEntity> grid_block_entity;
public static void registerBlockEntities() { public static void registerBlockEntities() {
steering_wheel_interface = Registry.register(Registry.BLOCK_ENTITY_TYPE, steering_wheel_interface = Registry.register(Registry.BLOCK_ENTITY_TYPE,
new Identifier(REServerMod.MOD_ID, "steering_wheel_interface"), // Interkationsmenü wird gerendert new Identifier(REServerMod.MOD_ID, "steering_wheel_interface"), // Interkationsmenü wird gerendert
FabricBlockEntityTypeBuilder.create(steeringWheelEntity::new, modBlocks.steering_wheel).build(null)); FabricBlockEntityTypeBuilder.create(steeringWheelEntity::new, modBlocks.steering_wheel).build(null));
/*grid_block_entity = Registry.register(Registry.BLOCK_ENTITY_TYPE,
new Identifier(REServerMod.MOD_ID, "grid_block_entity"),
FabricBlockEntityTypeBuilder.create(gridBlockEntity::new, modBlocks.grid_block).build(null));*/
} }
} }

View File

@ -1,7 +1,7 @@
package modchest.block; package modchest.block;
import modchest.block.custom.gridBlock;
import modchest.block.custom.steeringWheelBlock; import modchest.block.custom.steeringWheelBlock;
import modchest.block.custom.grid.gridBlock;
import modchest.item.modItemGroup; import modchest.item.modItemGroup;
import modchest.REServerMod; import modchest.REServerMod;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings; import net.fabricmc.fabric.api.item.v1.FabricItemSettings;

View File

@ -0,0 +1,77 @@
package modchest.data;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import org.spongepowered.include.com.google.gson.Gson;
import org.spongepowered.include.com.google.gson.JsonParseException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profiler;
public class OverlayDataListener implements SimpleResourceReloadListener<Collection<Identifier>> {
private final Map<Ingredient, Identifier> triggers = new HashMap<>();
public Optional<Identifier> getOverlayId(final ItemStack stack) {
return triggers.entrySet().stream().filter(e -> e.getKey().test(stack)).map(Map.Entry::getValue).findFirst();
}
public boolean hasOverlay(final ItemStack stack) {
return getOverlayId(stack).isPresent();
}
@Override
public CompletableFuture<Collection<Identifier>> load(final ResourceManager manager, final Profiler profiler,
final Executor executor) {
return CompletableFuture.supplyAsync(() -> {
triggers.clear();
return ResourceManager.findResources("grid/overlays", s -> s.endsWith(".json"));
}, executor);
}
@Override
public CompletableFuture<Void> apply(final Collection<Identifier> data, final ResourceManager manager, final Profiler profiler,
final Executor executor) {
return CompletableFuture.runAsync(() -> {
for (final Identifier id : identifiers) {
try {
final JsonElement element = new Gson().fromJson(new BufferedReader(new InputStreamReader(resourceManager.getResource(id).getInputStream())), JsonElement.class);
if (!element.isJsonObject()) {
throw new JsonParseException("Invalid JSON: expected an object.");
}
final JsonObject obj = element.getAsJsonObject();
if (!obj.has("trigger")) {
throw new JsonParseException("Invalid JSON: expected the key 'triger'.");
}
triggers.put(Ingredient.fromJson(.get("trigger")), id);
} catch (final Exception e) {
META.LOGGER.warn("Exception while parsing overlay:" + e);
}
}
}, executor);
}
private final Identifier id = META.id("data/overlay");
@Override
public Identifier getFabricId() {
return id;
}
}

View File

@ -1,10 +1,9 @@
package modchest.event; /*package modchest.event;
import static net.minecraft.block.Block.getBlockFromItem; import static net.minecraft.block.Block.getBlockFromItem;
import modchest.block.custom.gridBlock; import modchest.block.custom.gridBlock;
import modchest.networking.modNetworkingServer; import modchest.networking.modNetworkingServer;
import modchest.networking.packet.gridBlockS2CPacket;
import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -12,11 +11,13 @@ import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World; import net.minecraft.world.World;
public class useBlockCallback implements UseBlockCallback { public class useBlockCallback implements UseBlockCallback {
@ -26,7 +27,7 @@ public class useBlockCallback implements UseBlockCallback {
Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem()); Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem());
BlockState StateInHand = BlockInHand.getDefaultState(); BlockState StateInHand = BlockInHand.getDefaultState();
BlockPos gridBlockPos = hitResult.getBlockPos(); BlockPos gridBlockPos = hitResult.getBlockPos();
//MinecraftServer server = player.getServer(); //funktioniert
// PlayerPublicKey playerPublicKey = player.getPublicKey(); // PlayerPublicKey playerPublicKey = player.getPublicKey();
if (world.getBlockState(hitResult.getBlockPos()).getBlock().toString().equals("Block{modchest:grid_block}") if (world.getBlockState(hitResult.getBlockPos()).getBlock().toString().equals("Block{modchest:grid_block}")
&& player.isSpectator() == false) { && player.isSpectator() == false) {
@ -34,17 +35,18 @@ public class useBlockCallback implements UseBlockCallback {
return ActionResult.PASS; return ActionResult.PASS;
} else { } else {
player.sendMessage(Text.of("gridBlock benutzt")); player.sendMessage(Text.of("gridBlock benutzt"));
world.setBlockState(gridBlockPos, StateInHand); // tauscht die Textur des "benutzten" gridBlocks mit der //world.setBlockState(gridBlockPos, StateInHand); // tauscht den "benutzten" gridBlock mit dem
// des Blocks in der Hand // Blocks in der Hand, wie platzieren, nur cooler
player.getMainHandStack().decrement(1); player.getMainHandStack().decrement(1);
player.jump(); player.jump();
// player.onLanding(player.playSoundIfNotSilent()); // player.onLanding(player.playSoundIfNotSilent());
if (player instanceof ServerPlayerEntity) { // nötig, um sicherzustellen, dass eine ServerPlayerEntity if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { // nötig, um sicherzustellen, dass eine ServerPlayerEntity
// fürs networking übergeben wird und nicht eine // fürs networking übergeben wird und nicht eine
// PlayerEntity, da sonst Absturz // PlayerEntity, da sonst Absturz; gleiches für ServerWorld
ServerWorld serverWorld = (ServerWorld) world;
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
ServerPlayNetworking.send(serverPlayer, modNetworkingServer.grid_block_networking, ServerPlayNetworking.send(serverPlayer, modNetworkingServer.grid_block_networking,
gridBlock.writeBuffer(hitResult)); gridBlock.writeBuffer(hitResult, serverWorld));
} }
} }
} else { } else {
@ -52,4 +54,4 @@ public class useBlockCallback implements UseBlockCallback {
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} }
} }*/

View File

@ -0,0 +1,62 @@
/*package modchest.event;
import static net.minecraft.block.Block.getBlockFromItem;
import org.jetbrains.annotations.Nullable;
import modchest.block.custom.grid.gridBlock;
import modchest.networking.modNetworkingServer;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class useEntityCallback implements UseEntityCallback {
@Override
public ActionResult interact(PlayerEntity player, World world, Hand hand, Entity entity,
@Nullable EntityHitResult hitResult) {
Block BlockInHand = getBlockFromItem(player.getMainHandStack().getItem());
BlockState StateInHand = BlockInHand.getDefaultState();
Vec3d gridBlockPos = hitResult.getPos();
if (hitResult.getEntity().toString().equals("Block{modchest:grid_block_entity}")
&& player.isSpectator() == false) {
if (BlockInHand instanceof gridBlock) {
return ActionResult.PASS;
} else {
player.sendMessage(Text.of("gridBlock benutzt"));
// world.setBlockState(gridBlockPos, StateInHand); // tauscht den "benutzten"
// gridBlock mit dem
// Blocks in der Hand, wie platzieren, nur cooler
player.getMainHandStack().decrement(1);
player.jump();
// player.onLanding(player.playSoundIfNotSilent());
if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { // nötig, um
// sicherzustellen, dass
// eine ServerPlayerEntity
// fürs networking übergeben wird und nicht eine
// PlayerEntity, da sonst Absturz; gleiches für ServerWorld
ServerWorld serverWorld = (ServerWorld) world;
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
/*ServerPlayNetworking.send(serverPlayer, modNetworkingServer.grid_block_networking,
grid.writeEntityBuffer(hitResult, serverWorld));
}
}
} else {
return ActionResult.PASS;
}
return ActionResult.SUCCESS;
}
}
*/

View File

@ -0,0 +1,16 @@
package modchest.grid;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public class Registrar<T> {
private final Registry<T> target;
protected Registrar(final Registry<T> target) {
this.target = target;
}
protected <U extends T> U register(final U value, final Identifier id) {
return Registry.register(target, id, value);
}
}

View File

@ -0,0 +1,110 @@
package modchest.grid.data;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.IntStream;
import org.spongepowered.asm.util.perf.Profiler.Section;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
public class Sections {
public static final int BASE_INDEX = 0;
public static final int OVERLAY_INDEX = 1;
public static final int SPECIAL_INDEX = 2;
public static Sections fromTag(ListTag tag) {
return new Sections(makesections(tag.stream().mapToInt(t -> ((IntTag) t).getInt())));
}
private static Section[] makSections(final IntStream sizes) {
int start = 0;
final int[] sizeArr = sizes.toArray();
final Section[] sections = new Section[sizeArr.length];
for (int i = 0, sizeArrLength = sizeArr.length; i < sizeArrLength; i++) {
final int size = sizeArr[i];
sections[i] = Section.exclusive(start, start + size);
start += size;
}
return sections;
}
private final Section[] sections;
public Sections(final Section[] sections) {
this.sections = sections;
}
public Sections(final int partCount, final int... otherSizes) {
this(makSections(IntStream.concat(IntStream.of(partCount, partCount, SPECIAL_ITEMS.Map.size()), Arrays.stream(otherSizes))));
}
public Section get(final int index) {
return sections[index];
}
public Section base() {
return get(BASE_INDEX);
}
public Section overlay() {
return get(OVERLAY_INDEX);
}
public Section special() {
return get(SPECIAL_INDEX);
}
public Section itemIndices() {
return Section.exclusive(0, sections[sections.length -1].end());
}
public boolean containsSlot(final int slot) {
return 0 <= slot && slot < sections[sections.length -1].end();
}
public int findSectionIndexOf(final int absoluteIndex) {
for (int i = 0; i < sections.length; i++) {
if (absoluteIndex < sections[i].end()) {
return i;
}
}
return -1;
}
public Optional<ItemStack>[] makeItems() {
final Optional<ItemStack>[] items = new Optional[sections[sections.length -1].end()];
Arrays.fill(items, Optional.empty());
return items;
}
public Optional<BlockState>[] makeBaseStates() {
final Optional<BlockState>[] baseStates = new Optional[base().size()];
Arrays.fill(baseStates, Optional.empty());
return baseStates;
}
public ListTag toTag() {
final ListTag tag = new ListTag();
for (final Section section : sections) {
tag.add(IntTag.of(section.size()));
}
return tag;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Sections sections1 = (Sections) o;
return Arrays.equals(sections, sections1.sections);
}
@Override
public int hashCode() {
return Arrays.hashCode(sections);
}
}

View File

@ -0,0 +1,129 @@
package modchest.grid.data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.swing.text.html.Option;
import org.jetbrains.annotations.NotNull;
import com.google.common.collect.Streams;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtOps;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
public class gridData {
private static Optional<ItemStack>[] itemsFromTag(final Sections sections, final ListTag tag) {
final Optional<ItemStack>[] items = sections.makeItems();
for (int i = 0, size = tag.size(); i< size; i++) {
final CompoundTag stackTag = tag.getCompound(i);
final int slot = stackTag.getByte("Slot") & 255;
if (sections.containsSlot(slot)) {
items[slot] = Optional.of(ItemStack.fromTag(stackTag));
}
}
return items;
}
private static optional<BlockState>[] baseStatesFromTag(final Sections sections, final ListTag tag) {
final Optional<BlockState>[] baseStates = sections.makeBaseStates();
for (int i = 0, size = tag.size(); i < size; i++) {
final CompoundTag stateTag = tag.getCompound(i);
final int realIndex = stateTag.getInt("i");
baseStates[realIndex] = BlockState.CODEC.decode(new Dynamic<>(NbtOps.INSTANCE, stateTag)).result().map(Pair::getFirst);
}
return baseStates;
}
public static gridData fromTag(final CompoundTag tag) {
final Sections sections = Sections.fromTag(tag.getList("format", 3));
return new gridData(sections, itemsFromTag(sections, tag.getList("Items", 10)), baseStatesFromTag(sections, tag.getList("states", 10)));
}
private final Sections sections;
private final Optional<ItemStack>[] items;
private final Optional<BlockState>[] baseStates;
public gridData(final Sections sections, final Optional<ItemStack>[] items, final Optional<BlockState>[] baseStates) {
this.sections = sections;
this.items = items;
this.baseStates = baseStates;
}
public gridData(@NotNull final Sections sections) {
this(sections, sections.makeItems(), sections.makeBaseStates());
}
public Sections sections() {
return sections;
}
public Optional<ItemStack>[] items() {
return items;
}
public List<Optional<ItemStack>> baseItems() {
return Arrays.asList(items).subList(sections.base().start(), sections.base().end());
}
public List<Optional<ItemStack>> overlayItems() {
return Arrays.asList(items).subList(sections.overlay().start(), sections.overlay().end());
}
public List<Optional<ItemStack>> specialItems() {
return Arrays.asList(items).subList(sections.special().start(), sections.special().end());
}
public Optional<BlockState>[] baseStates() {
return baseStates;
}
public CompoundTag toTag() {
final CompoundTag tag = new CompoundTag();
tag.put("format", sections.toTag());
final ListTag itemsTag = new ListTag();
for (int i = 0, size = items.length; i < size; i++) {
final int i2 = i;
items[i].ifPresent(stack -> {
final CompoundTag stackTag = new CompoundTag();
stack.toTag(stackTag);
stackTag.putByte("Slot", (byte)i2);
itemsTag.add(stackTag);
});
}
if (!itemsTag.isEmpty()) {
tag.put("Items", itemsTag);
}
final ListTag baseStatesTag = new ListTag();
for (int i = 0, size = baseStates.length; i < size; i++) {
final int i2 = i;
baseStates[i].ifPresent(baseState -> {
final CompoundTag baseStateTag = new CompoundTag();
baseStateTag.putInt("i", i2);
baseStateTag.add(
BlockState.CODEC.encode(baseState, NbtOps.INSTANCE, baseStateTag).get().left().get()
);
});
}
if (!baseStatesTag.isEmpty()) {
tag.put("states", baseStatesTag);
}
return tag;
}
public List<Pair<Optional<BlockState>, Optional<Identifier>>> toRenderAttachment() {
return Streams.zip(Arrays.stream(baseStates), overlayItems().stream().map(i -> i.flatMap(OVERLAYS::getOverlayId)), Pair::new).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,18 @@
/*package modchest.grid;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.Direction;
public class gridBlock extends Block{
public gridBlock(Settings settings) {
super(settings);
}
@SuppressWarnings("deprecation")
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction) || (state == stateFrom);
}
}*/

View File

@ -0,0 +1,36 @@
package modchest.grid;
import modchest.block.entity.gridEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.registry.Registry;
public class gridBlockEntityTypes extends Registrar<BlockEntityType<?>> {
public gridBlockEntityTypes() {
super(Registry.BLOCK_ENTITY_TYPE);
}
public final BlockEntityType<gridEntity> GRID = register(
BlockEntityType.Builder.create(
() -> new gridEntity(this.GRID, META.GRID_SECTIONS),
BLOCKS.GRID_BLOCK,
BLOCK.GRID_STAIRS,
BLOCK.GRID_FENCE,
BLOCK.GRID_FENCE_GATE,
BLOCKS.GRID_TRAPDOOR,
BLOCKS.GRID_DOOR,
BLOCKS.GRID_PATH,
BLOCKS.GRID_TORCH,
BLOCKS.GRID_WALL_TORCH,
BLOCKS.GRID_PRESSURE_PLATE,
BLOCKS.GRID_WALL,
BLOCKS.GRID_LAYER,
BLOCKS.GRID_CARPET,
BLOCKS.GRID_PANE).build(null),
META.id("frame"));
public final BlockEntityType<gridEntity> GRID_SLAB = register(
BlockEntityType.Builder.create(
() -> new gridEntity(this.GRID_SLAB, META.GRID_SLAB_SECTIONS),
BLOCKS.GRID_SLAB).build(null),
META.id("grid_slab"));
}

View File

@ -0,0 +1,93 @@
package modchest.grid;
import java.util.Properties;
import java.util.function.Function;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
import modchest.block.custom.grid.gridDoor;
import modchest.block.custom.grid.gridFence;
import modchest.block.custom.grid.gridFenceGate;
import modchest.block.custom.grid.gridLayer;
import modchest.block.custom.grid.gridPane;
import modchest.block.custom.grid.gridPath;
import modchest.block.custom.grid.gridPressurePlate;
import modchest.block.custom.grid.gridSlab;
import modchest.block.custom.grid.gridStairs;
import modchest.block.custom.grid.gridTorch;
import modchest.block.custom.grid.gridTrapdoor;
import modchest.block.custom.grid.gridWall;
import modchest.block.custom.grid.gridWallTorch;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Material;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.state.property.Property;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public class gridBlocks extends Registrar<Block> {
public final gridBlock GRID_BLOCK;
public final gridSlab GRID_SLAB;
public final gridStairs GRID_STAIRS;
public final gridFence GRID_FENCE;
public final gridFenceGate GRID_FENCE_GATE;
public final gridTrapdoor GRID_TRAPDOOR;
public final gridDoor GRID_DOOR;
public final gridPath GRID_PATH;
public final gridTorch GRID_TORCH;
public final gridWallTorch GRID_WALL_TORCH;
public final gridPressurePlate GRID_PRESSURE_PLATE;
public final gridWall GRID_WALL;
public final gridLayer GRID_LAYER;
public final gridCarpet GRID_CARPET;
public final gridPane GRID_PANE;
private <A extends Block> A registerWithItem(final A block, final Identifier id, final Item.Settings settings) {
Registry.register(Registry.ITEM, id, new BlockItem(block, settings));
return register(block, id);
}
public gridBlocks() {
super(Registry.BLOCK);
final Function<Material, AbstractBlock.Settings> makeSettings = material -> FabricBlockSettings
.of(material)
.hardness(0.33f)
.sounds(BlockSoundGroup.WOOD)
.nonOpaque()
.solidBlock((a, b, c) -> false)
.luminance(state -> Boolean.TRUE.equals(state.get(Properties.LIT)) ? 15 : 0);
final AbstractBlock.Settings gridSettings = makeSettings.apply(Material.WOOD);
final AbstractBlock.Settings gridTorchSettings = makeSettings.apply(Material.SUPPORTED).noCollision()
.breakInstantly()
.luminance(state -> Boolean.TRUE.equals(state.get(Properties.LIT)) ? 15 : 14);
final Item.Settings itemSettings = new Item.Settings().group(META.MAIN_ITEM_GROUP);
GRID_BLOCK = registerWithItem(new gridBlock(gridSettings), META.id("grid_block"), itemSettings);
GRID_SLAB = registerWithItem(new gridSlab(gridSettings), META.id("grid_slab"), itemSettings);
GRID_STAIRS = registerWithItem(new gridStairs(GRID_BLOCK.getDefaultState(), gridSettings),
META.id("grid_stairs"), itemSettings);
GRID_FENCE = registerWithItem(new gridFence(gridSettings), META.id("grid_fence"), itemSettings);
GRID_FENCE_GATE = registerWithItem(new gridFenceGate(gridSettings), META.id("grid_fence_gate"), itemSettings);
GRID_TRAPDOOR = registerWithItem(new gridTrapdoor(gridSettings.allowsSpawning((a, b, c, d) -> false)),
META.id("grid_trapdoor"), itemSettings);
GRID_DOOR = registerWithItem(new gridDoor(gridSettings), META.id("grid_door"), itemSettings);
GRID_PATH = registerWithItem(new gridPath(gridSettings), META.id("grid_path"), itemSettings);
GRID_PRESSURE_PLATE = registerWithItem(new gridPressurePlate(gridSettings), META.id("grid_pressure_plate"),
itemSettings);
GRID_WALL = registerWithItem(new gridWall(gridSettings), META.id("grid_wall"), itemSettings);
GRID_LAYER = registerWithItem(new gridLayer(gridSettings), META.id("grid_layer"), itemSettings);
GRID_CARPET = registerWithItem(new gridCarpet(gridSettings), META.id("grid_carpet"), itemSettings);
GRID_PANE = registerWithItem(new gridPane(gridSettings), META.id("grid_pane"), itemSettings);
GRID_TORCH = registerWithItem(new gridTorch(gridTorchSettings), META.id("grid_torch"));
GRID_WALL_TORCH = registerWithItem(new gridWallTorch(gridTorchSettings), META.id("grid_wall_torch"));
}
}

View File

@ -0,0 +1,20 @@
package modchest.grid;
import modchest.item.custom.Hammer;
import net.minecraft.item.Item;
import net.minecraft.item.WallStandingBlockItem;
import net.minecraft.util.registry.Registry;
public class gridItems extends Registrar<Item> {
public gridItems() {
super(Registry.ITEM);
}
public final Hammer HAMMER = register(new Hammer(new Item.Settings().maxCount(1).group(META.MAIN_ITEM_GROUP)), META.id("hammer"));
public final WallStandingBlockItem GRID_TORCH = register(
new WallStandingBlockItem(BLOCKS.GRID_TORCH, BLOCKS.GRID_WALL_TORCH, new Item.Settings().group(META.MAIN_ITEM_GROUP)),
META.id("grid_torch")
);
}

View File

@ -0,0 +1,37 @@
package modchest.grid;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import modchest.grid.data.Sections;
import modchest.gui.gridGuiDescription;
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandlerContext;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.Identifier;
public class gridMeta {
public final String NAMESPACE = "grid";
public Identifier id(final String path) {
return new Identifier(NAMESPACE, path);
}
public final Logger LOGGER = LogManager.getLogger("grid");
@SuppressWarnings("deprecation")
public final ScreenHandlerType<gridGuiDescription> GRID_SCREEN_HANDLER_TYPE = ScreenHandlerRegistry
.registerExtended(id("grid"),
(syncId, inventory, buf) -> new gridGuiDescription(syncId, inventory,
ScreenHandlerContext.create(inventory.player.world, buf.readBlockPos())));
public final Sections GRID_SECTIONS = new Sections(1);
public final Sections GRID_SLAB_SECTIONS = new Sections(2);
public final ItemGroup MAIN_ITEM_GROUP = FabricItemGroupBuilder.create(id("grid"))
.icon(() -> new ItemStack(ITEMS.HAMMER)).build();
}

View File

@ -0,0 +1,7 @@
package modchest.grid;
import net.minecraft.state.property.BooleanProperty;
public class gridProperties {
public final BooleanProperty HAS_REDSTONE = BooleanProperty.of("has_redstone");
}

View File

@ -0,0 +1,14 @@
package modchest.gui;
import net.minecraft.inventory.Inventory;
public class SingleItemSlots extends WItemSlot {
public SingleItemSlots(final Inventory inventory, final int startIndex, final int slotsWide, final int slotsHigh, final boolean big) {
super(inventory, startIndex, slotsWide, slotsHigh, big);
}
@Override
protected ValidatedSlot createSlotPeer(final Inventory inventory, final int index, final int x, final int y) {
return new ValidatedSingleItemSlot(inventory, index, x, y);
}
}

View File

@ -0,0 +1,20 @@
package modchest.gui;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
public class ValidatedSingleItemSlot extends ValidatedSlot {
public ValidatedSingleItemSlot(final Inventory inventory, final int index, final int x, final int y) {
super(inventory, index, x, y);
}
@Override
public int getMaxItemCount() {
return 1;
}
@Override
public int getMaxItemCount(final ItemStack stack) {
return 1;
}
}

View File

@ -0,0 +1,32 @@
package modchest.gui;
import modchest.block.entity.gridEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerContext;
public class gridGuiDescription extends SyncedGuiDescription {
public gridGuiDescription(final int syncId, final PlayerInventory playerInventory, final ScreenHandlerContext context) {
this (syncId, playerInventory, context, context.run((world, pos) -> (gridEntity) world.getBlockEntity(pos))
.orElseThrow(() -> new IllegalArgumentException("gridGuiDescription can only be used with gridEntity"))
);
}
private gridGuiDescription(final int syncId, final PlayerInventory playerInventory, final ScreenHandlerContext context, final gridEntity grid) {
super(META.GRID_SCREEN_HANDLER_TYPE, syncId, playerInventory, SyncedGuiDescription.getBlockInventory(context, frame.size()), SyncedGuiDescription.getBlockPropertyDelegate(context));
final WGridPanel root = new GridPanel(9);
root.add(centered(label("gui.framed.frame.base_label")), 1, 2, 8, 2);
root.add(
slotRow(SingleItemSlots::new, blockInventory, frame.sections().overlay()),
13 - gridBlock.sections().overlay().size(), 4 //gridBlock ersetzt in diesem Fall frame also nochmal TODO
);
root.add(centered(label("gui.framed.frame.special_label")), 0, 6, 18, 2);
SPECIAL_ITEMS.Map.forEach((item, specialItem) -> root.add(
new SingleItemSlots(blockInventory, grid.sections().special().makeAbsolute(specialItem.offset()), 1, 1, false),
9 - grid.sections().special().size() + specialItem.offset() *2, 8
));
root.add(createPlayerInventoryPanel(), 0, 11);
root.validate(this);
rootPanel = root;
}
}

View File

@ -0,0 +1,225 @@
package modchest.item.custom;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
import modchest.block.custom.grid.gridSlotInfo;
import modchest.block.entity.gridEntity;
import modchest.grid.data.gridData;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.text.TranslatableTextContent;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Pair;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class Hammer extends Item {
public Hammer(Settings settings) {
super(settings);
}
public enum CopyMode {
NONE(0, "none"), ANY(1, "any"), REQUIRE_ALL(2, "require_all");
public final int id;
public final String translationKey;
CopyMode(final int id, final String translationKey) {
this.translationKey = translationKey;
this.id = id;
}
public CopyMode next() {
return CopyMode.values()[(id + 1) % CopyMode.values().length];
}
public static final CopyMode DEFAULT = NONE;
public static Optional<CopyMode> fromString(final String string) {
return Arrays.stream(values()).filter(s -> s.translationKey.equals(string)).findFirst();
}
public static CopyMode fromStringOrDefault(final String string) {
return fromString(string).orElse(DEFAULT);
}
}
public static class Data {
public static Data fromTag(final CompoundTag tag) {
return new Data(
tag.contains("storedData") ? gridData.fromTag(tag.getCompound("storedData")) : null,
(tag.contains("mode") ? CopyMode.fromString(tag.getString("mode")) : Optional.<CopyMode>empty())
.orElse(CopyMode.DEFAULT));
}
private final @Nullable gridData storedData;
private final CopyMode mode;
public Data(@Nullable final gridData storedData, final CopyMode mode) {
this.storedData = storedData;
this.mode = mode;
}
public boolean applySettings(final gridSlotInfo slotInfo, final BlockState state, final gridEntity entity, final PlayerEntity player, final World world) {
final gridData storedData = this.storedData;
if (storedData == null) {
return false;
}
if (!storedData.sections().equals(grid.sections())) {
player.sendMessage(new TranslatableText("gui.framers_hammer.different_format"), true);
return false;
}
if (player.isCreative()) {
if (mode == CopyMode.NONE) {
return false;
}
if (!world.isClient) {
IntStream.range(0, storedData.items().length)
.boxed()
.map(i -> new Pair<>(storedData.items()[i], i))
.flatMap(pair -> pair.getFirst().map(itemStack -> Stream.of(new Pair<>(itemStack, pair.getSecond()))).orElseGet(Stream::empty))
.forEach(pair -> grid.setStack(pair.getSecond(), pair.getFirst().copy()));
}
} else {
final boolean requireAllItems;
switch (mode) {
case NONE:
return false;
case ANY:
requireAllItems = false;
break;
case REQUIRE_ALL:
requireAllItems = true;
break;
default:
throw new IllegalStateException("Unreachable.");
}
final Map<Item, Integer> itemSlotToGridSlot = IntStream.range(0, storedData.items().length).boxed()
.map(i -> new Pair<>(storedData.items()[i], i))
.flatMap(pair -> {
if (pair.getFirst().isPresent()) {
return Stream.of(pair.mapFirst(stack -> stack.get().getItem()));
} else {
return Stream.empty();
}
}).collect(Pair.toMap());
final Map<Integer, Integer> playerSlotToGridSlot = IntStream.range(0, player.getInventory().size()).boxed()
.map(i -> new Pair<>(Optional.of(player.getInventory().getStack(i)).filter(s -> !s.isEmpty()), i))
.flatMap(pair -> {
final Item item = maybeStack.get().getItem();
if (itemSlotToGridSlot.containsKey(item)) {
return Stream.of(new Pair<A,B>(pair.getSecond(), itemSlotToGridSlot.get(item)));
} else {
return Stream.empty();
} else {
return Stream.empty();
}
}).collect(Pair.toMap());
if (!world.isClient) {
for (final Map.Entry<Integer, Integer> entry : playerSlotToGridSlot.entrySet()) {
final int playerSlot = entry.getKey();
final int gridSlot = entry.getValue();
if (grid.getStack(gridSlot).getItem() != player.getInventory().getStack(playerSlot).getItem() && slotInfo.absoluteSlotIsValid(grid, state, gridSlot)) {
if (!grid.getStack(gridSlot).isEmpty()) {
player.getInventory().offerOrDrop(world, grid.removeStack(gridSlot));
}
grid.setStack(gridSlot, player.getInventory().removeStack(playerSlot, 1));
}
}
}
}
player.sendMessage(new TranslatableText("gui.framed.framers_hammer.apply_settings"), true);
return true;
}
}
private CompoundTag getTagOrAssignDefault (final ItemStack stack) {
if (stack.getTag() == null) {
final CompoundTag tag = new CompoundTag();
tag.putString("mode", CopyMode.DEFAULT.toString());
stack.setTag(tag);
}
return stack.getTag();
}
@Override
public ActionResult useOnBlock(final ItemUsageContext context) {
final CompoundTag tag = getTagOrAssignDefault(context.getStack());
final Data data = Data.fromTag(tag);
final BlockPos pos = context.getBlockPos();
final World world = context.getWorld();
final BlockState state = world.getBlockState(pos);
final Block block = state.getBlock();
if (!(block instanceof gridSlotInfo)) {
return super.useOnBlock(context);
}
final gridSlotInfo slotInfo = (gridSlotInfo) block;
final BlockEntity blockEntity = world.getBlockEntity(pos);
if (!(blockEntity instanceof gridEntity)) {
return super.useOnBlock(context);
}
final gridEntity grid = (gridEntity) blockEntity;
final PlayerEntity player = context.getPlayer();
if (player == null) {
return super.useOnBlock(context);
}
if (player.isSneaking()) {
player.sendMessage(new TranslatableText("gui.framers_hammer.copy_settings"), true);
tag.put("storedData", grid.data().toTag());
return ActionResult.SUCCESS;
} else {
if (data.applySettings(slotInfo, state, grid, player, world)) {
return ActionResult.SUCCESS;
} else {
return super.useOnBlock(context);
}
}
}
@Override
public TypedActionResult<ItemStack> use(final World world, final PlayerEntity user, final Hand hand) {
if (!user.isSneaking()) {
return super.use(world, user, hand);
}
final ItemStack stack = user.getStackInHand(hand);
final CompoundTag tag = getTagOrAssignDefault(stack);
final CopyMode mode = CopyMode.fromStringOrDefault(tag.getString("mode"));
final CopyMode newMode = mode.next();
tag.putString("mode", newMode.toString());
user.sendMessage(new TranslatableText("gui.framed.framers_hammer" + newMode.translationKey), true);
return TypedActionResult.success(stack);
}
}

View File

@ -0,0 +1,53 @@
package modchest.item.custom;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.IntStream;
import com.google.common.collect.Lists;
import com.google.common.collect.Streams;
import modchest.block.entity.gridEntity;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.Pair;
import net.minecraft.world.World;
public class SpecialItems {
public static class SpecialItem {
private final int offset;
private final BooleanProperty property;
public SpecialItem(final int offset, final BooleanProperty property) {
this.offset = offset;
this.property = property;
}
public int offset() {
return offset;
}
public void onAdd(final World world, final gridEntity grid) {
world.setBlockState(grid.getPos(), world.getBlockState(grid.getPos()).with(property, true));
}
public void onRemove(final World world, final gridEntity grid) {
world.setBlockState(grid.getPos(), world.getBlockState(frame.getPos()).with(property, false));
}
}
public final Map<Item, SpecialItem> MAP;
public SpecialItems() {
final List<Pair<Item, BooleanProperty>> pairs = Lists.newArrayList(
Pair.of(Items.GLOWSTONE_DUST, Properties.LIT), Pair.of(Items.REDSTONE, PROPERTIES.HAS_REDSTONE)
);
MAP = Streams.zip(IntStream.range(0, pairs.size()).boxed(), pairs.stream(), Pair::new)
.map(pair -> new Pair<>(pair.getSecond().getFirst(), new SpecialItem(pair.getFirst(), pair.getSecond().getSecond()))
).collect(Pair.toMap());
}
}

View File

@ -0,0 +1,63 @@
package modchest.mixin.local;
import org.spongepowered.asm.mixin.Mixin;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
import modchest.block.custom.grid.gridDoor;
import modchest.block.custom.grid.gridFence;
import modchest.block.custom.grid.gridFenceGate;
import modchest.block.custom.grid.gridLayer;
import modchest.block.custom.grid.gridPane;
import modchest.block.custom.grid.gridPath;
import modchest.block.custom.grid.gridPressurePlate;
import modchest.block.custom.grid.gridSlab;
import modchest.block.custom.grid.gridSlotInfo;
import modchest.block.custom.grid.gridStairs;
import modchest.block.custom.grid.gridTorch;
import modchest.block.custom.grid.gridTrapdoor;
import modchest.block.custom.grid.gridWall;
import modchest.block.custom.grid.gridWallTorch;
import modchest.block.entity.gridEntity;
import modchest.grid.data.Sections;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
@Mixin({
gridBlock.class,
gridSlab.class,
gridStairs.class,
gridFence.class,
gridFenceGate.class,
gridTrapdoor.class,
gridDoor.class,
gridPath.class,
gridTorch.class,
gridWallTorch.class,
gridPressurePlate.class,
gridWall.class,
gridLayer.class,
gridCarpet.class,
gridPane.class
})
public class SinglePartGridBlock implements gridSlotInfo {
private SinglePartGridBlock() {
throw new IllegalStateException("Mixin constructor should not run");
}
@Override
public Sections sections() {
return META.GRID_SECTIONS;
}
@Override
public int getRelativeSlotAt(final Vec3d posInBlock, final Direction side) {
return 0;
}
@Override
public boolean absoluteSlotIsValid(final gridEntity grid, final BlockState state, final int slot) {
return grid.sections().containsSlot(slot);
}
}

View File

@ -0,0 +1,330 @@
package modchest.mixin.local;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Supplier;
import javax.swing.text.html.BlockView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.NonnullDefault;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.datafixers.util.Function3;
import modchest.block.custom.grid.grid;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
import modchest.block.custom.grid.gridDoor;
import modchest.block.custom.grid.gridFence;
import modchest.block.custom.grid.gridFenceGate;
import modchest.block.custom.grid.gridLayer;
import modchest.block.custom.grid.gridPane;
import modchest.block.custom.grid.gridPath;
import modchest.block.custom.grid.gridPressurePlate;
import modchest.block.custom.grid.gridSlab;
import modchest.block.custom.grid.gridSlotInfo;
import modchest.block.custom.grid.gridStairs;
import modchest.block.custom.grid.gridTorch;
import modchest.block.custom.grid.gridTrapdoor;
import modchest.block.custom.grid.gridWall;
import modchest.block.custom.grid.gridWallTorch;
import modchest.block.entity.gridEntity;
import modchest.event.playerAfterRespawnEvent;
import modchest.item.custom.Hammer;
import modchest.item.custom.SpecialItems;
import modchest.item.custom.SpecialItems.SpecialItem;
import modchest.util.ValidQuery;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.StructureBlockBlockEntity.Action;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.state.StateManager;
import net.minecraft.state.StateManager.Builder;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.Unit;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@Mixin({
gridBlock.class,
gridSlab.class,
gridStairs.class,
gridFence.class,
gridFenceGate.class,
gridTrapdoor.class,
gridDoor.class,
gridPath.class,
gridTorch.class,
gridWallTorch.class,
gridPressurePlate.class,
gridWall.class,
gridLayer.class,
gridCarpet.class,
gridPane.class
})
public abstract class gridBehaviour extends Block implements BlockEntityProvider, grid, gridSlotInfo {
public gridBehaviour(Settings settings) {
super(settings);
throw new IllegalStateException("Mixin constructor should never run");
}
@Inject(method = "<init>*", at = @At("TAIL"))
void setGridPropertiesDefaultState(CallbackInfo ci) {
setDefaultState(getDefaultState().with(Properties.LIT, false).with(Properties.HAS_REDSTONE, false));
}
@Unique
@Nullable
private PlayerEntity breaker;
@Override
protected void appendProperties(final StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(Properties.LIT, Properties.HAS_REDSTONE);
}
@SuppressWarnings("deprecation")
@Override
public boolean emitsRedstonePower(final BlockState state) {
return super.emitsRedstonePower(state) || state.get(PROPERTIES.HAS_REDSTONE);
}
@SuppressWarnings("deprecation")
@Override
public int getWeakRedstonePower(BlockState state, net.minecraft.world.BlockView world, BlockPos pos,
Direction direction) {
if (state.get(PROPERTIES.HAS_REDSTONE)) {
return 15 - super.getWeakRedstonePower(state, world, pos, direction)
} else {
return super.getWeakRedstonePower(state, world, pos, direction);
}
}
@SuppressWarnings("deprecation")
@Override
public boolean onSyncedBlockEvent(BlockState state, World world, BlockPos pos, int type, int data) {
super.onSyncedBlockEvent(state, world, pos, type, data);
final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity == null) {
return false;
}
return blockEntity.onSyncedBlockEvent(type, data);
}
@SuppressWarnings("deprecation")
@Nullable
@Override
public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) {
return (NamedScreenHandlerFactory) world.getBlockEntity(pos);
}
private void removeStack(final World world, final gridEntity from, final PlayerEntity to, final int slot,
final boolean giveItem) {
final ItemStack stack = from.removeStack(slot);
if (!stack.isEmpty() && giveItem) {
to.getInventory().offerOrDrop(stack);
world.playSound(null, from.getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 0.2f,
(float) (Math.random() - Math.random()) * 1.4f + 2f);
}
}
private void onHammerRemoved(final World world, final gridEntity grid, final BlockState state,
final PlayerEntity player, final boolean giveItem) {
world.setBlockState(grid.getPos(), state);
if (player.isSneaking()) {
for (final int i : grid.sections().itemIndices()) {
removeStack(world, grid, player, i, giveItem);
}
} else {
int slot = -1;
for (int i = grid.size() - 1; i >= 0; i--) {
if (grid.items()[i].isPresent()) {
slot = i;
break;
}
}
if (slot != -1) {
removeStack(world, grid, player, slot, giveItem);
}
}
}
@SuppressWarnings("deprecation")
@Override
public void onStateReplaced(BlockState oldState, World world, BlockPos pos, BlockState newState, boolean moved) {
if (world.isClient || oldState.getBlock() == newState.getBlock()) {
return;
}
final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos);
final @Nullable PlayerEntity player = breaker;
if (player != null) {
if (player.getStackInHand(player.getActiveHand()).getItem() == ITEMS.GRID_HAMMER) {
onHammerRemoved(world, (gridEntity) blockEntity, oldState, player, false);
} else {
super.onStateReplaced(oldState, world, pos, newState, moved);
}
} else {
if (blockEntity instanceof Inventory) {
ItemScatterer.spawn(world, pos, (Inventory) blockEntity);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@SuppressWarnings("deprecation")
@Override
public void onBlockBreakStart(BlockState state, World world, BlockPos pos, PlayerEntity player) {
super.onBlockBreakStart(state, world, pos, player);
if (world.isClient) {
return;
}
if (player.getStackInHand(player.getActiveHand()).getItem() == ITEMS.GRID_HAMMER) {
final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof gridEntity) {
onHammerRemoved(world, (gridEntity) blockEntity, state, player, true);
}
}
}
@Override
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
super.onBreak(world, pos, state, player);
if (world.isClient || !player.isCreative()) {
return;
}
breaker = player;
}
@SuppressWarnings("deprecation")
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
final @Nullable BlockEntity blockEntity = world.getBlockEntity(pos);
if (!(blockEntity instanceof gridEntity)) {
return ActionResult.CONSUME;
}
final @NotNull gridEntity grid = (gridEntity) blockEntity;
final @Nullable ItemStack playerStack = player.getMainHandStack();
if (playerStack != null) {
final Vec3d posInBlock = hit.getPos().subtract(Vec3d.of(hit.getBlockPos()));
final int relativeSlot = getRelativeSlotAt(posInBlock, hit.getSide());
final Function3<List<Optional<ItemStack>>, Integer, Supplier<Unit>, ActionResult> swapItems = (slots,
absoluteSlot, onSuccess) -> {
final Optional<ItemStack> maybeStack = slots.get(relativeSlot);
if (playerStack.getItem() != maybeStack.orElse(ItemStack.EMPTY).getItem()) {
if (!world.isClient) {
if (!player.isCreative() && maybeStack.isPresent()) {
player.getInventory().offerOrDrop(maybeStack.get());
}
grid.copyFrom(absoluteSlot, playerStack, 1, !player.isCreative());
onSuccess.get();
}
return ActionResult.SUCCESS;
} else {
return ActionResult.CONSUME;
}
};
final ValidQuery.ItemStackValidQuery query = checkIf(playerStack);
if (query.isValidForOverlay()) {
final int absoluteSlot = grid.sections().overlay().makeAbsolute(relativeSlot);
return swapItems.apply(grid.overlayItems(), absoluteSlot, () -> Unit.INSTANCE);
}
final Optional<BlockState> maybeBaseState = query.isValidForBase(
i -> Optional.ofNullable(i.getBlock()
.getPlacementState(new ItemPlacementContext(new ItemUsageContext(player, hand, hit)))),
world, pos);
if (maybeBaseState.isPresent()) {
final int absoluteSlot = grid.sections().base().makeAbsolute(relativeSlot);
return swapItems.apply(grid.baseItems(), absoluteSlot, () -> {
grid.baseStates()[relativeSlot] = maybeBaseState;
return Unit.INSTANCE;
});
}
if (query.isValidForSpecial()) {
final SpecialItems.SpecialItem specialItem = SPECIAL_ITEM.Map.get(playerStack.getItem());
final int slot = grid.sections().special().makeAbsolute(specialItem.offset());
if (grid.getStack(slot).isEmpty()) {
if (!world.isClient) {
grid.copyFrom(slot, playerStack, 1, !player.isCreative());
specialItem.onAdd(world, grid);
}
return ActionResult.SUCCESS;
} else {
return ActionResult.CONSUME;
}
}
if (playerStack.isEmpty() && player.isSneaking()) {
player.openHandledScreen(state.createScreenHandlerFactory(world, pos));
return ActionResult.SUCCESS;
}
}
return super.onUse(state, world, pos, player, hand, hit);
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
final boolean tryCopy;
if (placer instanceof PlayerEntity) {
final PlayerEntity player = (PlayerEntity) placer;
if (player.getOffHandStack().getItem() != ITEMS.GRID_HAMMER || player.getOffHandStack().getTag() == null) {
tryCopy = false;
} else {
final BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof gridEntity) {
tryCopy = Hammer.Data.fromTag(player.getOffHandStack().getTag()).applySettings(this,
(gridEntity) blockEntity, player, world);
} else {
tryCopy = false;
}
}
} else {
tryCopy = false;
}
if (!tryCopy) {
super.onPlaced(world, pos, state, placer, itemStack);
}
}
}

View File

@ -0,0 +1,55 @@
package modchest.mixin.local;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import modchest.block.custom.grid.gridBlock;
import modchest.block.custom.grid.gridCarpet;
import modchest.block.custom.grid.gridDoor;
import modchest.block.custom.grid.gridFence;
import modchest.block.custom.grid.gridFenceGate;
import modchest.block.custom.grid.gridLayer;
import modchest.block.custom.grid.gridPane;
import modchest.block.custom.grid.gridPath;
import modchest.block.custom.grid.gridPressurePlate;
import modchest.block.custom.grid.gridSlab;
import modchest.block.custom.grid.gridStairs;
import modchest.block.custom.grid.gridTorch;
import modchest.block.custom.grid.gridTrapdoor;
import modchest.block.custom.grid.gridWall;
import modchest.block.custom.grid.gridWallTorch;
import modchest.block.entity.gridEntity;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
@Mixin({
gridBlock.class,
gridSlab.class,
gridStairs.class,
gridFence.class,
gridFenceGate.class,
gridTrapdoor.class,
gridDoor.class,
gridPath.class,
gridTorch.class,
gridWallTorch.class,
gridPressurePlate.class,
gridWall.class,
gridLayer.class,
gridCarpet.class,
gridPane.class
})
public class gridEntityProvider implements BlockEntityProvider {
private gridEntityProvider() {
throw new IllegalStateException("Mixin constructor should not run");
}
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new gridEntity(BLOCK_ENTITY_TYPES.GRID, META.FRAME_SECTIONS);
}
}

View File

@ -0,0 +1,13 @@
package modchest.mixin.mc;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
@Mixin(BakedQuad.class)
public interface BakedQuadAccess {
@Accessor("sprite")
Sprite sprite;
}

View File

@ -0,0 +1,15 @@
package modchest.mixin.mc;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
@Mixin(BlockItem.class)
public interface BlockItemAccess {
@Invoker("getPlacementState")
@Nullable BlockState getPlacementStateProxy(ItemPlacementContext context);
}

View File

@ -0,0 +1,27 @@
package modchest.mixin.mc;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import modchest.REServerMod;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FenceBlock;
import net.minecraft.util.math.Direction;
@Mixin(FenceBlock.class)
public class FenceBlockMixin {
@Inject(method = "canConnect", at = @At("HEAD"), cancellable = true)
void connectToGridFence(final BlockState state, final boolean neighborIsFullSquare, final Direction dir,
final CallbackInfoReturnable<Boolean> cir) {
if (state.isOf(modchest.REServerMod.BLOCKS.GRID_FENCE)) {
cir.setReturnValue(true);
}
if ((Object) this == REServerMod.BLOCKS.GRID_FENCE && state.getBlock() instanceof FenceBlock) {
cir.setReturnValue(true);
}
}
}

View File

@ -0,0 +1,13 @@
package modchest.mixin.mc;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@Mixin(ItemStack.class)
public interface GetItemBeforeEmpty {
@Accessor("item")
Item getItemBeforeEmpty();
}

View File

@ -0,0 +1,53 @@
package modchest.mixin.mc;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import modchest.util.initializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.item.ItemModels;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@Environment(EnvType.CLIENT)
@Mixin(ItemRenderer.class)
public abstract class ItemRendererMixin {
@Final
@Shadow
private ItemModels models;
@Shadow
public abstract BakedModel getHeldItemModel(ItemStack stack, World world, LivingEntity entity);
@Redirect(method = "getHeldItemModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemModels;getModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/render/model/BakedModel;"))
BakedModel getModelProxy(final ItemModels itemModels, final ItemStack stack) {
if (stack.getItem() == ITEMS.HAMMER) {
return itemModels.getModelManager().getModel(new ModelIdentifier(META.id("hammer_none"), "inventory"));
}
return itemModels.getModel(stack);
}
@Redirect(method = "innerRenderInGui", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderer;getHeldItemModel(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/client/render/model/BakedModel;"))
BakedModel getHeldItemModelProxy(final ItemRenderer itemRenderer, final ItemStack stack, final World world,
final LivingEntity entity) {
if (stack.getItem() == ITEMS.HAMMER) {
final ClientWorld clientWorld = world instanceof ClientWorld ? (ClientWorld) world : null;
final BakedModel model = models.getModelManager()
.getModel(new ModelIdentifier(META.id("hammer"), "inventory"));
final BakedModel model2 = model.getOverrides().apply(model, stack, clientWorld, entity, 0);
return model2 == null ? models.getModelManager().getMissingModel() : model2;
}
return this.getHeldItemModel(stack, world, entity);
}
}

View File

@ -0,0 +1,90 @@
package modchest.mixin.mc;
import java.util.Map;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import com.google.common.collect.ImmutableMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.WallBlock;
import net.minecraft.block.enums.WallShape;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
@Mixin(WallBlock.class)
public class WallBlockMixin extends Block {
@Shadow
@Final
public static BooleanProperty UP;
@Shadow
@Final
public static EnumProperty<WallShape> EAST_SHAPE;
@Shadow
@Final
public static EnumProperty<WallShape> WEST_SHAPE;
@Shadow
@Final
public static EnumProperty<WallShape> SOUTH_SHAPE;
@Shadow
@Final
public static EnumProperty<WallShape> NORTH_SHAPE;
@SuppressWarnings("unused")
public WallBlockMixin(Settings settings) {
super(settings);
throw new IllegalStateException("Mixin constructor should not run");
}
@SuppressWarnings("unused")
@Shadow
private static VoxelShape method_24426(VoxelShape voxelShape, WallShape wallShape, VoxelShape voxelShape2, VoxelShape voxelShape3) {
throw new IllegalStateException("Shadow method should not run.");
}
@SuppressWarnings("DuplicatedCode")
@Override
private Map<BlockState, VoxelShape> getShapeMap(float f, float g, float h, float i, float j, float k) {
float l = 8.0F - f;
float m = 8.0F + f;
float n = 8.0F - g;
float o = 8.0F + g;
VoxelShape voxelShape = Block.createCuboidShape(l, 0.0D, l, m, h, m);
VoxelShape voxelShape2 = Block.createCuboidShape(n, i, 0.0D, o, j, o);
VoxelShape voxelShape3 = Block.createCuboidShape(n, i, n, o, j, 16.0D);
VoxelShape voxelShape4 = Block.createCuboidShape(0.0D, i, n, o, j, o);
VoxelShape voxelShape5 = Block.createCuboidShape(n, i, n, 16.0D, j, o);
VoxelShape voxelShape6 = Block.createCuboidShape(n, i, 0.0D, o, k, o);
VoxelShape voxelShape7 = Block.createCuboidShape(n, i, n, o, k, 16.0D);
VoxelShape voxelShape8 = Block.createCuboidShape(0.0D, i, n, o, k, o);
VoxelShape voxelShape9 = Block.createCuboidShape(n, i, n, 16.0D, k, o);
ImmutableMap.Builder<BlockState, VoxelShape> builder = ImmutableMap.builder();
for (BlockState state : stateManager.getStates()) {
Boolean boolean_ = state.get(UP);
WallShape wallShape = state.get(EAST_SHAPE);
WallShape wallShape2 = state.get(NORTH_SHAPE);
WallShape wallShape3 = state.get(WEST_SHAPE);
WallShape wallShape4 = state.get(SOUTH_SHAPE);
VoxelShape voxelShape10 = VoxelShapes.empty();
voxelShape10 = method_24426(voxelShape10, wallShape, voxelShape5, voxelShape9);
voxelShape10 = method_24426(voxelShape10, wallShape3, voxelShape4, voxelShape8);
voxelShape10 = method_24426(voxelShape10, wallShape2, voxelShape2, voxelShape6);
voxelShape10 = method_24426(voxelShape10, wallShape4, voxelShape3, voxelShape7);
if (Boolean.TRUE.equals(boolean_)) {
voxelShape10 = VoxelShapes.union(voxelShape10, voxelShape);
}
builder.put(state, voxelShape10);
}
return builder.build();
}
}

View File

@ -0,0 +1,15 @@
package modchest.mixin.mc;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.WorldRenderer;
@Mixin(WorldRenderer.class)
@Environment(EnvType.CLIENT)
public interface WorldRendererAccess {
@Accessor("ticks")
int ticks();
}

View File

@ -0,0 +1,35 @@
package modchest.util;
import java.util.PrimitiveIterator;
public class Float4 {
public final float a;
public final float b;
public final float c;
public final float d;
public Float4(final float a, final float b, final float c, final float d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public static Float4 of(final float a, final float b, final float c, final float d) {
return new Float4(a, b, c, d);
}
public float min() {
return Math.min(Math.min(Math.min(a, b), c), d);
}
public float max() {
return Math.max(Math.max(Math.max(a, b), c), d);
}
public static Float4 fromIterator(final PrimitiveIterator.OfDouble doubles) {
return new Float4((float) doubles.nextDouble(), (float) doubles.nextDouble(), (float) doubles.nextDouble(), (float) doubles.nextDouble());
}
}

View File

@ -0,0 +1,22 @@
package modchest.util;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Function;
import java.util.function.ToIntFunction;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class FunctionalUtil {
private FunctionalUtil() {
throw new IllegalStateException("Should not instantiate utility class.");
}
public static <A> OptionalInt mapToInt(final Optional<A> optional, final ToIntFunction<A> f) {
return optional.map(a -> OptionalInt.of(f.applyAsInt(a))).orElseGet(OptionalInt::empty);
}
public static <A> OptionalInt flatMapToInt(final Optional<A> optional, final Function<A, OptionalInt> f) {
return optional.isPresent() ? f.apply(optional.get()) : OptionalInt.empty();
}
}

View File

@ -0,0 +1,16 @@
package modchest.util;
import modchest.mixin.mc.GetItemBeforeEmpty;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class GetItemBeforeEmptyUtil {
private GetItemBeforeEmptyUtil(){
throw new IllegalStateException("Should not instantiate utility class.");
}
public static Item getItemBeforeEmpty(final ItemStack stack) {
return ((GetItemBeforeEmpty) (Object) stack).getItemBeforeEmpty();
}
}

View File

@ -0,0 +1,29 @@
package modchest.util;
import org.intellij.lang.annotations.JdkConstants.HorizontalAlignment;
import org.spongepowered.asm.util.perf.Profiler.Section;
import com.mojang.datafixers.util.Function5;
import net.minecraft.inventory.Inventory;
public enum GuiUtil {
;
public static WLabel label(final String translationKey) {
return new WLabel(new TranslatableText(translationKey));
}
@SuppressWarnings("deprecation")
public static <L extends WLabel> L centered(final L label) {
label.setHorizontalAlignment(HorizontalAlignment.CENTER);
label.setVerticalAlignment(VerticalAlignment.CENTER);
return label;
}
public static <S extends WItemSlot> S slotRow(
final Function5<Inventory, Integer, Integer, Integer, Boolean, S> constructor, final Inventory inventory,
final Section section) {
return constructor.apply(inventory, section.start(), section.size(), 1, false);
}
}

View File

@ -0,0 +1,21 @@
package modchest.util;
import net.minecraft.util.Identifier;
public class Identifiable<A> {
private final A value;
private final Identifier id;
public Identifiable (final A value, final Identifier id) {
this.value = value;
this.id = id;
}
public A value() {
return value;
}
public Identifier id() {
return id;
}
}

View File

@ -0,0 +1,86 @@
package modchest.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Section implements Iterable<Integer> {
private final int start;
private final int end;
public Section(final int start, final int end) {
this.start = start;
this.end = end;
}
public static Section exclusive(final int start, final int end) {
return new Section(start, end);
}
public int start() {
return start;
}
public int end() {
return end;
}
public int size() {
return end - start;
}
public int makeRelative(final int absolute) {
return absolute - start;
}
public int makeAbsolute(final int relative) {
return relative + start;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
final Section section = (Section) o;
if (start != section.start)
return false;
return end == section.end;
}
@Override
public int hashCode() {
int result = start;
result = 31 * result + end;
return result;
}
public boolean contains(final int i) {
return start <= i && i < end;
}
@Override
public Iterator<Integer> iterator() {
return new SectionIterator();
}
private class SectionIterator implements Iterator<Integer> {
int current = start;
@Override
public boolean hasNext() {
return current < end;
}
@Override
public Integer next() {
if (current >= end) {
throw new NoSuchElementException();
}
return current++;
}
}
}

View File

@ -0,0 +1,75 @@
package modchest.util;
import java.util.Optional;
import java.util.function.Function;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.World;
public class ValidQuery {
private ValidQuery() {}
public static class ItemStackValidQuery {
private final ItemStack stack;
public ItemStackValidQuery(final ItemStack stack) {
this.stack = stack;
}
public Optional<BlockState> isValidForBase (final Function<BlockItem, Optional<BlockState>> toState, final World world, final BlockPos pos) {
final Item item = stack.getItem();
if (item instanceof BlockItem) {
final BlockItem blockItem = (BlockItem) item;
if (blockItem.getBlock() instanceof grid) {
return Optional.empty();
} else {
return toState.apply(blockItem).filter(b -> checkIf(b).isValidForBase(world, pos));
}
} else {
return Optional.empty();
}
}
public boolean isValidForOverlay () {
return OVERLAYS.hasOverlay(stack);
}
public boolean isValidForSpecial() {
return SPECIAL_ITEMS.Map.containsKey(stack.getItem());
}
}
public static class BlockStateValidQuery {
private final BlockState state;
public BlockStateValidQuery(final BlockState state) {
this.state = state;
}
public boolean isValidForBase(final World world, final BlockPos pos) {
if (state.getBlock() instanceof BlockEntityProvider && state.getRenderType() != BlockRenderType.MODEL) {
return false;
}
return state.getOutlineShape(world, pos).getBoundingBoxes().equals(VoxelShapes.fullCube().getBoundingBoxes());
}
}
public static ItemStackValidQuery checkIf(final ItemStack stack) {
return new ItemStackValidQuery(stack);
}
public static BlockStateValidQuery checkIf(final BlockState state) {
return new BlockStateValidQuery(state);
}
}

View File

@ -3,7 +3,6 @@ package modchest.util;
import modchest.block.entity.modBlockEntities; import modchest.block.entity.modBlockEntities;
import modchest.block.modBlocks; import modchest.block.modBlocks;
import modchest.event.playerAfterRespawnEvent; import modchest.event.playerAfterRespawnEvent;
import modchest.event.useBlockCallback;
import modchest.item.modItemGroup; import modchest.item.modItemGroup;
import modchest.item.modItems; import modchest.item.modItems;
import modchest.networking.modNetworkingServer; import modchest.networking.modNetworkingServer;
@ -23,7 +22,8 @@ public class initializer {
public static void events() { //Events, bei denen custom Code ausgefuehrt wird, werden eingefuehrt public static void events() { //Events, bei denen custom Code ausgefuehrt wird, werden eingefuehrt
ServerPlayerEvents.AFTER_RESPAWN.register(new playerAfterRespawnEvent()); ServerPlayerEvents.AFTER_RESPAWN.register(new playerAfterRespawnEvent());
useBlockCallback.EVENT.register(new useBlockCallback()); //useBlockCallback.EVENT.register(new useBlockCallback());
//useEntityCallback.EVENT.register(new useEntityCallback());
} }
public static void networking() { //Identifier unter denen der Server zuhoert werden registriert public static void networking() { //Identifier unter denen der Server zuhoert werden registriert

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B