Merge branch 'master' into 1.16
# Conflicts: # src/main/java/carpet/network/ServerNetworkHandler.java # src/main/java/carpet/script/CarpetExpression.java
This commit is contained in:
commit
80ca80fe24
22 files changed
+528
-3
No files matched your search
@@ -11,6 +11,7 @@ version = project.minecraft_version+'-'+project.mod_version
|
|||||||
group = project.maven_group
|
group = project.maven_group
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
|
accessWidener "src/main/resources/carpet.accesswidener"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -2940,6 +2940,50 @@ item_category('ender_pearl') => misc
|
|||||||
item_category('stone') => building_blocks
|
item_category('stone') => building_blocks
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
### `recipe_data(item, type?)`, `recipe_data(recipe, type?)`
|
||||||
|
|
||||||
|
returns all recipes matching either an `item`, or represent actual `recipe` name. In vanilla datapack, for all items
|
||||||
|
that have one recipe available, the recipe name is the same as the item name but if an item has multiple recipes, its
|
||||||
|
direct name can be different.
|
||||||
|
|
||||||
|
Recipe type can take one of the following options:
|
||||||
|
* `'crafting'` - default, crafting table recipe
|
||||||
|
* `'smelting'` - furnace recipe
|
||||||
|
* `'blasting'` - blast furnace recipe
|
||||||
|
* `'smoking'` - smoker recipe
|
||||||
|
* `'campfire_cooking'` - campfire recipe
|
||||||
|
* `'stonecutting'` - stonecutter recipe
|
||||||
|
|
||||||
|
The return value is a list of available recipes (even if there is only one recipe available). Each recipe contains of
|
||||||
|
an item triple of the crafting result, list of ingredients, each containing a list of possible variants of the
|
||||||
|
ingredients in this slot, as item triples, or `null` if its a shaped recipe and a given slot in the patterns is left
|
||||||
|
empty, and recipe specification as another list. Possible recipe specs is:
|
||||||
|
* `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3.
|
||||||
|
* `['shapeless']` - shapeless crafting
|
||||||
|
* `['smelting', duration, xp]` - smelting/cooking recipes
|
||||||
|
* `['cutting']` - stonecutter recipe
|
||||||
|
* `['special']` - special crafting recipe, typically not present in the crafting menu
|
||||||
|
* `['custom']` - other recipe types
|
||||||
|
|
||||||
|
Note that ingredients are specified as tripes, with count and nbt information. Currently all recipes require always one
|
||||||
|
of the ingredients, and for some recipes, even if the nbt data for the ingredient is specified (e.g. `dispenser`), it
|
||||||
|
can accept items of any tags.
|
||||||
|
|
||||||
|
Also note that some recipes leave some products in the crafting window, and these can be determined using
|
||||||
|
`crafting_remaining_item()` function
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
<pre>
|
||||||
|
recipe_data('iron_ingot_from_nuggets')
|
||||||
|
recipe_data('iron_ingot')
|
||||||
|
recipe_data('glass', 'smelting')
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
### `crafting_remaining_item(item)`
|
||||||
|
|
||||||
|
returns `null` if the item has no remaining item in the crafting window when used as a crafting ingredient, or an
|
||||||
|
item name that serves as a replacement after crafting is done. Currently it can only be buckets and glass bottles.
|
||||||
|
|
||||||
### `inventory_size(inventory)`
|
### `inventory_size(inventory)`
|
||||||
|
|
||||||
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
|
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
|
||||||
@@ -3055,6 +3099,8 @@ __on_player_right_clicks_block(player, item_tuple, hand, block, face, hitvec) /
|
|||||||
__on_player_interacts_with_block(player, hand, block, face, hitvec) //right click on a block resulted in activation of said block
|
__on_player_interacts_with_block(player, hand, block, face, hitvec) //right click on a block resulted in activation of said block
|
||||||
__on_player_places_block(player, item_tuple, hand, block) // player have just placed the block.
|
__on_player_places_block(player, item_tuple, hand, block) // player have just placed the block.
|
||||||
__on_player_interacts_with_entity(player, entity, hand)
|
__on_player_interacts_with_entity(player, entity, hand)
|
||||||
|
__on_player_chooses_recipe(player, recipe, full_stack)
|
||||||
|
__on_player_switches_slot(player, from, to)
|
||||||
__on_player_attacks_entity(player, entity)
|
__on_player_attacks_entity(player, entity)
|
||||||
__on_player_takes_damage(player, amount, source, source_entity)
|
__on_player_takes_damage(player, amount, source, source_entity)
|
||||||
__on_player_deals_damage(player, amount, entity)
|
__on_player_deals_damage(player, amount, entity)
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ __on_player_right_clicks_block(player, item_tuple, hand, block, face, hitvec) /
|
|||||||
__on_player_interacts_with_block(player, hand, block, face, hitvec) //right click on a block resulted in activation of said block
|
__on_player_interacts_with_block(player, hand, block, face, hitvec) //right click on a block resulted in activation of said block
|
||||||
__on_player_places_block(player, item_tuple, hand, block) // player have just placed the block.
|
__on_player_places_block(player, item_tuple, hand, block) // player have just placed the block.
|
||||||
__on_player_interacts_with_entity(player, entity, hand)
|
__on_player_interacts_with_entity(player, entity, hand)
|
||||||
|
__on_player_chooses_recipe(player, recipe, full_stack)
|
||||||
|
__on_player_switches_slot(player, from, to)
|
||||||
__on_player_attacks_entity(player, entity)
|
__on_player_attacks_entity(player, entity)
|
||||||
__on_player_takes_damage(player, amount, source, source_entity)
|
__on_player_takes_damage(player, amount, source, source_entity)
|
||||||
__on_player_deals_damage(player, amount, entity)
|
__on_player_deals_damage(player, amount, entity)
|
||||||
|
|||||||
@@ -38,6 +38,50 @@ item_category('ender_pearl') => misc
|
|||||||
item_category('stone') => building_blocks
|
item_category('stone') => building_blocks
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
### `recipe_data(item, type?)`, `recipe_data(recipe, type?)`
|
||||||
|
|
||||||
|
returns all recipes matching either an `item`, or represent actual `recipe` name. In vanilla datapack, for all items
|
||||||
|
that have one recipe available, the recipe name is the same as the item name but if an item has multiple recipes, its
|
||||||
|
direct name can be different.
|
||||||
|
|
||||||
|
Recipe type can take one of the following options:
|
||||||
|
* `'crafting'` - default, crafting table recipe
|
||||||
|
* `'smelting'` - furnace recipe
|
||||||
|
* `'blasting'` - blast furnace recipe
|
||||||
|
* `'smoking'` - smoker recipe
|
||||||
|
* `'campfire_cooking'` - campfire recipe
|
||||||
|
* `'stonecutting'` - stonecutter recipe
|
||||||
|
|
||||||
|
The return value is a list of available recipes (even if there is only one recipe available). Each recipe contains of
|
||||||
|
an item triple of the crafting result, list of ingredients, each containing a list of possible variants of the
|
||||||
|
ingredients in this slot, as item triples, or `null` if its a shaped recipe and a given slot in the patterns is left
|
||||||
|
empty, and recipe specification as another list. Possible recipe specs is:
|
||||||
|
* `['shaped', width, height]` - shaped crafting. `width` and `height` can be 1, 2 or 3.
|
||||||
|
* `['shapeless']` - shapeless crafting
|
||||||
|
* `['smelting', duration, xp]` - smelting/cooking recipes
|
||||||
|
* `['cutting']` - stonecutter recipe
|
||||||
|
* `['special']` - special crafting recipe, typically not present in the crafting menu
|
||||||
|
* `['custom']` - other recipe types
|
||||||
|
|
||||||
|
Note that ingredients are specified as tripes, with count and nbt information. Currently all recipes require always one
|
||||||
|
of the ingredients, and for some recipes, even if the nbt data for the ingredient is specified (e.g. `dispenser`), it
|
||||||
|
can accept items of any tags.
|
||||||
|
|
||||||
|
Also note that some recipes leave some products in the crafting window, and these can be determined using
|
||||||
|
`crafting_remaining_item()` function
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
<pre>
|
||||||
|
recipe_data('iron_ingot_from_nuggets')
|
||||||
|
recipe_data('iron_ingot')
|
||||||
|
recipe_data('glass', 'smelting')
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
### `crafting_remaining_item(item)`
|
||||||
|
|
||||||
|
returns `null` if the item has no remaining item in the crafting window when used as a crafting ingredient, or an
|
||||||
|
item name that serves as a replacement after crafting is done. Currently it can only be buckets and glass bottles.
|
||||||
|
|
||||||
### `inventory_size(inventory)`
|
### `inventory_size(inventory)`
|
||||||
|
|
||||||
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
|
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ blocks_daylight
|
|||||||
blocks_movement
|
blocks_movement
|
||||||
brightness
|
brightness
|
||||||
chunk_tickets
|
chunk_tickets
|
||||||
|
crafting_remaining_item
|
||||||
create_marker
|
create_marker
|
||||||
current_dimension
|
current_dimension
|
||||||
day_time
|
day_time
|
||||||
@@ -67,6 +68,7 @@ power
|
|||||||
property
|
property
|
||||||
query
|
query
|
||||||
random_tick
|
random_tick
|
||||||
|
recipe_data
|
||||||
rect
|
rect
|
||||||
reload_chunk
|
reload_chunk
|
||||||
remove_all_markers
|
remove_all_markers
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ __on_player_attacks_entity
|
|||||||
__on_player_breaks_block
|
__on_player_breaks_block
|
||||||
__on_player_clicks_block
|
__on_player_clicks_block
|
||||||
__on_player_changes_dimension
|
__on_player_changes_dimension
|
||||||
|
__on_player_chooses_recipe
|
||||||
__on_player_deploys_elytra
|
__on_player_deploys_elytra
|
||||||
__on_player_drops_item
|
__on_player_drops_item
|
||||||
__on_player_drops_stack
|
__on_player_drops_stack
|
||||||
@@ -21,6 +22,7 @@ __on_player_starts_sneaking
|
|||||||
__on_player_starts_sprinting
|
__on_player_starts_sprinting
|
||||||
__on_player_stops_sneaking
|
__on_player_stops_sneaking
|
||||||
__on_player_stops_sprinting
|
__on_player_stops_sprinting
|
||||||
|
__on_player_switches_slot
|
||||||
__on_player_uses_item
|
__on_player_uses_item
|
||||||
__on_player_wakes_up
|
__on_player_wakes_up
|
||||||
__on_statistic
|
__on_statistic
|
||||||
|
|||||||
@@ -62,7 +62,9 @@
|
|||||||
|
|
||||||
player spawn entity_id entity_list entity_area entity_selector query modify entity_event
|
player spawn entity_id entity_list entity_area entity_selector query modify entity_event
|
||||||
|
|
||||||
stack_limit item_category inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item
|
stack_limit item_category recipe_data crafting_remaining_item
|
||||||
|
|
||||||
|
inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item
|
||||||
|
|
||||||
scan volume neighbours rect diamond
|
scan volume neighbours rect diamond
|
||||||
|
|
||||||
@@ -87,6 +89,7 @@
|
|||||||
__on_player_breaks_block
|
__on_player_breaks_block
|
||||||
__on_player_clicks_block
|
__on_player_clicks_block
|
||||||
__on_player_changes_dimension
|
__on_player_changes_dimension
|
||||||
|
__on_player_chooses_recipe
|
||||||
__on_player_deploys_elytra
|
__on_player_deploys_elytra
|
||||||
__on_player_drops_item
|
__on_player_drops_item
|
||||||
__on_player_drops_stack
|
__on_player_drops_stack
|
||||||
@@ -102,6 +105,7 @@
|
|||||||
__on_player_starts_sprinting
|
__on_player_starts_sprinting
|
||||||
__on_player_stops_sneaking
|
__on_player_stops_sneaking
|
||||||
__on_player_stops_sprinting
|
__on_player_stops_sprinting
|
||||||
|
__on_player_switches_slot
|
||||||
__on_player_uses_item
|
__on_player_uses_item
|
||||||
__on_player_wakes_up
|
__on_player_wakes_up
|
||||||
__on_statistic
|
__on_statistic
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package carpet.fakes;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IngredientInterface
|
||||||
|
{
|
||||||
|
List<Collection<ItemStack>> getRecipeStacks();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package carpet.fakes;
|
||||||
|
|
||||||
|
import net.minecraft.recipe.Recipe;
|
||||||
|
import net.minecraft.recipe.RecipeType;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface RecipeManagerInterface
|
||||||
|
{
|
||||||
|
List<Recipe<?>> getAllMatching(RecipeType type, Identifier output);
|
||||||
|
}
|
||||||
@@ -14,6 +14,11 @@ public class ClientPlayerEntity_clientCommandMixin
|
|||||||
@Inject(method = "sendChatMessage", at = @At("HEAD"))
|
@Inject(method = "sendChatMessage", at = @At("HEAD"))
|
||||||
private void inspectMessage(String string, CallbackInfo ci)
|
private void inspectMessage(String string, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
|
if (string.startsWith("/call"))
|
||||||
|
{
|
||||||
|
String command = string.substring(6);
|
||||||
|
CarpetClient.sendClientCommand(command);
|
||||||
|
}
|
||||||
if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet())
|
if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet())
|
||||||
{
|
{
|
||||||
ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this;
|
ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this;
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import carpet.fakes.IngredientInterface;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.recipe.Ingredient;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Mixin(Ingredient.class)
|
||||||
|
public class Ingredient_scarpetMixin implements IngredientInterface
|
||||||
|
{
|
||||||
|
@Shadow @Final private Ingredient.Entry[] entries;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Collection<ItemStack>> getRecipeStacks()
|
||||||
|
{
|
||||||
|
List<Collection<ItemStack>> res = Arrays.stream(entries).map(Ingredient.Entry::getStacks).collect(Collectors.toList());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import carpet.fakes.RecipeManagerInterface;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import net.minecraft.recipe.Recipe;
|
||||||
|
import net.minecraft.recipe.RecipeManager;
|
||||||
|
import net.minecraft.recipe.RecipeType;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Mixin(RecipeManager.class)
|
||||||
|
public class RecipeManager_scarpetMixin implements RecipeManagerInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
@Shadow private Map<RecipeType<?>, Map<Identifier, Recipe<?>>> recipes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Recipe<?>> getAllMatching(RecipeType type, Identifier output)
|
||||||
|
{
|
||||||
|
Map<Identifier, Recipe<?>> typeRecipes = recipes.get(type);
|
||||||
|
if (typeRecipes.containsKey(output)) return Collections.singletonList(typeRecipes.get(output));
|
||||||
|
return Lists.newArrayList(typeRecipes.values().stream().filter(
|
||||||
|
r -> Registry.ITEM.getId(r.getOutput().getItem()).equals(output)).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.network.packet.c2s.play.ButtonClickC2SPacket;
|
||||||
|
import net.minecraft.network.packet.c2s.play.CraftRequestC2SPacket;
|
||||||
|
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket;
|
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket;
|
||||||
@@ -29,10 +32,12 @@ import static carpet.script.CarpetEventServer.Event.PLAYER_RELEASED_ITEM;
|
|||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_RIDES;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_RIDES;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_JUMPS;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_JUMPS;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_RIGHT_CLICKS_BLOCK;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_RIGHT_CLICKS_BLOCK;
|
||||||
|
import static carpet.script.CarpetEventServer.Event.PLAYER_CHOOSES_RECIPE;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_STARTS_SNEAKING;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_STARTS_SNEAKING;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_STARTS_SPRINTING;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_STARTS_SPRINTING;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_STOPS_SNEAKING;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_STOPS_SNEAKING;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_STOPS_SPRINTING;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_STOPS_SPRINTING;
|
||||||
|
import static carpet.script.CarpetEventServer.Event.PLAYER_SWITCHES_SLOT;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_USES_ITEM;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_USES_ITEM;
|
||||||
import static carpet.script.CarpetEventServer.Event.PLAYER_WAKES_UP;
|
import static carpet.script.CarpetEventServer.Event.PLAYER_WAKES_UP;
|
||||||
|
|
||||||
@@ -219,4 +224,28 @@ public class ServerPlayNetworkHandler_scarpetEventsMixin
|
|||||||
//todo add hit and hand in the future
|
//todo add hit and hand in the future
|
||||||
PLAYER_ATTACKS_ENTITY.onEntityAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), null);
|
PLAYER_ATTACKS_ENTITY.onEntityAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onButtonClick", at = @At("HEAD"))
|
||||||
|
private void onItemBeingPickedFromInventory(ButtonClickC2SPacket packet, CallbackInfo ci)
|
||||||
|
{
|
||||||
|
// crafts not int the crafting window
|
||||||
|
//CarpetSettings.LOG.error("Player clicks button "+packet.getButtonId());
|
||||||
|
}
|
||||||
|
@Inject(method = "onCraftRequest", at = @At("HEAD"))
|
||||||
|
private void onRecipeSelectedInRecipeManager(CraftRequestC2SPacket packet, CallbackInfo ci)
|
||||||
|
{
|
||||||
|
if (PLAYER_CHOOSES_RECIPE.isNeeded())
|
||||||
|
{
|
||||||
|
PLAYER_CHOOSES_RECIPE.onRecipeSelected(player, packet.getRecipe(), packet.shouldCraftAll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onUpdateSelectedSlot", at = @At("HEAD"))
|
||||||
|
private void onUpdatedSelectedSLot(UpdateSelectedSlotC2SPacket packet, CallbackInfo ci)
|
||||||
|
{
|
||||||
|
if (PLAYER_SWITCHES_SLOT.isNeeded())
|
||||||
|
{
|
||||||
|
PLAYER_SWITCHES_SLOT.onSlotSwitch(player, player.inventory.selectedSlot, packet.getSelectedSlot());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
package carpet.network;
|
package carpet.network;
|
||||||
|
|
||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
|
import carpet.CarpetSettings;
|
||||||
import carpet.script.utils.ShapesRenderer;
|
import carpet.script.utils.ShapesRenderer;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
public class CarpetClient
|
public class CarpetClient
|
||||||
@@ -51,4 +56,26 @@ public class CarpetClient
|
|||||||
{
|
{
|
||||||
return isServerCarpet;
|
return isServerCarpet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean sendClientCommand(String command)
|
||||||
|
{
|
||||||
|
if (!isServerCarpet && CarpetServer.minecraft_server == null) return false;
|
||||||
|
ClientNetworkHandler.clientCommand(command);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onClientCommand(Tag t)
|
||||||
|
{
|
||||||
|
CarpetSettings.LOG.info("Server Response:");
|
||||||
|
CompoundTag tag = (CompoundTag)t;
|
||||||
|
CarpetSettings.LOG.info(" - id: "+tag.getString("id"));
|
||||||
|
CarpetSettings.LOG.info(" - code: "+tag.getInt("code"));
|
||||||
|
if (tag.contains("error")) CarpetSettings.LOG.warn(" - error: "+tag.getString("error"));
|
||||||
|
if (tag.contains("output"))
|
||||||
|
{
|
||||||
|
ListTag outputTag = (ListTag) tag.get("output");
|
||||||
|
for (int i = 0; i < outputTag.size(); i++)
|
||||||
|
CarpetSettings.LOG.info(" - response: " + Text.Serializer.fromJson(outputTag.getString(i)).getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,9 @@ public class ClientNetworkHandler
|
|||||||
if (CarpetClient.shapes != null)
|
if (CarpetClient.shapes != null)
|
||||||
CarpetClient.shapes.addShapes((ListTag) t);
|
CarpetClient.shapes.addShapes((ListTag) t);
|
||||||
});
|
});
|
||||||
|
put("clientCommand", (p, t) -> {
|
||||||
|
CarpetClient.onClientCommand(t);
|
||||||
|
});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
@@ -99,4 +102,17 @@ public class ClientNetworkHandler
|
|||||||
CarpetSettings.LOG.error("Unknown carpet data: "+key);
|
CarpetSettings.LOG.error("Unknown carpet data: "+key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void clientCommand(String command)
|
||||||
|
{
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
tag.putString("id", command);
|
||||||
|
tag.putString("command", command);
|
||||||
|
CompoundTag outer = new CompoundTag();
|
||||||
|
outer.put("clientCommand", tag);
|
||||||
|
CarpetClient.getPlayer().networkHandler.sendPacket(new CustomPayloadC2SPacket(
|
||||||
|
CarpetClient.CARPET_CHANNEL,
|
||||||
|
(new PacketByteBuf(Unpooled.buffer())).writeVarInt(CarpetClient.DATA).writeCompoundTag(outer)
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,22 +6,37 @@ import carpet.helpers.TickSpeed;
|
|||||||
import carpet.settings.ParsedRule;
|
import carpet.settings.ParsedRule;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.StringTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
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.util.PacketByteBuf;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class ServerNetworkHandler
|
public class ServerNetworkHandler
|
||||||
{
|
{
|
||||||
private static Map<ServerPlayerEntity, String> remoteCarpetPlayers = new HashMap<>();
|
private static Map<ServerPlayerEntity, String> remoteCarpetPlayers = new HashMap<>();
|
||||||
private static Set<ServerPlayerEntity> validCarpetPlayers = new HashSet<>();
|
private static Set<ServerPlayerEntity> validCarpetPlayers = new HashSet<>();
|
||||||
|
|
||||||
|
private static Map<String, BiConsumer<ServerPlayerEntity, Tag>> dataHandlers = new HashMap<String, BiConsumer<ServerPlayerEntity, Tag>>(){{
|
||||||
|
put("clientCommand", (p, t) -> {
|
||||||
|
handleClientCommand(p, (CompoundTag)t);
|
||||||
|
});
|
||||||
|
}};
|
||||||
|
|
||||||
public static void handleData(PacketByteBuf data, ServerPlayerEntity player)
|
public static void handleData(PacketByteBuf data, ServerPlayerEntity player)
|
||||||
{
|
{
|
||||||
if (data != null)
|
if (data != null)
|
||||||
@@ -29,8 +44,13 @@ public class ServerNetworkHandler
|
|||||||
int id = data.readVarInt();
|
int id = data.readVarInt();
|
||||||
if (id == CarpetClient.HELLO)
|
if (id == CarpetClient.HELLO)
|
||||||
onHello(player, data);
|
onHello(player, data);
|
||||||
|
if (id == CarpetClient.DATA)
|
||||||
|
onClientData(player, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void onPlayerJoin(ServerPlayerEntity playerEntity)
|
public static void onPlayerJoin(ServerPlayerEntity playerEntity)
|
||||||
{
|
{
|
||||||
if (!playerEntity.networkHandler.connection.isLocal())
|
if (!playerEntity.networkHandler.connection.isLocal())
|
||||||
@@ -61,7 +81,68 @@ public class ServerNetworkHandler
|
|||||||
CarpetServer.settingsManager.getRules().forEach(data::withRule);
|
CarpetServer.settingsManager.getRules().forEach(data::withRule);
|
||||||
playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetClient.CARPET_CHANNEL, data.build() ));
|
playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetClient.CARPET_CHANNEL, data.build() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void handleClientCommand(ServerPlayerEntity player, CompoundTag commandData)
|
||||||
|
{
|
||||||
|
String command = commandData.getString("command");
|
||||||
|
String id = commandData.getString("id");
|
||||||
|
List<Text> output = new ArrayList<>();
|
||||||
|
String[] error = {null};
|
||||||
|
int resultCode = -1;
|
||||||
|
if (player.getServer() == null)
|
||||||
|
{
|
||||||
|
error[0] = "No Server";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resultCode = player.getServer().getCommandManager().execute(
|
||||||
|
new ServerCommandSource(player, player.getPos(), player.getRotationClient(),
|
||||||
|
player.world instanceof ServerWorld ? (ServerWorld) player.world : null,
|
||||||
|
player.server.getPermissionLevel(player.getGameProfile()), player.getName().getString(), player.getDisplayName(),
|
||||||
|
player.world.getServer(), player)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void sendError(Text message)
|
||||||
|
{
|
||||||
|
error[0] = message.getString();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void sendFeedback(Text message, boolean broadcastToOps)
|
||||||
|
{
|
||||||
|
output.add(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
command
|
||||||
|
);
|
||||||
|
};
|
||||||
|
CompoundTag result = new CompoundTag();
|
||||||
|
result.putString("id", id);
|
||||||
|
result.putInt("code", resultCode);
|
||||||
|
if (error[0] != null) result.putString("error", error[0]);
|
||||||
|
ListTag outputResult = new ListTag();
|
||||||
|
for (Text line: output) outputResult.add(StringTag.of(Text.Serializer.toJson(line)));
|
||||||
|
if (!output.isEmpty()) result.put("output", outputResult);
|
||||||
|
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(
|
||||||
|
CarpetClient.CARPET_CHANNEL,
|
||||||
|
DataBuilder.create().withCustomNbt("clientCommand", result).build()
|
||||||
|
));
|
||||||
|
// run command plug to command output,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void onClientData(ServerPlayerEntity player, PacketByteBuf data)
|
||||||
|
{
|
||||||
|
CompoundTag compound = data.readCompoundTag();
|
||||||
|
if (compound == null) return;
|
||||||
|
for (String key: compound.getKeys())
|
||||||
|
{
|
||||||
|
if (dataHandlers.containsKey(key))
|
||||||
|
dataHandlers.get(key).accept(player, compound.get(key));
|
||||||
|
else
|
||||||
|
CarpetSettings.LOG.warn("Unknown carpet client data: "+key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void updateRuleWithConnectedClients(ParsedRule<?> rule)
|
public static void updateRuleWithConnectedClients(ParsedRule<?> rule)
|
||||||
{
|
{
|
||||||
if (CarpetSettings.superSecretSetting) return;
|
if (CarpetSettings.superSecretSetting) return;
|
||||||
|
|||||||
@@ -494,6 +494,37 @@ public class CarpetEventServer
|
|||||||
handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource);
|
handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
PLAYER_CHOOSES_RECIPE("player_chooses_recipe", 3, false)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onRecipeSelected(ServerPlayerEntity player, Identifier recipe, boolean fullStack)
|
||||||
|
{
|
||||||
|
handler.call( () ->
|
||||||
|
{
|
||||||
|
return Arrays.asList(
|
||||||
|
((c, t) -> new EntityValue(player)),
|
||||||
|
((c, t) -> new StringValue(NBTSerializableValue.nameFromRegistryId(recipe))),
|
||||||
|
((c, t) -> new NumericValue(fullStack))
|
||||||
|
);
|
||||||
|
}, player::getCommandSource);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PLAYER_SWITCHES_SLOT("player_switches_slot", 3, false)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSlotSwitch(ServerPlayerEntity player, int from, int to)
|
||||||
|
{
|
||||||
|
if (from == to) return; // initial slot update
|
||||||
|
handler.call( () ->
|
||||||
|
{
|
||||||
|
return Arrays.asList(
|
||||||
|
((c, t) -> new EntityValue(player)),
|
||||||
|
((c, t) -> new NumericValue(from)),
|
||||||
|
((c, t) -> new NumericValue(to))
|
||||||
|
);
|
||||||
|
}, player::getCommandSource);
|
||||||
|
}
|
||||||
|
},
|
||||||
PLAYER_TAKES_DAMAGE("player_takes_damage", 4, false)
|
PLAYER_TAKES_DAMAGE("player_takes_damage", 4, false)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@@ -653,6 +684,8 @@ public class CarpetEventServer
|
|||||||
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { }
|
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { }
|
||||||
public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, RegistryKey<World> fromDim, RegistryKey<World> dimTo) {}
|
public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, RegistryKey<World> fromDim, RegistryKey<World> dimTo) {}
|
||||||
public void onDamage(Entity target, float amount, DamageSource source) { }
|
public void onDamage(Entity target, float amount, DamageSource source) { }
|
||||||
|
public void onRecipeSelected(ServerPlayerEntity player, Identifier recipe, boolean fullStack) {}
|
||||||
|
public void onSlotSwitch(ServerPlayerEntity player, int from, int to) {}
|
||||||
|
|
||||||
|
|
||||||
public void onWorldEvent(ServerWorld world, BlockPos pos) { }
|
public void onWorldEvent(ServerWorld world, BlockPos pos) { }
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ package carpet.script;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.fakes.BiomeArrayInterface;
|
import carpet.fakes.BiomeArrayInterface;
|
||||||
import carpet.fakes.ChunkTicketManagerInterface;
|
import carpet.fakes.ChunkTicketManagerInterface;
|
||||||
|
import carpet.fakes.IngredientInterface;
|
||||||
import carpet.fakes.MinecraftServerInterface;
|
import carpet.fakes.MinecraftServerInterface;
|
||||||
|
import carpet.fakes.BiomeArrayInterface;
|
||||||
|
import carpet.fakes.RecipeManagerInterface;
|
||||||
import carpet.fakes.ServerChunkManagerInterface;
|
import carpet.fakes.ServerChunkManagerInterface;
|
||||||
import carpet.fakes.SpawnHelperInnerInterface;
|
import carpet.fakes.SpawnHelperInnerInterface;
|
||||||
import carpet.fakes.StatTypeInterface;
|
import carpet.fakes.StatTypeInterface;
|
||||||
@@ -83,6 +86,13 @@ import net.minecraft.nbt.StringTag;
|
|||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.particle.ParticleEffect;
|
import net.minecraft.particle.ParticleEffect;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
|
import net.minecraft.recipe.AbstractCookingRecipe;
|
||||||
|
import net.minecraft.recipe.CuttingRecipe;
|
||||||
|
import net.minecraft.recipe.Recipe;
|
||||||
|
import net.minecraft.recipe.RecipeType;
|
||||||
|
import net.minecraft.recipe.ShapedRecipe;
|
||||||
|
import net.minecraft.recipe.ShapelessRecipe;
|
||||||
|
import net.minecraft.recipe.SpecialCraftingRecipe;
|
||||||
import net.minecraft.scoreboard.Scoreboard;
|
import net.minecraft.scoreboard.Scoreboard;
|
||||||
import net.minecraft.scoreboard.ScoreboardCriterion;
|
import net.minecraft.scoreboard.ScoreboardCriterion;
|
||||||
import net.minecraft.scoreboard.ScoreboardObjective;
|
import net.minecraft.scoreboard.ScoreboardObjective;
|
||||||
@@ -135,6 +145,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -1493,6 +1504,121 @@ public class CarpetExpression
|
|||||||
return (_c, _t) -> res;
|
return (_c, _t) -> res;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("recipe_data", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
CarpetContext cc = (CarpetContext)c;
|
||||||
|
if (lv.size() < 1) throw new InternalExpressionException("'recipe_data' requires at least one argument");
|
||||||
|
String recipeName = lv.get(0).evalValue(c).getString();
|
||||||
|
RecipeType type = RecipeType.CRAFTING;
|
||||||
|
if (lv.size() > 1)
|
||||||
|
{
|
||||||
|
String recipeType = lv.get(1).evalValue(c).getString();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
type = Registry.RECIPE_TYPE.get(new Identifier(recipeType));
|
||||||
|
}
|
||||||
|
catch (InvalidIdentifierException ignored)
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException("Unknown crafting category: " + recipeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Recipe<?>> recipes;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName));
|
||||||
|
}
|
||||||
|
catch (InvalidIdentifierException ignored)
|
||||||
|
{
|
||||||
|
return LazyValue.NULL;
|
||||||
|
}
|
||||||
|
if (recipes.isEmpty())
|
||||||
|
return LazyValue.NULL;
|
||||||
|
List<Value> recipesOutput = new ArrayList<>();
|
||||||
|
for (Recipe<?> recipe: recipes)
|
||||||
|
{
|
||||||
|
ItemStack result = recipe.getOutput();
|
||||||
|
List<Value> ingredientValue = new ArrayList<>();
|
||||||
|
CarpetSettings.LOG.error("input size: "+recipe.getPreviewInputs().size());
|
||||||
|
recipe.getPreviewInputs().forEach(
|
||||||
|
ingredient ->
|
||||||
|
{
|
||||||
|
// I am flattening ingredient lists per slot.
|
||||||
|
// consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference
|
||||||
|
// in depths of lists.
|
||||||
|
List<Collection<ItemStack>> stacks = ((IngredientInterface) (Object) ingredient).getRecipeStacks();
|
||||||
|
if (stacks.isEmpty())
|
||||||
|
{
|
||||||
|
ingredientValue.add(Value.NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<Value> alternatives = new ArrayList<>();
|
||||||
|
stacks.forEach(col -> col.stream().map(ListValue::fromItemStack).forEach(alternatives::add));
|
||||||
|
ingredientValue.add(ListValue.wrap(alternatives));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Value recipeSpec;
|
||||||
|
if (recipe instanceof ShapedRecipe)
|
||||||
|
{
|
||||||
|
recipeSpec = ListValue.of(
|
||||||
|
new StringValue("shaped"),
|
||||||
|
new NumericValue(((ShapedRecipe) recipe).getWidth()),
|
||||||
|
new NumericValue(((ShapedRecipe) recipe).getHeight())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (recipe instanceof ShapelessRecipe)
|
||||||
|
{
|
||||||
|
recipeSpec = ListValue.of(new StringValue("shapeless"));
|
||||||
|
}
|
||||||
|
else if (recipe instanceof AbstractCookingRecipe)
|
||||||
|
{
|
||||||
|
recipeSpec = ListValue.of(
|
||||||
|
new StringValue("smelting"),
|
||||||
|
new NumericValue(((AbstractCookingRecipe) recipe).getCookTime()),
|
||||||
|
new NumericValue(((AbstractCookingRecipe) recipe).getExperience())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (recipe instanceof CuttingRecipe)
|
||||||
|
{
|
||||||
|
recipeSpec = ListValue.of(new StringValue("cutting"));
|
||||||
|
}
|
||||||
|
else if (recipe instanceof SpecialCraftingRecipe)
|
||||||
|
{
|
||||||
|
recipeSpec = ListValue.of(new StringValue("special"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recipeSpec = ListValue.of(new StringValue("custom"));
|
||||||
|
}
|
||||||
|
|
||||||
|
recipesOutput.add(ListValue.of(ListValue.fromItemStack(result), ListValue.wrap(ingredientValue), recipeSpec));
|
||||||
|
}
|
||||||
|
Value ret = ListValue.wrap(recipesOutput);
|
||||||
|
return (_c, _t) -> ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("crafting_remaining_item", 1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
String itemStr = lv.get(0).evalValue(c).getString();
|
||||||
|
Item item;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Identifier id = new Identifier(itemStr);
|
||||||
|
item = Registry.ITEM.get(id);
|
||||||
|
if (item == Items.AIR && !id.getPath().equalsIgnoreCase("air"))
|
||||||
|
throw new InvalidIdentifierException("boo");
|
||||||
|
}
|
||||||
|
catch (InvalidIdentifierException ignored)
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException("Incorrect item: "+itemStr);
|
||||||
|
}
|
||||||
|
if (!item.hasRecipeRemainder()) return LazyValue.NULL;
|
||||||
|
Value ret = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder())));
|
||||||
|
return (_c, _t ) -> ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
this.expr.addLazyFunction("inventory_size", -1, (c, t, lv) ->
|
this.expr.addLazyFunction("inventory_size", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
@@ -2960,7 +3086,7 @@ public class CarpetExpression
|
|||||||
|
|
||||||
this.expr.addLazyFunction("seed", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("seed", -1, (c, t, lv) -> {
|
||||||
ServerCommandSource s = ((CarpetContext)c).s;
|
ServerCommandSource s = ((CarpetContext)c).s;
|
||||||
Value ret = new NumericValue(s.getWorld().getSeed());
|
Value ret = new StringValue(Long.toString(s.getWorld().getSeed()));
|
||||||
return (cc, tt) -> ret;
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -244,3 +244,23 @@ __on_player_disconnects(player, reason) ->
|
|||||||
print('__on_player_disconnects(player)');
|
print('__on_player_disconnects(player)');
|
||||||
print('Player '+player+' disconnects because: '+reason)
|
print('Player '+player+' disconnects because: '+reason)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
__on_player_chooses_recipe(player, recipe, full_stack) ->
|
||||||
|
(
|
||||||
|
print('');
|
||||||
|
print('__on_player_chooses_recipe(player, recipe, full_stack)');
|
||||||
|
print('player chooses recipe:');
|
||||||
|
print(' - player: '+player);
|
||||||
|
print(' - recipe: '+recipe);
|
||||||
|
print(' - full stack: '+ full_stack);
|
||||||
|
);
|
||||||
|
|
||||||
|
__on_player_switches_slot(player, from, to) ->
|
||||||
|
(
|
||||||
|
print('');
|
||||||
|
print('__on_player_switches_slot(player, from, to)');
|
||||||
|
print('player switches inventory slot:');
|
||||||
|
print(' - player: '+player);
|
||||||
|
print(' - from: '+ from);
|
||||||
|
print(' - to: '+ to);
|
||||||
|
);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
accessWidener v1 named
|
||||||
|
Accessible class net/minecraft/recipe/Ingredient$Entry
|
||||||
@@ -160,6 +160,9 @@
|
|||||||
"ServerWorld_scarpetEventMixin",
|
"ServerWorld_scarpetEventMixin",
|
||||||
"HungerManagerMixin_scarpetEventsMixin",
|
"HungerManagerMixin_scarpetEventsMixin",
|
||||||
|
|
||||||
|
"RecipeManager_scarpetMixin",
|
||||||
|
"Ingredient_scarpetMixin",
|
||||||
|
|
||||||
"PistonBlock_movableTEMixin",
|
"PistonBlock_movableTEMixin",
|
||||||
"PistonBlockEntity_movableTEMixin",
|
"PistonBlockEntity_movableTEMixin",
|
||||||
"World_movableTEMixin",
|
"World_movableTEMixin",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"mixins": [
|
"mixins": [
|
||||||
"carpet.mixins.json"
|
"carpet.mixins.json"
|
||||||
],
|
],
|
||||||
|
"accessWidener" : "carpet.accesswidener",
|
||||||
|
|
||||||
"depends": {
|
"depends": {
|
||||||
"minecraft": "1.16.x",
|
"minecraft": "1.16.x",
|
||||||
|
|||||||
Reference in new issue
Block a user