SforzandoCF

btwce 1.21

Sep 30th, 2024 (edited)
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 21.95 KB | None | 0 0
  1. public final class HibachiBlock extends Block {
  2.     public HibachiBlock (AbstractBlock.Settings settings) {
  3.         super (settings);
  4.     }
  5.    
  6.     protected void neighborUpdate (BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
  7.         super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify);
  8.         this.tryLight(world, pos);
  9.     }
  10.    
  11.     protected void onBlockAdded (BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) {
  12.         super.onBlockAdded(state, world, pos, oldState, notify);
  13.         this.tryLight(world, pos);
  14.     }
  15.    
  16.     protected void randomTick (BlockState state, ServerWorld world, BlockPos pos, Random random) {
  17.         super.randomTick(state, world, pos, random);
  18.         this.tryLight(world, pos);
  19.     }
  20.    
  21.     private void tryLight (World world, BlockPos pos) {
  22.         if (world.isReceivingRedstonePower(pos) && world.getBlockState(pos.up()).isAir())
  23.             world.setBlockState(Blocks.FIRE.getDefaultState());
  24.     }
  25. }
  26.  
  27. public final class BlockDispenserBlock extends HorizontalFacingBlock implements BlockEntityProvider {
  28.     public BlockDispenserBlock (AbstractBlock.Settings settings) {
  29.         super (settings);
  30.     }
  31.    
  32.     protected void neighborUpdate (BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
  33.         super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify);
  34.         this.tryDispense(world, pos);
  35.     }
  36.    
  37.     protected void onBlockAdded (BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) {
  38.         super.onBlockAdded(state, world, pos, oldState, notify);
  39.         this.tryDispense(world, pos);
  40.     }
  41.    
  42.     protected void randomTick (BlockState state, ServerWorld world, BlockPos pos, Random random) {
  43.         super.randomTick(state, world, pos, random);
  44.         this.tryDispense(world, pos);
  45.     }
  46.    
  47.     private void tryDispense (World world, BlockPos pos) {
  48.         if (!world.getBlockState(pos).hasProperty(HorizontalFacingBlock.FACING)) return;
  49.         if (world.getRecievedStrongRedstonePower(pos) > 0) {
  50.             List<Entity> entities = world.getNonSpectatingEntities(Entity.class, new Box(pos.offset(1L, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING))));
  51.             if (entities.size() > 0) {
  52.                 boolean entityConsumed = false;
  53.                 for (Entity e : entities) {
  54.                     if (!entityConsumed)
  55.                         this.getOrCreateBlockEntity(world, pos).addItem(BlockDispenserBehaviors.ENTITY_COLLECTION.get(e.getClass()).collect(world, pos, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING), e));
  56.                     if (BlockDispenserEntityBehaviors.get(e.getClass()).consumesEntity()) entityConsumed = true;
  57.                 }
  58.                 if (entityConsumed) return;
  59.             }
  60.             if (world.getBlockState(pos.offset(1L, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING))).isIn(BlockTags.REPLACEABLE)) {
  61.                 Item next = this.getOrCreateBlockEntity(world, pos).next().getItem();
  62.                 if (BlockDispenserBehaviors.DISPENSING.get(next) != null) {
  63.                     BlockDispenserBehaviors.DISPENSING.get(next).dispense(world, pos, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING));
  64.                 } else if (BlockDispenserBehaviors.DISPENSING_BY_CLASS.get(next) != null) {
  65.                     BlockDispenserBehaviors.DISPENSING_BY_CLASS.get(next.getClass()).dispense(world, pos, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING));
  66.                 } else {
  67.                     if (next instanceof BlockItem)
  68.                         world.setBlockState(Block.getBlockForItem(next).getDefaultState());
  69.                     else
  70.                         Block.dropStack(world, pos.offset(1L, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING)), world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING), new ItemStack(next));
  71.                 }
  72.             } else {
  73.                 Block next = world.getBlockState(pos.offset(1L, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING))).getBlock();
  74.                 if (BlockDispenserBehaviors.COLLECTION.get(next) != null)
  75.                     this.getOrCreateBlockEntity(world, pos).addItem(BlockDispenserBehaviors.COLLECTION.get(next).collect(world, pos, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING)));
  76.                 else if (BlockDispenserBehaviors.COLLECTION_BY_CLASS.get(next) != null)
  77.                     this.getOrCreateBlockEntity(world, pos).addItem(BlockDispenserBehaviors.COLLECTION_BY_CLASS.get(next.getClass()).collect(world, pos, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING)));
  78.                 else
  79.                     world.destroyBlock(pos.offset(1L, world.getBlockState(pos).getValue(HorizontalFacingBlock.FACING)), false);
  80.             }
  81.         }
  82.     }
  83.    
  84.     public BlockEntity newBlockEntity (BlockPos pos, BlockState state) {
  85.         return new BlockEntity(pos, state);
  86.     }
  87.    
  88.     public BlockEntity getOrCreateBlockEntity (World world, BlockPos pos) {
  89.         if (world.getBlockEntity(pos) instanceof BlockEntity be)
  90.             return be;
  91.         else
  92.             return this.newBlockEntity(pos, world.getBlockState(pos));
  93.     }
  94.    
  95.     @FunctionalInterface
  96.     public static interface EntityBehavior {
  97.         ItemStack collect (World world, BlockPos pos, Direction d, Entity e);
  98.        
  99.         default boolean consumesEntity () {
  100.             return true;
  101.         }
  102.     }
  103.    
  104.     @FunctionalInterface
  105.     public static interface DispenseBehavior {
  106.         void dispense (World world, BlockPos pos, Direction d);
  107.     }
  108.    
  109.     @FunctionalInterface
  110.     public static interface CollectBehavior {
  111.         ItemStack collect (World world, BlockPos pos, Direction d);
  112.     }
  113.    
  114.     public static class BlockEntity extends net.minecraft.block.entity.BlockEntity implements Iterator<Item> {
  115.         private DefaultedList<ItemStack> items = DefaultedList.<ItemStack>ofSize(9, ItemStack.EMPTY);
  116.         private int index = 0;
  117.        
  118.         public BlockEntity (BlockPos pos, BlockState state) {
  119.             super (BetterThanWolvesBlockEntities.BLOCK_DISPENSER, pos, state);
  120.         }
  121.        
  122.         public boolean hasNext () {
  123.             return true;
  124.         }
  125.        
  126.         public Item next () {
  127.             if (this.index == 8) this.index = -1;
  128.             Item i = this.items.get(++this.index);
  129.             this.items.set(this.index, this.items.get(this.index).shrink(1));
  130.             return i;
  131.         }
  132.        
  133.         public void addItem (ItemStack item) {
  134.             ItemStack copy = item.copy();
  135.             for (ItemStack i : this.items) {
  136.                 if (i.getItem() == copy.getItem() || i.isEmpty()) {
  137.                     if ((i.getCount() + copy.getCount()) <= copy.getMaxCount()) {
  138.                         this.items.set(this.items.indexOf(i), copy.grow(i.getCount()));
  139.                     } else {
  140.                         this.items.set(this.items.indexOf(i), copy.setCount(i.getMaxCount()));
  141.                         copy.setCount(copy.getCount() - copy.getMaxCount());
  142.                     }
  143.                 }
  144.             }
  145.             if (copy.getCount() > 0)
  146.                 Block.dropStack(this.getWorld(), this.pos, this.state.hasProperty(HorizontalFacingBlock.FACING) ? this.state.getValue(HorizontalFacingBlock.FACING) : Direction.UP, copy);
  147.         }
  148.     }
  149. }
  150.  
  151. public class BlockDispenserBehaviors {
  152.     public static Map<Class<? extends Entity>, BlockDispenserBlock.EntityBehavior> ENTITY_COLLECTION = Map.<Class<? extends Entity>, BlockDispenserBlock.EntityBehavior>of();
  153.     public static Map<Item, BlockDispenserBlock.DispenseBehavior> DISPENSING = Map.<Item, BlockDispenserBlock.DispenseBehavior>of();
  154.     public static Map<Class<? extends Item>, BlockDispenserBlock.DispenseBehavior> DISPENSING_BY_CLASS = Map.<Class<? extends Item>, BlockDispenserBlock.DispenseBehavior>of();
  155.     public static Map<Block, BlockDispenserBlock.CollectBehavior> COLLECTION = Map.<Block, BlockDispenserBlock.CollectBehavior>of();
  156.    
  157.     static {
  158.         ENTITY_COLLECTION.put(WolfEntity.class, (w, p, d, e) -> {
  159.             e.discard();
  160.             Block.dropStack(w, p.offset(1L, d), new ItemStack(Items.STRING, 2));
  161.             return new ItemStack(BetterThanWolvesItems.COMPANION_CUBE);
  162.         });
  163.         ENTITY_COLLECTION.put(ChickenEntity.class, (w, p, d, e) -> {
  164.             e.discard();
  165.             return new ItemStack(Items.EGG);
  166.         });
  167.         ENTITY_COLLECTION.put(SheepEntity.class, (w, p, d, e) -> {
  168.             DyeColor color = ((SheepEntity)e).getColor();
  169.             e.discard();
  170.             Block.dropStack(w, p.offset(1L, d), new ItemStack(Items.STRING));
  171.             return ((SheepEntity)e).shearable() ? new ItemStack(BlockDispenserBlock.getWool(color)) : ItemStack.EMPTY;
  172.         });
  173.         DISPENSING_BY_CLASS.put(WindmillItem.class, (w, p, d, i) -> {
  174.             if (((WindmillItem)i).canPlace(w, p.offset(1L, d)))
  175.                 ((WindmillItem)i).tryPlace(p.offset(1L, d));
  176.             else
  177.                 Block.dropStack(w, p, d, new ItemStack(BetterThanWolvesItems.WINDMILL));
  178.         });
  179.         DISPENSING_BY_CLASS.put(VerticalWindmillItem.class, (w, p, d, i) -> { Block.dropStack(w, p, d, new ItemStack(i)); });
  180.         DISPENSING_BY_CLASS.put(WaterWheelItem.class, (w, p, d, i) -> {
  181.             if (((WaterWheelItem)i).canPlace(w, p.offset(1L, d)))
  182.                 ((WaterWheelItem)i).tryPlace(p.offset(1L, d));
  183.             else
  184.                 Block.dropStack(w, p, d, new ItemStack(BetterThanWolvesItems.WATER_WHEEL));
  185.         });
  186.         DISPENSING_BY_CLASS.put(BedItem.class, (w, p, d, i) -> {
  187.             if (w.getBlockState(p.offset(1L, d)).isIn(BlockTags.REPLACEABLE) && w.getBlockState(p.offset(2L, d)).isIn(BlockTags.REPLACEABLE) && w.getBlockState(p.offset(1L, d).down()).isSolid() && w.getBlockState(p.offset(2L, d).down()).isSolid()) {
  188.                 w.setBlockState(p.offset(1L, d), Block.getBlockForItem(i).getDefaultState().with(HorizontalFacingBlock.FACING, d).with(BedBlock.PART, BedPart.FOOT).with(BedBlock.OCCUPIED, Boolean.FALSE), 11);
  189.                 w.setBlockState(p.offset(2L, d), Block.getBlockForItem(i).getDefaultState().with(HorizontalFacingBlock.FACING, d).with(BedBlock.PART, BedPart.HEAD).with(BedBlock.OCCUPIED, Boolean.FALSE), 11);
  190.             } else {
  191.                 Block.dropStack(w, p, d, new ItemStack(i));
  192.             }
  193.         });
  194.         DISPENSING_BY_CLASS.put(HangingSignItem.class, (w, p, d, i) -> { Block.dropStack(w, p, d, new ItemStack(i)); });
  195.         DISPENSING_BY_CLASS.put(SignItem.class, (w, p, d, i) -> {
  196.             Boolean waterlogged;
  197.             if (w.getFluidState(p.offset(1L, d)).getType() == Fluids.WATER)
  198.                 waterlogged = Boolean.TRUE;
  199.             else
  200.                 waterlogged = Boolean.FALSE;
  201.             w.setBlockState(p.offset(1L, d), Block.getBlockForItem(i).getDefaultState().with(AbstractSignBlock.WATERLOGGED, waterlogged).with(WallSignBlock.FACING, d)), 11);
  202.            
  203.         });
  204.         DISPENSING_BY_CLASS.put(TallBlockItem.class, (w, p, d, i) -> { Block.dropStack(w, p, d, new ItemStack(i)); });
  205.         DISPENSING_BY_CLASS.put(DyeItem.class, (w, p, d, i) -> {
  206.             BlockState b = w.getBlockState(p.offset(1L, d));
  207.             if (b.isIn(BlockTags.WOOL)) {
  208.                 w.setBlockState(p.offset(1L, d), BlockDispenserBlock.getWool(((DyeItem)i).getColor()), 11);
  209.             } else if (b instanceof AbstractSignBlock) {
  210.                 SignBlockEntity sign = w.getBlockEntity(p.offset(1L, d));
  211.                 sign.setText(sign.getText(true).setColor(((DyeItem)i).getColor()), true);
  212.                 sign.setText(sign.getText(false).setColor(((DyeItem)i).getColor()), false);
  213.             } else {
  214.                 Block.dropStack(w, p, d, new ItemStack(i));
  215.             }
  216.         });
  217.     }
  218. }
  219.  
  220. public class CauldronBlock extends BaseEntityBlock {
  221.     public NamedScreenHandlerFactory createScreenHandlerFactory (BlockState state, World world, BlockPos pos) {
  222.         return this.getOrCreateBlockEntity(world, pos);
  223.     }
  224.    
  225.     public static class BlockEntity extends net.minecraft.block.entity.BlockEntity implements NamedScreenHandlerFactory {
  226.         private Inventory inventory = this.new Inventory();
  227.        
  228.         DefaultedList<ItemStack> items = DefaultedList.<ItemStack>ofSize(27, ItemStack.EMPTY);
  229.        
  230.         private boolean active = false;
  231.        
  232.         private int[] activeSlots;
  233.         private int[] activeSlotDecreases;
  234.        
  235.         private int progress = 0;
  236.         private int targetProgress;
  237.        
  238.         private ItemStack output;
  239.        
  240.         public BlockEntity (BlockPos pos, BlockState state) {
  241.             super (BetterThanWolvesBlockEntities.CAULDRON, pos, state);
  242.             this.notifyItemsChanged(-2);
  243.         }
  244.        
  245.         public Text getDisplayName () {
  246.             return Text.translatable("btwce:block.entity.cauldron.name");
  247.         }
  248.        
  249.         public ScreenHandler createMenu (int syncId, PlayerInventory inventory, Player player) {
  250.             return new GenericContainerScreen(new GenericContainerScreenHandler(MenuType<GenericContainerScreenHandler>, syncId, inventory, this.inventory, 3), inventory, this.getDisplayName());
  251.         }
  252.        
  253.         public void tick () {
  254.             if (this.active)
  255.                 this.activeTick();
  256.             else
  257.                 this.notifyItemsChanged(-2);
  258.         }
  259.        
  260.         private void activeTick () {
  261.             this.progress++;
  262.             if (this.progress >= targetProgress) {
  263.                 this.active = false;
  264.                 this.progress = 0;
  265.                 this.activeRecipe.assemble(this.inventory);
  266.             }
  267.         }
  268.        
  269.         void notifyItemsChanged (int slotIsh) {
  270.             switch (slotIsh) {
  271.                 case -2:
  272.                     this.active = this.resetActiveRecipes();
  273.                     this.getWorld().updateNeighborsAlways(this.pos, BetterThanWolvesBlocks.CAULDRON);
  274.                     break;
  275.                 case -1:
  276.                     this.getWorld().updateNeighborsAlways(this.pos, BetterThanWolvesBlocks.CAULDRON);
  277.                     break;
  278.                 default:
  279.                     if (Arrays.binarySearch(this.activeItems, slotIsh) & 0x80000000 != 0)
  280.                         this.notifyItemsChanged(-2);
  281.                     else
  282.                         this.getWorld().updateNeighborsAlways(this.pos, BetterThanWolvesBlocks.CAULDRON);
  283.             }
  284.         }
  285.        
  286.         private boolean resetActiveRecipes () {
  287.             List<RecipeHolder<CauldronRecipe>> recipes = new RecipeManager(Registries.REGISTRY.getReadOnlyWrapper()).listAllOfType(CauldronRecipe.TYPE);
  288.             for (RecipeHolder<CauldronRecipe> r : recipes) {
  289.                 if (r.value().test(this.inventory)) {
  290.                     this.activeRecipe = r;
  291.                     this.targetProgress = r.getTickTime();
  292.                     this.progress = 0;
  293.                     return true;
  294.                 }
  295.             }
  296.             return false;
  297.         }
  298.        
  299.         public int firstAvailableSlot (ItemStack item) {
  300.             return Math.min(this.items.indexOf(item), this.items.indexOf(ItemStack.EMPTY));
  301.         }
  302.        
  303.         private class Inventory extends net.minecraft.inventory.Inventory {
  304.             public Inventory () {}
  305.            
  306.             public int size () {
  307.                 return this.super.items.size();
  308.             }
  309.            
  310.             public boolean isEmpty () {
  311.                 return this.super.items.isEmpty();
  312.             }
  313.            
  314.             public ItemStack getStack (int slot) {
  315.                 return this.super.items.get(slot);
  316.             }
  317.            
  318.             public ItemStack removeStack (int slot, int amount) {
  319.                 this.super.notifyItemsChanged(slot);
  320.                 this.super.items.get(slot).shrink(amount);
  321.                 return this.super.items.get(slot);
  322.             }
  323.            
  324.             public ItemStack removeStack (int slot) {
  325.                 this.super.notifyItemsChanged(slot);
  326.                 return this.super.items.remove(slot);
  327.             }
  328.            
  329.             public void setStack (int slot, ItemStack item) {
  330.                 this.super.notifyItemsChanged(slot);
  331.                 this.super.items.set(slot, item);
  332.             }
  333.            
  334.             public void markDirty () {
  335.                 this.super.notifyItemsChanged(-1);
  336.             }
  337.            
  338.             public boolean canPlayerUse (PlayerEntity player) {
  339.                 return net.minecraft.inventory.Inventory.canPlayerUse(this.super, player, 5.0F);
  340.             }
  341.            
  342.             public Stream<ItemStack> stream () {
  343.                 return this.super.items.stream();
  344.             }
  345.            
  346.             public CauldronBlock.BlockEntity getOwner () {
  347.                 return this.super;
  348.             }
  349.            
  350.             public DetachedInventory detachedCopy () {
  351.                 return new DetachedInventory(List.<ItemStack>copyOf(this.super.items));
  352.             }
  353.            
  354.             public static class DetachedInventory extends CauldronBlock.BlockEntity.Inventory {
  355.                 public DetachedInventory (ItemStack items) {
  356.                     this.list = items;
  357.                 }
  358.                
  359.                 public int size () {
  360.                     return this.list.size();
  361.                 }
  362.                
  363.                 public boolean isEmpty () {
  364.                     return this.list.isEmpty();
  365.                 }
  366.                
  367.                 public ItemStack getStack (int slot) {
  368.                     return this.list.get(slot);
  369.                 }
  370.                
  371.                 public ItemStack removeStack (int slot, int amount) {
  372.                     this.list.get(slot).shrink(amount);
  373.                     return this.list.get(slot);
  374.                 }
  375.                
  376.                 public ItemStack removeStack (int slot) {
  377.                     return this.list.remove(slot);
  378.                 }
  379.                
  380.                 public void setStack (int slot, ItemStack item) {
  381.                     this.list.set(slot, item);
  382.                 }
  383.                
  384.                 public void markDirty () {}
  385.                
  386.                 public boolean canPlayerUse (PlayerEntity player) {
  387.                     return true;
  388.                 }
  389.                
  390.                 public Stream<ItemStack> stream () {
  391.                     return this.list.stream();
  392.                 }
  393.                
  394.                 public CauldronBlock.BlockEntity getOwner () {
  395.                     return null;
  396.                 }
  397.            
  398.                 public DetachedInventory detachedCopy () {
  399.                     return new DetachedInventory(List.<ItemStack>copyOf(this.list));
  400.                 }
  401.             }
  402.         }
  403.     }
  404. }
  405.  
  406. public class CauldronRecipe implements Recipe<DefaultedList<ItemStack>> {
  407.     public static final RecipeType<CauldronRecipe> TYPE = RecipeType.register("btwce:cauldron_cooking");
  408.    
  409.     private DefaultedList<ItemStack> items;
  410.     private ItemStack result;
  411.     private DefaultedList<ItemStack> remainders;
  412.     private int time;
  413.    
  414.     public CauldronRecipe (DefaultedList<ItemStack> inputs, ItemStack output, DefaultedList<ItemStack> remainders, int time) {
  415.         this.items = inputs;
  416.         this.result = output;
  417.         this.remainders = remainders;
  418.         this.time = time;
  419.     }
  420.    
  421.     @Override
  422.     public boolean matches (DefaultedList<ItemStack> inputs, World world) {
  423.         return this.items.equals(inputs);
  424.     }
  425.    
  426.     @Override
  427.     public ItemStack assemble (DefaultedList<ItemStack> inputs, RegistryWrapper.WrapperLookup registry) {
  428.         return this.result;
  429.     }
  430.    
  431.     @Override
  432.     public boolean fits (int width, int height) {
  433.         return width >= 9 && height >= 3;
  434.     }
  435.    
  436.     @Override
  437.     public ItemStack getResultItem (RegistryWrapper.WrapperLookup registry) {
  438.         return this.result;
  439.     }
  440.    
  441.     @Override
  442.     public ItemStack getRemainder (DefaultedList<ItemStack> inputs) {
  443.         return this.result;
  444.     }
  445.    
  446.     @Override
  447.     public Serializer getSerializer () {
  448.         return new Serializer();
  449.     }
  450.    
  451.     @Override
  452.     public RecipeType<CauldronRecipe> getType () {
  453.         return TYPE;
  454.     }
  455.    
  456.     public boolean test (CauldronBlock.BlockEntity.Inventory inventory) {
  457.         try {
  458.             return this.assemble(inventory.detachedCopy());
  459.         } catch (NullPointerException npe) {
  460.             return true;
  461.         }
  462.     }
  463.    
  464.     public boolean assemble (CauldronBlock.BlockEntity.Inventory inventory) {
  465.         List<Integer> slots = List.<Integer>of();
  466.         DefaultedList<Item> itemSs = this.getItems();
  467.         for (ItemStack i : inventory.stream().toList())
  468.             if (itemSs.contains(i.getItem()))
  469.                 slots.add(Integer.valueOf(inventory.stream().toList().indexOf(i)));
  470.         if (slots.size() != itemSs.size()) return false;
  471.         for (Integer i : slots)
  472.             inventory.removeStack(i.toString(), this.items.get(itemSs.indexOf(inventory.getItem(i.intValue()).getItem())).getCount());
  473.         ItemStack resultCopy = this.result.copy();
  474.         for (ItemStack i : inventory.stream().toList()) {
  475.             if (i.getItem() == resultCopy.getItem()) {
  476.                 if (i.getCount() + resultCopy.getCount() <= i.getMaxStackSize()) {
  477.                     inventory.setItem(inventory.stream().toList().indexOf(i), i.grow(resultCopy.getCount()));
  478.                 } else {
  479.                     resultCopy.setCount(i.getCount() + resultCopy.getCount() - i.getMaxStackSize());
  480.                     inventory.setItem(inventory.stream().toList().indexOf(i), i.setCount(i.getMaxStackSize()));
  481.                 }
  482.             }
  483.         }
  484.         if (resultCopy.getCount() != 0) Block.dropStack(inventory.getOwner().getWorld(), inventory.getOwner().getPos(), Direction.UP, resultCopy);
  485.         return true;
  486.     }
  487. }
Add Comment
Please, Sign In to add comment