generated from minecraft-cursed-legacy/Example-Mod
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Modded ItemInstance Data and TileInteractionCallback (#19)
* version bumps * add tick callback * more world gen events * changes * update loader version * specify stuff * bump version * improve docs * Better copying * warning it's broken * so save/load works * f*kn mojang * progress * attached data * attached data 2 * attached data 3 * e * update mappings * make datamanager constructor public; make DataManager#copyData * Delete MixinItemEntity.java * remove item entity mixin * Update MixinClientInteractionManager.java * Update MixinClass_70.java * Final touches? * docs
- Loading branch information
1 parent
2e21811
commit 3ef85ad
Showing
19 changed files
with
468 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
src/main/java/io/github/minecraftcursedlegacy/api/data/AttachedData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package io.github.minecraftcursedlegacy.api.data; | ||
|
||
import io.github.minecraftcursedlegacy.api.registry.Id; | ||
import net.minecraft.util.io.CompoundTag; | ||
|
||
/** | ||
* Data which can be attached to various vanilla objects, such as items and blocks. | ||
* @see {@link DataManager}. | ||
*/ | ||
public interface AttachedData { | ||
/** | ||
* @return the id of this modded data. | ||
*/ | ||
Id getId(); | ||
/** | ||
* @return a tag representation of this data. | ||
*/ | ||
CompoundTag toTag(CompoundTag tag); | ||
/** | ||
* @param tag the tag from which to load data. | ||
*/ | ||
void fromTag(CompoundTag tag); | ||
/** | ||
* Creates a deep copy of this {@link AttachedData}, similar to the recommendations for {@link Object#clone}. | ||
*/ | ||
AttachedData copy(); | ||
} |
86 changes: 86 additions & 0 deletions
86
src/main/java/io/github/minecraftcursedlegacy/api/data/DataManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package io.github.minecraftcursedlegacy.api.data; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.function.Function; | ||
|
||
import io.github.minecraftcursedlegacy.api.registry.Id; | ||
import io.github.minecraftcursedlegacy.impl.data.DataStorage; | ||
import net.minecraft.item.ItemInstance; | ||
import net.minecraft.util.io.CompoundTag; | ||
|
||
/** | ||
* Manager for data which can be attached to various vanilla objects, such as items and blocks. | ||
*/ | ||
public final class DataManager<T> { | ||
private final Map<Id, Function<T, ? extends AttachedData>> attachedDataFactories = new HashMap<>(); | ||
|
||
/** | ||
* Adds the specified attached data to the {@link DataManager} instance. This data can later be accessed on an instance of the object via {@link #getAttachedData}. | ||
* @return a key to use to retrieve the attached data from an object. | ||
*/ | ||
public <E extends AttachedData> DataKey<E> addAttachedData(Id id, Function<T, E> dataProvider) { | ||
this.attachedDataFactories.put(id, dataProvider); | ||
return new DataKey<>(id); | ||
} | ||
|
||
/** | ||
* Retrieves the specified attached data from the object. | ||
*/ | ||
public <E extends AttachedData> E getAttachedData(T object, DataKey<E> key) throws ClassCastException { | ||
return key.apply(((DataStorage) object).getAttachedData(key.id, () -> this.attachedDataFactories.get(key.id).apply(object))); | ||
} | ||
|
||
/** | ||
* Used by the implementation. | ||
* @return a {@linkplain Set set} of all {@linkplain Id ids} of {@link AttachedData} instances registered to this manager. | ||
*/ | ||
public Set<Id> getDataKeys() { | ||
return this.attachedDataFactories.keySet(); | ||
} | ||
|
||
/** | ||
* Used by the implementation. | ||
* @return an attached data instance of the given type constructed by the given tag. | ||
*/ | ||
public AttachedData deserialize(T object, Id id, CompoundTag data) { | ||
AttachedData result = this.attachedDataFactories.get(id).apply(object); | ||
result.fromTag(data); | ||
return result; | ||
} | ||
|
||
/** | ||
* Used by the implementation. | ||
* @param from the object to use the data of. | ||
* @param to the object to receive the data. | ||
*/ | ||
public void copyData(T from, T to) { | ||
DataStorage to_ = (DataStorage) (Object) to; | ||
|
||
((DataStorage) (Object) from).getAllAttachedData().forEach(entry -> { | ||
Id dataId = entry.getKey(); | ||
AttachedData data = entry.getValue(); | ||
to_.putAttachedData(dataId, data.copy()); | ||
}); | ||
} | ||
|
||
public static final DataManager<ItemInstance> ITEM_INSTANCE = new DataManager<>(); | ||
|
||
public static final class DataKey<T extends AttachedData> { | ||
private DataKey(Id id) throws NullPointerException { | ||
if (id == null) { | ||
throw new NullPointerException("DataKey cannot store a null ID!"); | ||
} | ||
|
||
this.id = id; | ||
} | ||
|
||
private final Id id; | ||
|
||
@SuppressWarnings("unchecked") | ||
private T apply(AttachedData data) throws ClassCastException { | ||
return (T) data; | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/main/java/io/github/minecraftcursedlegacy/api/event/TileInteractionCallback.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package io.github.minecraftcursedlegacy.api.event; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import net.fabricmc.fabric.api.event.Event; | ||
import net.fabricmc.fabric.api.event.EventFactory; | ||
import net.minecraft.entity.player.Player; | ||
import net.minecraft.item.ItemInstance; | ||
import net.minecraft.level.Level; | ||
import net.minecraft.tile.Tile; | ||
|
||
/** | ||
* Callback for right clicking a tile. This is run both client and server side. | ||
* | ||
* <p>Upon return: | ||
* <ul> | ||
* <li> SUCCESS cancels further event processing and vanilla code, and the method this is event is called from returns true (succeeds). | ||
* <li> PASS falls back to further event processing. If all events PASS, then vanilla behaviour runs. | ||
* <li> FAIL cancels further event processing and vanilla code, and the method this is event is called from returns false (fails). | ||
* </ul> | ||
*/ | ||
@FunctionalInterface | ||
public interface TileInteractionCallback { | ||
Event<TileInteractionCallback> EVENT = EventFactory.createArrayBacked(TileInteractionCallback.class, | ||
(listeners) -> (player, level, item, tile, x, y, z, face) -> { | ||
for (TileInteractionCallback listener : listeners) { | ||
ActionResult result = listener.onTileInteract(player, level, item, tile, x, y, z, face); | ||
|
||
if (result != ActionResult.PASS) { | ||
return result; | ||
} | ||
} | ||
|
||
return ActionResult.PASS; | ||
}); | ||
|
||
/** | ||
* @param player the player causing the tile interaction. | ||
* @param level the level the tile is being interacted with in. | ||
* @param item the item instance that the player is using to interact with the tile. | ||
* @param tile the tile being interacted with at the time of this event firing. This does not change if an event subscriber alters the tile at that position. | ||
* @param face probably the tile face. The last parameter of {@link ItemInstance#useOnTile(Player, Level, int, int, int, int)}; | ||
* @return the action result, as specified in the javadoc of {@link TileInteractionCallback}. | ||
*/ | ||
ActionResult onTileInteract(Player player, Level level, @Nullable ItemInstance item, Tile tile, int x, int y, int z, int face); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/main/java/io/github/minecraftcursedlegacy/impl/data/DataStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package io.github.minecraftcursedlegacy.impl.data; | ||
|
||
import java.util.Map.Entry; | ||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
|
||
import io.github.minecraftcursedlegacy.api.data.AttachedData; | ||
import io.github.minecraftcursedlegacy.api.registry.Id; | ||
import net.minecraft.util.io.CompoundTag; | ||
|
||
public interface DataStorage { | ||
CompoundTag getModdedTag(); | ||
void putAttachedData(Id id, AttachedData data); | ||
AttachedData getAttachedData(Id id, Supplier<AttachedData> supplier); | ||
Set<Entry<Id,AttachedData>> getAllAttachedData(); | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/io/github/minecraftcursedlegacy/impl/event/TileInteractionImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package io.github.minecraftcursedlegacy.impl.event; | ||
|
||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; | ||
|
||
import io.github.minecraftcursedlegacy.api.event.ActionResult; | ||
import io.github.minecraftcursedlegacy.api.event.TileInteractionCallback; | ||
import net.minecraft.entity.player.Player; | ||
import net.minecraft.item.ItemInstance; | ||
import net.minecraft.level.Level; | ||
import net.minecraft.tile.Tile; | ||
|
||
public class TileInteractionImpl { | ||
public static void onTileInteract(Player player, Level level, ItemInstance item, int x, int y, int z, int i1, CallbackInfoReturnable<Boolean> info) { | ||
int tile = level.getTileId(x, y, z); | ||
ActionResult result = TileInteractionCallback.EVENT.invoker().onTileInteract(player, level, item, Tile.BY_ID[tile], x, y, z, i1); | ||
|
||
if (result != ActionResult.PASS) { | ||
info.setReturnValue(result == ActionResult.SUCCESS); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
src/main/java/io/github/minecraftcursedlegacy/mixin/MixinClientInteractionManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package io.github.minecraftcursedlegacy.mixin; | ||
|
||
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 io.github.minecraftcursedlegacy.impl.event.TileInteractionImpl; | ||
import net.minecraft.client.ClientInteractionManager; | ||
import net.minecraft.entity.player.Player; | ||
import net.minecraft.item.ItemInstance; | ||
import net.minecraft.level.Level; | ||
|
||
@Mixin(ClientInteractionManager.class) | ||
public class MixinClientInteractionManager { | ||
@Inject(at = @At("HEAD"), method = "useItemOnTile", cancellable = true) | ||
private void api_onTileInteract(Player player, Level level, ItemInstance item, int x, int y, int z, int i1, CallbackInfoReturnable<Boolean> info) { | ||
TileInteractionImpl.onTileInteract(player, level, item, x, y, z, i1, info); | ||
} | ||
} |
12 changes: 5 additions & 7 deletions
12
...aftcursedlegacy/mixin/MixinClass_556.java → ...edlegacy/mixin/MixinHandItemRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
src/main/java/io/github/minecraftcursedlegacy/mixin/MixinItemInstance.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package io.github.minecraftcursedlegacy.mixin; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
|
||
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.CallbackInfo; | ||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; | ||
|
||
import io.github.minecraftcursedlegacy.api.data.AttachedData; | ||
import io.github.minecraftcursedlegacy.api.data.DataManager; | ||
import io.github.minecraftcursedlegacy.api.registry.Id; | ||
import io.github.minecraftcursedlegacy.impl.data.DataStorage; | ||
import net.minecraft.item.ItemInstance; | ||
import net.minecraft.util.io.CompoundTag; | ||
|
||
@Mixin(ItemInstance.class) | ||
public abstract class MixinItemInstance implements DataStorage { | ||
private CompoundTag api_data = new CompoundTag(); | ||
private Map<Id, AttachedData> api_attachedDataMap = new HashMap<>(); | ||
|
||
@Inject(at = @At("RETURN"), method = "copy") | ||
private void api_copyData(CallbackInfoReturnable<ItemInstance> info) { | ||
DataStorage ds = ((DataStorage) (Object) info.getReturnValue()); | ||
|
||
this.api_attachedDataMap.forEach((id, data) -> { | ||
ds.putAttachedData(id, data.copy()); | ||
}); | ||
} | ||
|
||
@Inject(at = @At("RETURN"), method = "toTag") | ||
private void api_addData(CompoundTag tag, CallbackInfoReturnable<CompoundTag> info) { | ||
tag.put("moddedData", this.getModdedTag()); | ||
} | ||
|
||
@Inject(at = @At("RETURN"), method = "split") | ||
private void api_copySplitData(int countToTake, CallbackInfoReturnable<ItemInstance> info) { | ||
DataStorage ds = ((DataStorage) (Object) info.getReturnValue()); | ||
|
||
this.api_attachedDataMap.forEach((id, data) -> { | ||
ds.putAttachedData(id, this.api_attachedDataMap.get(id).copy()); | ||
}); | ||
} | ||
|
||
@Inject(at = @At("RETURN"), method = "fromTag") | ||
private void api_readData(CompoundTag tag, CallbackInfo info) { | ||
if (tag.containsKey("moddedData")) { | ||
this.api_data = tag.getCompoundTag("moddedData"); | ||
} | ||
|
||
// Load Data | ||
DataManager.ITEM_INSTANCE.getDataKeys().forEach(id -> { | ||
if (this.api_data.containsKey(id.toString())) { | ||
this.putAttachedData(id, DataManager.ITEM_INSTANCE.deserialize((ItemInstance) (Object) this, id, this.api_data.getCompoundTag(id.toString()))); | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public CompoundTag getModdedTag() { | ||
this.api_attachedDataMap.forEach((id, data) -> { | ||
this.api_data.put(id.toString(), data.toTag(new CompoundTag())); | ||
}); | ||
|
||
return this.api_data; | ||
} | ||
|
||
@Override | ||
public Set<Entry<Id,AttachedData>> getAllAttachedData() { | ||
return this.api_attachedDataMap.entrySet(); | ||
} | ||
|
||
@Override | ||
public void putAttachedData(Id id, AttachedData data) { | ||
this.api_attachedDataMap.put(id, data); | ||
} | ||
|
||
@Override | ||
public AttachedData getAttachedData(Id id, Supplier<AttachedData> supplier) { | ||
return this.api_attachedDataMap.computeIfAbsent(id, i -> supplier.get()); | ||
} | ||
} |
Oops, something went wrong.