Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

How to set texture for dynamically registered blocks from already existing blocks [1.18.2]


X-Lomir
 Share

Recommended Posts

Which maps are you talking about?

5 minutes ago, X-Lomir said:

Also I'm wondering why on the Forge docs it's written to use a separate class when creating a simple channel object. Wouldn't it be okay if I did it in my JustVerticalSlabsLoader?

Just a matter of code style. You can put it wherever you want, really.

Link to comment
Share on other sites

  • Replies 150
  • Created
  • Last Reply

Top Posters In This Topic

10 minutes ago, diesieben07 said:

Which maps are you talking about?

The volatile immutable slab maps used to go from block to slab and vice versa, the ones instantiated in the ServerAboutToStart event.

Link to comment
Share on other sites

Just now, diesieben07 said:

Why do you need them on the client?

Because I actually use them also to render. I had changed my code to make so that my vertical slabs refer the slab and not the block to fix some issues, however this caused some problems in rendering. So I needed the maps during rendering to go from slab to block whenever possible, and also I have a map holding all the translucent slabs.

Link to comment
Share on other sites

So the server will have them after ServerAboutToStart event fired, after on the client the RecipesUpdated event will fire and there I can send a request to the server to get the values for my maps. Correct?

Link to comment
Share on other sites

Okay, now it works without crashing and without major inconveniences. However I found two issues:

  1. Vertical slabs don't show up in the creative inventory, neither the dedicated tab nor the search tab.
  2. In the stonecutter menu the recipes are there but they are not visible, resulting in a shift of the visual recipes compared to the actual output recipe.

They most probably originate from the same problem, that is when I compute the maps I use ForgeRegistries.ITEMS.tags().getTag(ItemTags.SLABS), but this returns null. This is because in ForgeRegistryTagManager I can see the field tags being a map with size 0, client side.

I'm guessing it's because Minecraft registries, and the same Forge registries, are only server side. However I'm not sure what to do to get the Item list of slabs client side.

Link to comment
Share on other sites

However if I compute my maps during that event I won't have access to the recipe manager anymore, am I right?

Also, other than the recipe manager, I need my maps to be computed before I do

MutableSearchTree<ItemStack> creativeSearchTree = Minecraft.getInstance().getSearchTree(SearchRegistry.CREATIVE_NAMES);
for(BlockState referredSlabState : VerticalSlabUtils.slabStateMap.values()) {
  creativeSearchTree.add(VerticalSlabUtils.getVerticalSlabItem(referredSlabState, VerticalSlabUtils.isTranslucent(referredSlabState)));
}
creativeSearchTree.refresh();

during the RecipesUpdateEvent.

Link to comment
Share on other sites

  • 2 weeks later...

I'm actually working on a similar kind of mod, that adds vertical slabs. I made them so they can connect like stairs.

GitHub Branch

Now I have a "Connectable_Oak_Leaf_Wall" that get's registered in my ModBuildingBlocks Class.

The Forge Documentation on tinting is pretty minimalistic: https://mcforge.readthedocs.io/en/1.18.x/resources/client/models/tinting/#blockcoloritemcolor

So I call this in my Main:

unknown.png

Why does it not work? I'm obviously doing something very wrong since you wrote like 30 lines to change the color. But since your Half Slabs probably are getting created in a very different way I thought maybe you could help?

Link to comment
Share on other sites

11 minutes ago, Brainterminator said:

I'm actually working on a similar kind of mod, that adds vertical slabs. I made them so they can connect like stairs.

GitHub Branch

Now I have a "Connectable_Oak_Leaf_Wall" that get's registered in my ModBuildingBlocks Class.

The Forge Documentation on tinting is pretty minimalistic: https://mcforge.readthedocs.io/en/1.18.x/resources/client/models/tinting/#blockcoloritemcolor

So I call this in my Main:

unknown.png

Why does it not work? I'm obviously doing something very wrong since you wrote like 30 lines to change the color. But since your Half Slabs probably are getting created in a very different way I thought maybe you could help?

That register method takes as first parameter a instance of BlockColor, you are passing it an int (FoliageColor#getDefaultColor returns an int).

A BlockColor instance is quite easy as BlockColor is just an interface with a single method:

public interface BlockColor {
   int getColor(BlockState p_92567_, @Nullable BlockAndTintGetter p_92568_, @Nullable BlockPos p_92569_, int p_92570_);
}

Since you basically want to copy the coloring foliage gets, you can do something similar to me:

@SubscribeEvent
public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
  event.getBlockColors().register(
    new BlockColor() {
      public int getColor(BlockState state, @Nullable BlockAndTintGetter getter, @Nullable BlockPos pos, int tintIndex) {
        return getter != null && pos != null ? event.getBlockColors().getColor(Blocks.OAK_LEAVES.defaultBlockState(), getter, pos, tintIndex) : -1;
      }
    },
    ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL
  );
}

Where you basically create a new BlockColor instance that returns the same coloring for oak leaves.

Alternatively you can also create a separate class implementing BlockColor:

public class ConnectableOakLeafWallBlockColor implements BlockColor {
  public int getColor(BlockState state, @Nullable BlockAndTintGetter getter, @Nullable BlockPos pos, int tintIndex) {
    return getter != null && pos != null ? Minecraft.getInstance().getBlockColors().getColor(Blocks.OAK_LEAVES.defaultBlockState(), getter, pos, tintIndex) : -1;
  }
}

And just pass it to register:

@SubscribeEvent
public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
  event.getBlockColors().register(new ConnectableOakLeafWallBlockColor(), ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL);
}

The choice is yours.

 

Also be careful because you need to avoid having this part of the code when your mod runs only server-side or it will just crash being unable to find BlockColor (which indeed exists only client-side). I fixed this problem by having a separate class handling my color registering annotated like so (be careful to make your methods static if you do the same):

@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD)
public class ColorHandlerEventHandler {

  @SubscribeEvent
  public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
    // do stuff
  }

  @SubscribeEvent
  public static void onColorHandlerEventItem(ColorHandlerEvent.Item event) {
    // do stuff
  }
}

I speak from experience 🤣

I hope I was of help, if you need to look more at my code the most updated branch is this one.

Link to comment
Share on other sites

Posted (edited)
2 hours ago, X-Lomir said:

That register method takes as first parameter a instance of BlockColor, you are passing it an int (FoliageColor#getDefaultColor returns an int).

A BlockColor instance is quite easy as BlockColor is just an interface with a single method:

public interface BlockColor {
   int getColor(BlockState p_92567_, @Nullable BlockAndTintGetter p_92568_, @Nullable BlockPos p_92569_, int p_92570_);
}

Since you basically want to copy the coloring foliage gets, you can do something similar to me:

@SubscribeEvent
public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
  event.getBlockColors().register(
    new BlockColor() {
      public int getColor(BlockState state, @Nullable BlockAndTintGetter getter, @Nullable BlockPos pos, int tintIndex) {
        return getter != null && pos != null ? event.getBlockColors().getColor(Blocks.OAK_LEAVES.defaultBlockState(), getter, pos, tintIndex) : -1;
      }
    },
    ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL
  );
}

Where you basically create a new BlockColor instance that returns the same coloring for oak leaves.

Alternatively you can also create a separate class implementing BlockColor:

public class ConnectableOakLeafWallBlockColor implements BlockColor {
  public int getColor(BlockState state, @Nullable BlockAndTintGetter getter, @Nullable BlockPos pos, int tintIndex) {
    return getter != null && pos != null ? Minecraft.getInstance().getBlockColors().getColor(Blocks.OAK_LEAVES.defaultBlockState(), getter, pos, tintIndex) : -1;
  }
}

And just pass it to register:

@SubscribeEvent
public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
  event.getBlockColors().register(new ConnectableOakLeafWallBlockColor(), ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL);
}

The choice is yours.

 

Also be careful because you need to avoid having this part of the code when your mod runs only server-side or it will just crash being unable to find BlockColor (which indeed exists only client-side). I fixed this problem by having a separate class handling my color registering annotated like so (be careful to make your methods static if you do the same):

@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD)
public class ColorHandlerEventHandler {

  @SubscribeEvent
  public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
    // do stuff
  }

  @SubscribeEvent
  public static void onColorHandlerEventItem(ColorHandlerEvent.Item event) {
    // do stuff
  }
}

I speak from experience 🤣

I hope I was of help, if you need to look more at my code the most updated branch is this one.

First of all, thank you so much for your quick and detailed reply!!!

A lot of things got a lot clearer to me but my blocks still are rendered in gray. I don't get why and when I wanted to look into your code I realized there are no tinted blocks in your mod.

At least I couldn't find any leaves slabs or grass slabs so I'm still a little lost but your answer was by far the best I got in the last 2 weeks I spent trying to find a solution to this problem

 

p.s.: I just realised I'm stupid and I forgot to call it in the Main Constructor ..... sigh

Edited by Brainterminator
Link to comment
Share on other sites

2 hours ago, Brainterminator said:

I don't get why and when I wanted to look into your code I realized there are no tinted blocks in your mod.

Yeah I know, this is because Minecraft Vanilla doesn't have slabs of such materials, so in Vanilla no vertical slabs will have a need for coloring. However if you try my mod in combination with another mod that adds horizontal slabs of grass or foliage or whatever other block that needs coloring you will see that the vertical slabs will appear and will be tinted correctly :)

I'm glad you could figure out the other problem anyway

Link to comment
Share on other sites

56 minutes ago, X-Lomir said:

Yeah I know, this is because Minecraft Vanilla doesn't have slabs of such materials, so in Vanilla no vertical slabs will have a need for coloring. However if you try my mod in combination with another mod that adds horizontal slabs of grass or foliage or whatever other block that needs coloring you will see that the vertical slabs will appear and will be tinted correctly :)

I'm glad you could figure out the other problem anyway

In case of the Server How did you workaround that? I heard you can use the DistExecutor but lambda expression still overwhelm me so... I'm having problems with that.

My Constructor looks like this:

public UtilityBlocks()
    {
        IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus();

        ModItems.register(eventBus);
        ModBlocks.register(eventBus);
        ModBuildingBlocks.register(eventBus);

        eventBus.addListener(this::setup);
        eventBus.addListener(this::clientSetup);

        
        eventBus.addListener(this::registerBlockColors);
        eventBus.addListener(this::registerItemColors);

        // Register ourselves for server and other game events we are interested in
        MinecraftForge.EVENT_BUS.register(this);
    }

But as you already said this way it is not runnable on a server. Do you know an easy way to outsource that?

Link to comment
Share on other sites

13 minutes ago, Brainterminator said:

In case of the Server How did you workaround that? I heard you can use the DistExecutor but lambda expression still overwhelm me so... I'm having problems with that.

My Constructor looks like this:

public UtilityBlocks()
    {
        IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus();

        ModItems.register(eventBus);
        ModBlocks.register(eventBus);
        ModBuildingBlocks.register(eventBus);

        eventBus.addListener(this::setup);
        eventBus.addListener(this::clientSetup);

        
        eventBus.addListener(this::registerBlockColors);
        eventBus.addListener(this::registerItemColors);

        // Register ourselves for server and other game events we are interested in
        MinecraftForge.EVENT_BUS.register(this);
    }

But as you already said this way it is not runnable on a server. Do you know an easy way to outsource that?

As I said in my first reply, what I did was to directly subscribe a class that would handle the color events:

@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD)
public class ColorHandlerEventHandler {

  @SubscribeEvent
  public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
    // do stuff
  }

  @SubscribeEvent
  public static void onColorHandlerEventItem(ColorHandlerEvent.Item event) {
    // do stuff
  }
}

The important parts here are the Annotation for the class and the fact that its methods are static. If you do this you should also remove the lines in your constructor where you add those methods as listeners on the bus.

So, to sum it up, remove the lines that register registerBlockColors and registerItemColors, move those two methods into a separate class and make them static, annotate the class with @EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD) and you're good to go.

Link to comment
Share on other sites

4 minutes ago, X-Lomir said:

As I said in my first reply, what I did was to directly subscribe a class that would handle the color events:

@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD)
public class ColorHandlerEventHandler {

  @SubscribeEvent
  public static void onColorHandlerEventBlock(ColorHandlerEvent.Block event) {
    // do stuff
  }

  @SubscribeEvent
  public static void onColorHandlerEventItem(ColorHandlerEvent.Item event) {
    // do stuff
  }
}

The important parts here are the Annotation for the class and the fact that its methods are static. If you do this you should also remove the lines in your constructor where you add those methods as listeners on the bus.

So, to sum it up, remove the lines that register registerBlockColors and registerItemColors, move those two methods into a separate class and make them static, annotate the class with @EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD) and you're good to go.

I tried replicating your steps with my mod:

package net.brain.utilityblocks.handler;

import net.brain.utilityblocks.block.ModBuildingBlocks;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.world.level.FoliageColor;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.api.distmarker.Dist;

@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD)
public class ColorHandlerEventHandler {
    @SubscribeEvent
    public void registerBlockColors(ColorHandlerEvent.Block event){
        event.getBlockColors().register((p_92626_, p_92627_, p_92628_, p_92629_) -> {
            return p_92627_ != null && p_92628_ != null ? BiomeColors.getAverageFoliageColor(p_92627_, p_92628_) : FoliageColor.getDefaultColor();
        }, ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL.get());
    }

    @SubscribeEvent
    public void registerItemColors(ColorHandlerEvent.Item event){
        event.getItemColors().register(new ItemColor() {
            @Override
            public int getColor(ItemStack pStack, int pTintIndex) {
                return FoliageColor.getDefaultColor();
            }
        }, ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL.get());
    }
}

but somehow it doesn't work. When I declare the registerBlockColors function in my Main Class and call "eventBus.addListener(this::registerBlockColors);" from the Constructor it works. 

 

Link to comment
Share on other sites

1 minute ago, Brainterminator said:

I tried replicating your steps with my mod:

package net.brain.utilityblocks.handler;

import net.brain.utilityblocks.block.ModBuildingBlocks;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.world.level.FoliageColor;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.api.distmarker.Dist;

@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.MOD)
public class ColorHandlerEventHandler {
    @SubscribeEvent
    public void registerBlockColors(ColorHandlerEvent.Block event){
        event.getBlockColors().register((p_92626_, p_92627_, p_92628_, p_92629_) -> {
            return p_92627_ != null && p_92628_ != null ? BiomeColors.getAverageFoliageColor(p_92627_, p_92628_) : FoliageColor.getDefaultColor();
        }, ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL.get());
    }

    @SubscribeEvent
    public void registerItemColors(ColorHandlerEvent.Item event){
        event.getItemColors().register(new ItemColor() {
            @Override
            public int getColor(ItemStack pStack, int pTintIndex) {
                return FoliageColor.getDefaultColor();
            }
        }, ModBuildingBlocks.CONNECTABLE_OAK_LEAF_WALL.get());
    }
}

but somehow it doesn't work. When I declare the registerBlockColors function in my Main Class and call "eventBus.addListener(this::registerBlockColors);" from the Constructor it works. 

 

I told you, the methods need to be static. This is because with the annotation you're subscribing the class, not an instance of it.

Quote from @diesieben07: "@EventBusSubscriber registers the class to the event bus, as such your event handler methods must be static."

Quotes from me: "be careful to make your methods static if you do the same", "The important parts here are the Annotation for the class and the fact that its methods are static", "move those two methods into a separate class and make them static".

Link to comment
Share on other sites

Posted (edited)
30 minutes ago, X-Lomir said:

I told you, the methods need to be static. This is because with the annotation you're subscribing the class, not an instance of it.

Quote from @diesieben07: "@EventBusSubscriber registers the class to the event bus, as such your event handler methods must be static."

Quotes from me: "be careful to make your methods static if you do the same", "The important parts here are the Annotation for the class and the fact that its methods are static", "move those two methods into a separate class and make them static".

First of all thank you for all your help I have been stuck with this for a while! 
Okay so the @EventBusSubscriber makes it so I don't have to call the method, Forge automatically does?

 

EDIT: THANK YOU SO MUCH NOW EVERYTHING WORKS FINE!
YOU'RE A GOD DAMN LEGEND

Edited by Brainterminator
Fixed it!
Link to comment
Share on other sites

11 minutes ago, Brainterminator said:

First of all thank you for all your help I have been stuck with this for a while! 
Okay so the @EventBusSubscriber makes it so I don't have to call the method, Forge automatically does?

Yep. Instead of telling Forge a specific method needs to be called upon a certain event (which is what you were doing in the constructor) you're telling Forge to register that class (not instance, so only the static fields) to the event bus. Then, by adding @SubscribeEvent and the type of the event as parameter to the methods Forge will know that it has to call them upon the specified event.

By the way if you think about it you're never calling any method you register to the event listeners (this::methodName passed the method as parameter, doesn't call it), you're instead passing them as parameter so that Forge knows what to call and when. The key difference is that in the constructor you're registering the methods to the event bus by calling IEventBus#addListener, instead with the separate class you're using annotations to do it.

I am glad I was of help and I hope this explanation was helpful too.

Link to comment
Share on other sites

28 minutes ago, X-Lomir said:

Yep. Instead of telling Forge a specific method needs to be called upon a certain event (which is what you were doing in the constructor) you're telling Forge to register that class (not instance, so only the static fields) to the event bus. Then, by adding @SubscribeEvent and the type of the event as parameter to the methods Forge will know that it has to call them upon the specified event.

By the way if you think about it you're never calling any method you register to the event listeners (this::methodName passed the method as parameter, doesn't call it), you're instead passing them as parameter so that Forge knows what to call and when. The key difference is that in the constructor you're registering the methods to the event bus by calling IEventBus#addListener, instead with the separate class you're using annotations to do it.

I am glad I was of help and I hope this explanation was helpful too.

It definitely was! Thank you so much again! It was also really helpful to get it explained for once! I was also on a discord and when I asked them about it they were like "just use lambda", " if you don't even understand this don't even bother making a mc mod"

Link to comment
Share on other sites

  • 1 month later...
Posted (edited)

@diesieben07I have a new bug that I can't understand why it's happening. For a bit of context, I added the feature of double vertical slabs, similar to double slabs. However the bug happens when a vertical slab that emits lights becomes double: at that point it stops emitting light.

Normal vertical slab just placed: https://imgur.com/a/QCXa16B

Double vertical slab just placed: https://imgur.com/i43sHvt

And as you can see in both cases the level property stays to 15, however when it's double light is not emitted, not even after updating the chunk.

The relevant code is the following:

public BlockState getStateForPlacement(BlockPlaceContext placeContext) {
  BlockPos pos = placeContext.getClickedPos();
  Level level = placeContext.getLevel();
  BlockState referredSlabState = VerticalSlabUtils.getReferredSlabState(placeContext.getItemInHand());
  // if item in hand and block clicked on have the same referredSlabStates, then they are both the same kind of vertical slabs
  if (referredSlabState == VerticalSlabUtils.getReferredSlabState(level, pos)) {
    BlockState blockstate = this.defaultBlockState().setValue(WATERLOGGED, false).setValue(DOUBLE, true);
    if (referredSlabState != null) {
      BlockState referredBlockState = VerticalSlabUtils.getReferredBlockState(referredSlabState);
      BlockState referredState = referredBlockState != null ? referredBlockState : referredSlabState;
      blockstate = blockstate
        .setValue(LEVEL, getReferredProperty(referredState::getLightEmission, referredState::getLightEmission, level, pos)) // Set the level property exactly as below
        .setValue(OCCLUSION, referredState.useShapeForLightOcclusion());
    }
    return blockstate;
  } else {
    BlockState blockstate = this.defaultBlockState().setValue(FACING, placeContext.getHorizontalDirection()).setValue(WATERLOGGED, level.getFluidState(pos).getType() == Fluids.WATER);
    if (referredSlabState != null) {
      BlockState referredBlockState = VerticalSlabUtils.getReferredBlockState(referredSlabState);
      blockstate = blockstate
        .setValue(LEVEL, getReferredProperty(referredSlabState::getLightEmission, referredSlabState::getLightEmission, level, pos)) // Setting the level property like this works for normal vertical slabs
        .setValue(OCCLUSION, (referredBlockState != null ? referredBlockState : referredSlabState).useShapeForLightOcclusion());
    }
    return blockstate.setValue(SHAPE, getStairsShape(blockstate, level, pos)).setValue(DOUBLE, false);
  }
}
public VerticalSlabBlock(Material material) {
  super(
    BlockBehaviour.Properties.of(material)
    .isValidSpawn((state, getter, pos, entityType) -> false)
    .isRedstoneConductor((state, getter, pos) -> false)
    .isSuffocating((state, getter, pos) -> false)
    .lightLevel(LightBlock.LIGHT_EMISSION)
    .dynamicShape()
  );
  this.registerDefaultState(
    this.defaultBlockState()
      .setValue(FACING, Direction.NORTH)
      .setValue(SHAPE, StairsShape.STRAIGHT)
      .setValue(WATERLOGGED, false)
      .setValue(LEVEL, 0)
      .setValue(OCCLUSION, false)
      .setValue(DOUBLE, false)
  );
}

If there's any other part of the code that's needed let me know, anyway as always here you can find the whole repo.

Edited by X-Lomir
Misclicked when posted the first time and updated code snippets.
Link to comment
Share on other sites

If it's needed to test it out, you can just hardcode the LEVEL values in both methods to 15, removing the 0 in the constructor and removing the calls to getReferredProperty.

Btw getReferredProperty I'm sure works fine because it works with normal vertical slabs and it keeps the correct light level for double vertical slabs, and anyway the bug is still there even when hardcoding 15.

I really have no clue on why this happens, it's the last bug I have to fix before I can release a new stable version and I've been trying to solve this for days and I made no progress 😅

Link to comment
Share on other sites

Update:

I discovered that it's not just a bug of double vertical slabs, it affects also normal vertical slabs.

The actual bug is the following: "external" faces (faces that align with the edge of the block) do not emit light, only "internal" (faces within the block) do.

Here a couple of images to better understand the situation: https://imgur.com/a/ryaevWb (I used the hardcoding trick explained before here, that's why a oak slab is emitting light).

So at first I noticed the bug only with double vertical slabs as they are naturally without "internal" faces that can emit light, but upon further inspection this is what the bug actually was.

Honestly I still have no idea on how to fix this, but maybe this new info can help in getting some help 😄

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share




×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.