Outdated: Creating your own sound engine (for AS 2) - CreativeMD/AmbientSounds GitHub Wiki

Setting up your own engine

AmbientSounds 2 offers you to create your own configuration. From small changes to complete different scenarios, everything is possible. The library might be expanded even further if people request so.

This tutorial should introduce you into the system. The original from AmbientSounds engine can be found here. You can replace it by using a resourcepack which includes aassets/ambientsounds/engine.json file and share it with your friends (or include it in your modpack). You can also send it to me, so I can add it to my curseforge page. Anyway let's get started.

Types

If you are not known to the basics of programming or have never worked with json this might be interesting for you:

  • Integer
    • A "whole" number. Examples: ..,-3,-2,-1,0,1,2,3,...
  • Boolean
    • true or false
  • Float
    • a decimal number
  • String
    • text in quotes. Example: "A random text"
  • Array
    • basically multiple things within brackets separated by a comma. Example: [ "first random text", "second", "something else" ]
  • Equations
    • Every part starts with either =, >, >=, < or <= followed by a number. There can be multiple parts, but all of them have to to be separated by a &. The given number will be compared to the property. Example: "temperature": ">0.5&<=1". In our example the temperature of the biome is 0.75, which will produce the following condition: If 0.75 is greater than 0.5 and smaller or equal than 1 return true.

Dimensions

This is the first layer of the engine. It determines the general environment settings. Vanilla minecraft has 3 dimensions (the end, hell (Nether) and overworld), but it also possible to support mod added ones.

Selectors

Only one dimension can be active at the same time. AmbientSounds will go through each of your specified dimensions (in the same order as you wrote them) and check if they are selected or not.

Currently there is only one selector you can add to your dimension:

  • id (integer, integer array): will be active if the current dimension (of minecraft) equals the specified number (you can also define multiple ids as an array like so: "id": [ 0, 1, 3 ],). Hell: -1, Overworld: 0, The End: 1

If you have not specified any selector, the dimension will always be active if none of the ones before are active. The default engines uses this, so all dimension which don't have an id of -1 or 1 will be treated as an overworld dimensions.

Properties

  • name (string): A unique identifier for the dimension, useful to keep everything organised
  • rain (boolean): True means it is always raining, while false means it is never raining. Used for Hell and The End.
  • storm (boolean): True means it is always storming, while false means it is never storming. Used for Hell and The End.
  • average-height (float): Will set the average-height to a constant number. The average-height is the distance between the player and the surface. Used for Hell and The End to avoid cave sounds by setting it to zero, which means the player is always standing on the top.
  • biome-selector (ambient-selector): Selectors will be explained down here. The selector will determine if the biome properties are active and what volume multiplicator they have. Normally you want it to be the region surface.

Example

  "dimensions": [
    {
      "name": "nether",
      "id": -1,
      "rain": false,
      "storm": false,
      "average-height": 0
    },
    {
      "name": "the end",
      "id": 1,
      "rain": false,
      "storm": false,
      "average-height": 0
    }, 
    {
      "name": "surface",
      "biome-selector": {
        "regions": [ "surface" ]
      }
    }
  ],

Regions (ambient selector)

Regions are the second layer and should help you to group areas of the game in a sensible way. Every region requires a unique name as shown below.

Examples

To prevent any sort of confusion let me show you a few examples:

  "regions": [
    {
      "name": "jungle",
      "biomes": [ "jungle", "sacred springs", "tropical", "bamboo forest", "encalyptus forest", "overgrown cliffs" ],
      "temperature": ">0.5"
    },
    {
      "name": "surface",
      "position": {
        "relativePosition": ">=-10&<=20",
        "fadeValue": "5"
      }
    },
    {
      "name": "plains",
      "variants": [
        {
          "biomes": [ "plains", "chaparral", "fen", "field", "flower", "grass", "oasis", "tundra", "mushroom island", "darklands" ],
          "bad-regions": [ "forest", "savanna" ]
        },
        {
          "top-block": "minecraft:grass",
          "treesPerChunk": "<=4",
          "bad-regions": [ "ocean", "forest", "savanna", "highland", "nether" ]
        }
      ]
    },
  ],

Ambient-Selectors

Ambient-Selectors are properties which can be used to determine if a region, dimension biome-selector or sounds are active or not.

Bound to biome

AmbientSounds will scan all biomes around the player (if the biome is further away the volume will be decreased). All of the following properties are depending on biomes.

Additionally, the biome-selector of the dimension will determine if biomes properties can be active and which volume modifier they will have. In our example the overworld (surface) has a biome-selector bound to the region surface, which means none of biomes will not be active if the player is standing in a cave or flying above the earth. Most likely you don't have to change anything about that, so just ignore it if you don't need it.

  • top-block (string): The top block of a biome. Examples: plains, forest, savanna have minecraft:grass, while desert has minecraft:sand as a top block.
  • treesPerChunk (equations): How many trees a biome will generate per tree. Useful to separate a forest from other biomes.
  • temperature (equations): Might be useful to take a look at Minecraft Wiki to find out the temperature of a specific biome.
  • biomes (string array): This will check if the name of the biome contains any of the specified strings. Placeholder symbol * is allowed as well (used for ExtremeHills). Examples can be found above.
  • bad-biomes (string array): If the player is not inside in any of the given biome (works in the same way as biomes).
  • dimensions (string/integer array): Checks for the dimension name or the dimension id and will return true if the player is in any of the given dimensions.
  • bad-dimensions (string/integer array): Checks for the dimension name or the dimension id and will return false if the player is in any of the given dimensions.

Miscellaneous

  • regions (string array): _Required regions which need to be active. _
  • bad-regions (string array): All of the specified regions have to be inactive.
  • isStorming (boolean): If true it will be active if it is storming and inactive if it is not storming, if false it will be the other way around.
  • isRaining (boolean): If true it will be active if it is raining and inactive if it is not raining, if false it will be the other way around.
  • underwater (boolean): If true it will be active if the player is underwater and inactive if the player is not underwater, if false it will be the other way around.
  • underwater-pitch (object): Allows you to pitch a sound depending on how deep underwater the player is.
    • min (float): Default is 0.5. The lowest pitch value possible.
    • max (float): Default is 2. The highest> pitch value possible.
    • pitchPerBlock (float): Default is 0.3. Rate at which the pitch will change depending on the depth (per block).
  • position: The surface region can be used as an example.
    • relativePosition (integer): The relative height to the surface (it will be zero if the player is standing on the surface, negative if he is in a cave and positive if he is in the air). Height is measured in blocks.
    • absolutePosition (integer): The absolute y coordinate of the player. A Minecraft world goes from 0 to 255. Height is measured in blocks.
    • fadeValue (float):
  • variants (ambient selector array): An array of more selectors. Can be useful if there are more ways to describe one area as shown in the plains region above. If one of these variants are active this property will be active as well.

Sounds

Sounds are the third and last layer of the engine.

Properties

  • source (string): Can be any kind of source (also minecraft vanilla ones).
  • selector (ambient-selector, ambient-selector array): Can either be just one ambient-selector or multiple (as shown below)
  • volume (float): Volume multiplicator. A decimal number in between 0.0 and 1.0.
  • day (float): Volume multiplicator if it is day. A decimal number in between 0.0 and 1.0.
  • night (float): Volume multiplicator if it is night. A decimal number in between 0.0 and 1.0.
  • full (boolean): If the sound is full, it will consume the biome for every other full sounds. Meaning they can't use this biome anymore. Used to make sure only one bird sound will be played at a time.
  • minPause (integer): The sound will still loop, but pause for the given time. This is the minimum pause time. Time is measured in ticks.
  • maxPause (integer): The sound will still loop, but pause for the given time. This is the maximum pause time. Time is measured in ticks.
  • fade (float): Default is 0.002. The sound will increase/ decrease it's volume by this given amount.
  • fadeIn (float): Default is 0.002. The sound will increase it's volume by this given amount. If this property does not exists the fade value will be taken instead.
  • fadeOut (float): Default is 0.002. The sound will decrease it's volume by this given amount. If this property does not exists the fade value will be taken instead.

Examples

  "sounds": [
    {
      "source": "ambientsounds:suspense.cave",
      "selector": {
        "regions": [ "cave" ]
      },
      "full": true
    },
    {
      "source": "ambientsounds:water.beach",
      "selector": {
        "regions": [ "beach" ],
        "temperature": ">0"
      },
      "volume": 0.3,
      "full": true
    },
    {
      "source": "ambientsounds:animals.wolf.wolf",
      "selector": {
        "regions": [ "plains", "savanna" ],
        "temperature": ">1&<=2"
      },
      "minPause": 10,
      "maxPause": 200,
      "day": 0,
      "night": 1
    }
  ]

Those properties can also be added to one of the selectors, so they will be applied if those are active. Note that the engine does not try to find the best solution possible, but instead only takes the first one which returns true.

  "sounds": [
    {
      "source": "ambientsounds:animals.cricket.cricket",
      "selector": [
        {
          "regions": [ "plains", "savanna" ],
          "temperature": ">0.1&<=1.5"
        },
        {
          "regions": [ "forest" ],
          "temperature": ">0.1&<=1.5",
          "volume": 0.5
        }
      ],    
      "day": 0.23,
      "night": 0.10
    }
  ]

Last words

Again I highly recommend to take a look at the original engine. If you want to report any mistake or if you have some ideas how i could improve this tutorial feel free to tell me them. Anyway hope I could explain you how to create your own engine and I wish you a lot of fun experimenting with the system.